diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index 09443babc81..32419a0dc31 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -910,6 +910,7 @@ mcumgr MCUs mcux MCUXpresso +MCXW mdash MDNS MediaInput diff --git a/.github/workflows/check-data-model-directory-updates.yaml b/.github/workflows/check-data-model-directory-updates.yaml index ecd7745516b..0c791bebd0d 100644 --- a/.github/workflows/check-data-model-directory-updates.yaml +++ b/.github/workflows/check-data-model-directory-updates.yaml @@ -45,11 +45,6 @@ jobs: run: | scripts/run_in_build_env.sh './scripts/build_python.sh --install_virtual_env out/venv --enable_ble false --extra_packages lxml' - - name: Check for changes to master data_model directory without a SHA update - if: (!contains(github.event.pull_request.labels.*.name, 'data-model-file-structural-change-dm-tt-use-only')) - run: | - scripts/run_in_python_env.sh out/venv 'python3 scripts/dm_xml_ci_change_enforcement.py data_model/master' - - name: Check for changes to 1.3 data_model directory without a SHA update if: (!contains(github.event.pull_request.labels.*.name, 'data-model-file-structural-change-dm-tt-use-only')) run: | diff --git a/.github/workflows/examples-linux-arm.yaml b/.github/workflows/examples-linux-arm.yaml index fb5906a4b7c..2f5067064d6 100644 --- a/.github/workflows/examples-linux-arm.yaml +++ b/.github/workflows/examples-linux-arm.yaml @@ -38,7 +38,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-crosscompile:174 + image: ghcr.io/project-chip/chip-build-crosscompile:182 steps: - name: Checkout diff --git a/.github/workflows/examples-linux-standalone.yaml b/.github/workflows/examples-linux-standalone.yaml index cdd98289243..aae9ea4d2a9 100644 --- a/.github/workflows/examples-linux-standalone.yaml +++ b/.github/workflows/examples-linux-standalone.yaml @@ -38,7 +38,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:174 + image: ghcr.io/project-chip/chip-build:182 steps: - name: Checkout diff --git a/.github/workflows/examples-nxp.yaml b/.github/workflows/examples-nxp.yaml index c9980da1c69..0e98e4fcdcb 100644 --- a/.github/workflows/examples-nxp.yaml +++ b/.github/workflows/examples-nxp.yaml @@ -43,7 +43,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nxp:174 + image: ghcr.io/project-chip/chip-build-nxp:176 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: @@ -73,21 +73,21 @@ jobs: run: | scripts/run_in_build_env.sh "\ ./scripts/build/build_examples.py \ - --target nxp-mcxw71-freertos-contact-sensor-thread-mtd-low-power-cmake-frdm \ + --target nxp-mcxw71-freertos-contact-sensor-thread-mtd-low-power-frdm-ota-factory \ build \ " - name: Get MCXW71 contact sensor size stats run: | .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nxp mcxw71+release contact \ - out/nxp-mcxw71-freertos-contact-sensor-thread-mtd-low-power-cmake-frdm/app.elf \ + out/nxp-mcxw71-freertos-contact-sensor-thread-mtd-low-power-frdm-ota-factory/app.elf \ /tmp/bloat_reports/ - name: Build MCXW72 examples run: | scripts/run_in_build_env.sh "\ ./scripts/build/build_examples.py \ - --target nxp-mcxw72-freertos-contact-sensor-thread-mtd-low-power-cmake-frdm \ + --target nxp-mcxw72-freertos-contact-sensor-thread-mtd-low-power-frdm-ota-factory \ build \ " @@ -101,7 +101,7 @@ jobs: run: | scripts/run_in_build_env.sh "\ ./scripts/build/build_examples.py \ - --target nxp-rt1060-freertos-thermostat-thread-wifi-ota-evkc-iwx12-cmake \ + --target nxp-rt1060-freertos-thermostat-thread-wifi-ota-evkc-iwx12 \ build \ " @@ -115,7 +115,7 @@ jobs: run: | scripts/run_in_build_env.sh "\ ./scripts/build/build_examples.py \ - --target nxp-rt1170-freertos-thermostat-thread-wifi-ota-iwx12-cmake \ + --target nxp-rt1170-freertos-thermostat-thread-wifi-ota-iwx12 \ build \ " @@ -126,15 +126,15 @@ jobs: run: | scripts/run_in_build_env.sh "\ ./scripts/build/build_examples.py \ - --target nxp-rw61x-freertos-thermostat-thread-wifi-ota-factory-cmake \ - --target nxp-rw61x-freertos-thermostat-wifi-se05x-cmake \ + --target nxp-rw61x-freertos-thermostat-thread-wifi-ota-factory \ + --target nxp-rw61x-freertos-thermostat-wifi-se05x \ build \ " - name: Build RW61X thermostat ethernet example app run: | scripts/run_in_build_env.sh "\ ./scripts/build/build_examples.py \ - --target nxp-rw61x-freertos-thermostat-ethernet-cmake-frdm \ + --target nxp-rw61x-freertos-thermostat-ethernet-frdm \ build \ " @@ -153,7 +153,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nxp-zephyr:174 + image: ghcr.io/project-chip/chip-build-nxp-zephyr:176 steps: - name: Checkout diff --git a/.github/workflows/java-tests.yaml b/.github/workflows/java-tests.yaml index c06288f6838..62e1f2303eb 100644 --- a/.github/workflows/java-tests.yaml +++ b/.github/workflows/java-tests.yaml @@ -44,7 +44,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-java:174 + image: ghcr.io/project-chip/chip-build-java:182 options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=0 net.ipv6.conf.all.forwarding=0" diff --git a/.github/workflows/kotlin-style.yaml b/.github/workflows/kotlin-style.yaml index e281d1176d9..d55b050082c 100644 --- a/.github/workflows/kotlin-style.yaml +++ b/.github/workflows/kotlin-style.yaml @@ -13,8 +13,11 @@ concurrency: jobs: + + # This test is currently disabled due to Issue #41932 detekt: name: Static code analysis + if: false runs-on: ubuntu-latest steps: diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 890b0aedca1..70bc3924759 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -63,6 +63,9 @@ jobs: container: image: ghcr.io/project-chip/chip-build:174 + volumes: + - "/:/runner-root-volume" + - "/tmp/log_output:/tmp/test_logs" options: >- --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" @@ -596,7 +599,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build:174 + image: ghcr.io/project-chip/chip-build:182 options: >- --privileged --sysctl net.ipv6.conf.all.disable_ipv6=0 diff --git a/.gitmodules b/.gitmodules index 07cd7d41d23..4028d75f16e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,6 +10,7 @@ path = third_party/mbedtls/repo url = https://github.com/ARMmbed/mbedtls.git branch = mbedtls-2.28 + excluded-platforms = esp32 [submodule "qrcode"] path = examples/common/QRCode/repo url = https://github.com/nayuki/QR-Code-generator.git @@ -50,7 +51,7 @@ path = third_party/freertos/repo url = https://github.com/FreeRTOS/FreeRTOS-Kernel.git branch = V10.3.1-kernel-only - platforms = ameba,cc13xx_26xx,bouffalolab,esp32,infineon,qpg,cc32xx,realtek + platforms = ameba,cc13xx_26xx,bouffalolab,infineon,qpg,cc32xx,realtek [submodule "simw-top-mini"] path = third_party/simw-top-mini/repo url = https://github.com/NXP/plug-and-trust.git @@ -204,6 +205,7 @@ path = third_party/boringssl/repo/src url = https://github.com/google/boringssl.git branch = master + excluded-platforms = esp32 [submodule "third_party/mt793x_sdk/filogic"] path = third_party/mt793x_sdk/filogic url = https://github.com/MediaTek-Labs/genio-matter-bsp.git @@ -300,7 +302,7 @@ [submodule "third_party/lwip/repo"] path = third_party/lwip/repo url = https://github.com/lwip-tcpip/lwip.git - excluded-platforms = darwin + excluded-platforms = darwin,esp32 [submodule "third_party/abseil-cpp/src"] path = third_party/abseil-cpp/src url = https://github.com/abseil/abseil-cpp.git @@ -326,6 +328,7 @@ [submodule "third_party/libtrustymatter/repo"] path = third_party/libtrustymatter/repo url = https://github.com/nxp-imx/libtrustymatter + platforms = nxp [submodule "third_party/amazon-kinesis-video-streams-webrtc-sdk-c/repo"] path = third_party/amazon-kinesis-video-streams-webrtc-sdk-c/repo url = https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-c diff --git a/config/esp32/args.gni b/config/esp32/args.gni index 33de39cfc51..25060a328f2 100644 --- a/config/esp32/args.gni +++ b/config/esp32/args.gni @@ -26,7 +26,6 @@ lwip_platform = "external" #Enabling this causes some error #chip_inet_config_enable_tun_endpoint = false -chip_inet_config_enable_tcp_endpoint = false chip_inet_config_enable_udp_endpoint = true chip_config_memory_management = "platform" diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt index 5fefa91d891..eaa248de1c1 100644 --- a/config/esp32/components/chip/CMakeLists.txt +++ b/config/esp32/components/chip/CMakeLists.txt @@ -121,6 +121,12 @@ if(CONFIG_DISABLE_IPV4) endif() endif() +if(CONFIG_ENABLE_TCP_TRANSPORT) + chip_gn_arg_append("chip_inet_config_enable_tcp_endpoint" "true") +else() + chip_gn_arg_append("chip_inet_config_enable_tcp_endpoint" "false") +endif() + if(CONFIG_DISABLE_READ_CLIENT) chip_gn_arg_append("chip_enable_read_client" "false") endif() @@ -135,7 +141,15 @@ if(CONFIG_ENABLE_ICD_SERVER) chip_gn_arg_append("chip_icd_report_on_active_mode" "true") endif() if(CONFIG_ENABLE_ICD_LIT) - chip_gn_arg_append("chip_enable_icd_lit" "true") + chip_gn_arg_append("chip_enable_icd_lit" "true") + chip_gn_arg_append("chip_enable_icd_checkin" "true") + chip_gn_arg_append("chip_enable_icd_user_active_mode_trigger" "true") + if (CONFIG_ENABLE_ICD_DSLS) + chip_gn_arg_append("chip_enable_icd_dsls" "true") + else() + chip_gn_arg_append("chip_enable_icd_dsls" "false") + endif() + else() if(CONFIG_ENABLE_ICD_CIP) chip_gn_arg_append("chip_enable_icd_checkin" "true") else() diff --git a/config/esp32/components/chip/Kconfig b/config/esp32/components/chip/Kconfig index 5d8f7f2e734..b266a0f75a1 100644 --- a/config/esp32/components/chip/Kconfig +++ b/config/esp32/components/chip/Kconfig @@ -32,7 +32,7 @@ menu "CHIP Core" default 8 help The maximum number of simultaneously active CHIP exchange contexts. - + An exchange context object is used to track the state of an ongoing CHIP message exchange (conversation) with a peer, e.g. a cloud service, a mobile application, or another device. @@ -257,6 +257,14 @@ menu "CHIP Core" Here, we are also enabling LWIP_CHECK_THREAD_SAFETY which will assert when LwIP code gets called from any other context or without holding the LwIP lock. + config USE_LWIP_PBUF_RAM_PACKETBUFFER + bool "Use lwIP PBUF_RAM type for CHIP packet buffer" + default n + help + Enable this option to use lwIP PBUF_RAM type for CHIP packet buffer. Configure via + MAX_LARGE_BUFFER_SIZE_BYTES to support larger packets exceeding IPv6 MTU. + If not enabled, CHIP will use lwIP PBUF_POOL type for packet buffer. + endmenu # "Networking Options" menu "System Options" @@ -285,8 +293,8 @@ menu "CHIP Core" depends on ENABLE_OTA_REQUESTOR default n help - Enable this option for delta OTA image updates. - Delta OTA updates allow for smaller, more efficient updates by only + Enable this option for delta OTA image updates. + Delta OTA updates allow for smaller, more efficient updates by only sending the changes between the current and new firmware versions. config OTA_AUTO_REBOOT_ON_APPLY @@ -447,12 +455,22 @@ menu "CHIP Device Layer" bool "Enable Long Idle Time ICD" depends on ENABLE_ICD_SERVER default n + select ENABLE_ICD_CIP + select ENABLE_ICD_USER_ACTIVE_MODE_TRIGGER help Enables or Disables LIT ICD + config ENABLE_ICD_DSLS + bool "Enable Dynamic SIT LIT Support" + depends on ENABLE_ICD_LIT + default y + help + Enables or Disables dynamic switching from SIT to LIT operating modes. + + config ENABLE_ICD_CIP bool "Enable Check-in protocol" - depends on ENABLE_ICD_LIT + depends on ENABLE_ICD_SERVER default y help Enables or Disables ICD Check-in protocol @@ -480,12 +498,12 @@ menu "CHIP Device Layer" config ENABLE_ICD_USER_ACTIVE_MODE_TRIGGER bool "Enable User Active Mode Trigger feature" - depends on ENABLE_ICD_LIT + depends on ENABLE_ICD_SERVER default y help Enables or Disables ICD User Active Mode Trigger feature - config ENABLE_BG_EVENT_PROCESSING + menuconfig ENABLE_BG_EVENT_PROCESSING bool "Enable Background event processing" default n help @@ -1214,6 +1232,23 @@ menu "CHIP Device Layer" endmenu + menu "Matter TCP transport options" + config ENABLE_TCP_TRANSPORT + bool "Enable TCP transport" + select USE_LWIP_PBUF_RAM_PACKETBUFFER + default n + help + Enable TCP transport. If enabled, USE_LWIP_PBUF_RAM_PACKETBUFFER must be configured. + + config MAX_LARGE_BUFFER_SIZE_BYTES + int "Max buffer size for TCP payloads" + depends on ENABLE_TCP_TRANSPORT + default 1530 + help + Max TCP payload buffer size. + + endmenu + menu "Network Commissioning Driver Endpoint Id" config THREAD_NETWORK_COMMISSIONING_DRIVER bool "Use the generic Thread network commissioning driver" diff --git a/config/nrfconnect/chip-module/Kconfig b/config/nrfconnect/chip-module/Kconfig index 6b0a9b1c3b4..a045d211055 100644 --- a/config/nrfconnect/chip-module/Kconfig +++ b/config/nrfconnect/chip-module/Kconfig @@ -96,24 +96,6 @@ config CHIP_OTA_REQUESTOR imply STREAM_FLASH imply STREAM_FLASH_ERASE -config CHIP_OTA_REQUESTOR_BUFFER_SIZE - int "OTA Requestor image buffer size" - default 1024 - depends on CHIP_OTA_REQUESTOR - help - Configures the size of the buffer used by OTA Requestor when downloading - and writing a new firmware image to flash. - -config CHIP_OTA_REQUESTOR_REBOOT_ON_APPLY - bool "Auto-reboot when firmware update is applied" - default y - depends on CHIP_OTA_REQUESTOR - imply REBOOT - help - Reboots the device automatically after downloading a new firmware update - to swap the old and the new firmware images. The reboot happens only when - a user consents to apply the firmware update. - config CHIP_EXAMPLE_DEVICE_INFO_PROVIDER bool "Include default device information provider build" default y @@ -300,14 +282,6 @@ config CHIP_FACTORY_RESET_ERASE_SETTINGS default y depends on NVS || ZMS -config CHIP_LOG_SIZE_OPTIMIZATION - bool "Disable some detailed logs to decrease flash usage" - help - Disables some log levels for specific Matter log modules that provide - information that is too detailed to be used in most cases. You can find - full configuration enabled by this option in the - platform/nrfconnect/CHIPPlatformConfig.h file. - config CHIP_IPV4 bool "IPv4 support for Matter" default n diff --git a/config/nxp/README.md b/config/nxp/README.md index 1d41618ba81..e5663d1bf22 100644 --- a/config/nxp/README.md +++ b/config/nxp/README.md @@ -6,7 +6,7 @@ structured as follows : | File/Folder | Contents | | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| chip-gn | GN project used to build selected CHIP libraries with the _nxp_zephyr_ platform integration layer | +| chip-gn | GN project used to build selected CHIP libraries with the _zephyr_ platform integration layer | | chip-module | CMake wrapper for the GN project defined in `chip-gn` directory, and other components that allow one to use CHIP as a Zephyr module | | app | Common and optional Kconfig configuration files that can be used in NXP Zephyr applications | | chip-gn-freertos | GN project used to build selected CHIP libraries with the NXP FreeRTOS platform integration layer | diff --git a/config/nxp/chip-gn/BUILD.gn b/config/nxp/chip-gn/BUILD.gn index b7e1aa60256..902ca7c5cab 100644 --- a/config/nxp/chip-gn/BUILD.gn +++ b/config/nxp/chip-gn/BUILD.gn @@ -23,7 +23,7 @@ declare_args() { chip_build_example_providers = false } -group("nxp_zephyr") { +group("zephyr") { deps = [ "${chip_root}/src/lib" ] if (chip_build_tests) { @@ -36,5 +36,5 @@ group("nxp_zephyr") { } group("default") { - deps = [ ":nxp_zephyr" ] + deps = [ ":zephyr" ] } diff --git a/config/nxp/chip-gn/args.gni b/config/nxp/chip-gn/args.gni index 702e9537b4b..bd0f171cf98 100644 --- a/config/nxp/chip-gn/args.gni +++ b/config/nxp/chip-gn/args.gni @@ -16,7 +16,7 @@ import("//build_overrides/chip.gni") import("${chip_root}/src/crypto/crypto.gni") -chip_device_platform = "nxp_zephyr" +chip_device_platform = "zephyr" chip_build_tests = false diff --git a/config/nxp/chip-module/CMakeLists.txt b/config/nxp/chip-module/CMakeLists.txt index 4371efc9d69..c21c57962e1 100644 --- a/config/nxp/chip-module/CMakeLists.txt +++ b/config/nxp/chip-module/CMakeLists.txt @@ -17,7 +17,7 @@ # # @file # CMake sub-project defining 'chip' target which represents CHIP library -# and other optional libraries like unit tests, built with 'nxp_zephyr' +# and other optional libraries like unit tests, built with 'zephyr' # platform. # Since CHIP doesn't provide native CMake support, ExternalProject # module is used to build the required artifacts with GN meta-build @@ -106,10 +106,7 @@ matter_add_gn_arg_string("zephyr_ar" ${CMAKE_AR}) matter_add_gn_arg_string("zephyr_cc" ${CMAKE_C_COMPILER}) matter_add_gn_arg_string("zephyr_cxx" ${CMAKE_CXX_COMPILER}) -if (CONFIG_CHIP_FACTORY_DATA) - matter_add_gn_arg_bool("chip_use_transitional_commissionable_data_provider" FALSE) - matter_add_gn_arg_bool("chip_enable_factory_data" TRUE) -elseif (CONFIG_CHIP_FACTORY_DATA_CUSTOM_BACKEND) +if (CONFIG_CHIP_FACTORY_DATA OR CONFIG_CHIP_FACTORY_DATA_CUSTOM_BACKEND) matter_add_gn_arg_bool("chip_use_transitional_commissionable_data_provider" FALSE) endif() diff --git a/config/nxp/chip-module/Kconfig b/config/nxp/chip-module/Kconfig index 022f6d441b0..685d8267929 100644 --- a/config/nxp/chip-module/Kconfig +++ b/config/nxp/chip-module/Kconfig @@ -203,14 +203,6 @@ config CHIP_FACTORY_RESET_ERASE_SETTINGS endif -config CHIP_LOG_SIZE_OPTIMIZATION - bool "Disable some detailed logs to decrease flash usage" - help - Disables some log levels for specific Matter log modules that provide - information that is too detailed to be used in most cases. You can find - full configuration enabled by this option in the - platform/nxp/CHIPPlatformConfig.h file. - config CHIP_IPV4 bool "IPv4 support for Matter" default n @@ -229,41 +221,3 @@ config BOOTLOADER_MCUBOOT select IMG_MANAGER select STREAM_FLASH select STREAM_FLASH_ERASE - -config CHIP_OTA_REQUESTOR_BUFFER_SIZE - int "OTA Requestor image buffer size" - default 256 - depends on CHIP_OTA_REQUESTOR - help - Configures the size of the buffer used by OTA Requestor when downloading - and writing a new firmware image to flash. - -config CHIP_OTA_REQUESTOR_REBOOT_ON_APPLY - bool "Auto-reboot when firmware update is applied" - default y - depends on CHIP_OTA_REQUESTOR - imply REBOOT - help - Reboots the device automatically after downloading a new firmware update - to swap the old and the new firmware images. The reboot happens only when - a user consents to apply the firmware update. - -choice CHIP_OTA_REQUEST_UPGRADE_TYPE - prompt "Type of the upgrade to apply on new images" - default CHIP_OTA_REQUEST_UPGRADE_TEST - depends on CHIP_OTA_REQUESTOR - - config CHIP_OTA_REQUEST_UPGRADE_PERMANENT - bool "Mark the image as permanent" - help - The upgrade will be permanent on the next reboot. - No coming back to the old image. - - config CHIP_OTA_REQUEST_UPGRADE_TEST - bool "Mark the image as a test" - help - The upgrade will be marked as a test. - Image will be run on the next reboot, if confirmed it - becomes permanent, otherwise the new image is reverted. - -endchoice diff --git a/config/nxp/chip-module/Kconfig.defaults b/config/nxp/chip-module/Kconfig.defaults index b229b253575..b86b78ec3d9 100644 --- a/config/nxp/chip-module/Kconfig.defaults +++ b/config/nxp/chip-module/Kconfig.defaults @@ -23,6 +23,29 @@ if CHIP config CHIP_OPERATIONAL_TIME_SAVE_INTERVAL default 1 +config CHIP_ENABLE_WIFI_STATION + default y if CHIP_WIFI + +config CHIP_SYSTEM_THREAD_LOCAL_STORAGE + default n + +config CHIP_SYSTEM_USE_ZEPHYR_SOCKET_EXTENSIONS + default n + +config CHIP_TASK_PRIORITY + default 5 + +config MAX_EVENT_QUEUE_SIZE + default 64 + +config CHIP_MRP_LOCAL_ACTIVE_RETRY_INTERVAL + default 800 if NET_L2_OPENTHREAD + default 2000 + +config CHIP_MRP_LOCAL_IDLE_RETRY_INTERVAL + default 800 if NET_L2_OPENTHREAD + default 2000 + if CHIP_FACTORY_DATA config CHIP_DEVICE_VENDOR_ID @@ -226,6 +249,13 @@ config HCI_NXP_ENABLE_AUTO_SLEEP config CHIP_OTA_REQUESTOR default n +if CHIP_OTA_REQUESTOR + +config CHIP_OTA_REQUESTOR_BUFFER_SIZE + default 256 + +endif # CHIP_OTA_REQUESTOR + config CHIP_DEVICE_SOFTWARE_VERSION default 1 diff --git a/config/nxp/cmake/Kconfig.matter.common b/config/nxp/cmake/Kconfig.matter.common index 6e8d3c9fce1..f18ef24eaeb 100644 --- a/config/nxp/cmake/Kconfig.matter.common +++ b/config/nxp/cmake/Kconfig.matter.common @@ -352,13 +352,6 @@ config CHIP_ICD_IDLE_MODE_DURATION It determines the maximum amount of time the device can stay in the idle mode, which means the device may be unreachable and not able to receive messages. -config CHIP_ICD_IDLE_MODE_INTERVAL_MS - int "Intermittently Connected Device idle mode interval (ms)" - default 2000 - help - Provides the ICD idle mode interval in milliseconds. - - config CHIP_ICD_ACTIVE_MODE_DURATION int "Intermittently Connected Device active mode duration (ms)" default 10000 @@ -366,12 +359,6 @@ config CHIP_ICD_ACTIVE_MODE_DURATION Provides the Intermittently Connected Device active mode duration in milliseconds. It determines the minimum amount of time the device shall stay in the active mode. -config CHIP_ICD_ACTIVE_MODE_INTERVAL_MS - int "Intermittently Connected Device active mode interval (ms)" - default 500 - help - Provides the ICD active mode interval in milliseconds. - config CHIP_ICD_ACTIVE_MODE_THRESHOLD int "Intermittently Connected Device active mode threshold (ms)" default 5000 diff --git a/config/silabs/Kconfig b/config/silabs/Kconfig index 23caeeb1ab0..632902fa500 100644 --- a/config/silabs/Kconfig +++ b/config/silabs/Kconfig @@ -35,24 +35,6 @@ config CHIP_OTA_REQUESTOR imply STREAM_FLASH imply STREAM_FLASH_ERASE -config CHIP_OTA_REQUESTOR_BUFFER_SIZE - int "OTA Requestor image buffer size" - default 1024 - depends on CHIP_OTA_REQUESTOR - help - Configures the size of the buffer used by OTA Requestor when downloading - and writing a new firmware image to flash. - -config CHIP_OTA_REQUESTOR_REBOOT_ON_APPLY - bool "Auto-reboot when firmware update is applied" - default y - depends on CHIP_OTA_REQUESTOR - imply REBOOT - help - Reboots the device automatically after downloading a new firmware update - to swap the old and the new firmware images. The reboot happens only when - a user consents to apply the firmware update. - config CHIP_OTA_IMAGE_BUILD bool default y if CHIP_OTA_REQUESTOR @@ -213,14 +195,6 @@ config CHIP_FACTORY_RESET_ERASE_SETTINGS default y depends on NVS || ZMS -config CHIP_LOG_SIZE_OPTIMIZATION - bool "Disable some detailed logs to decrease flash usage" - help - Disables some log levels for specific Matter log modules that provide - information that is too detailed to be used in most cases. You can find - full configuration enabled by this option in the - platform/silabs/CHIPPlatformConfig.h file. - config CHIP_OPENTHREAD_JOINER_ENABLED bool "Specify whether the Thread Joiner functionality is used when it is enabled" default n diff --git a/config/telink/chip-module/Kconfig b/config/telink/chip-module/Kconfig index 6cd2496c1c7..aceb5dd6326 100644 --- a/config/telink/chip-module/Kconfig +++ b/config/telink/chip-module/Kconfig @@ -56,24 +56,6 @@ config BOOTLOADER_MCUBOOT select STREAM_FLASH_ERASE select TELINK_W91_N22_MATTER_OTA_LAYOUT if BOARD_TLSR9118BDK40D || BOARD_TLSR9118BDK40D_V1 -config CHIP_OTA_REQUESTOR_BUFFER_SIZE - int "OTA Requestor image buffer size" - default 256 - depends on CHIP_OTA_REQUESTOR - help - Configures the size of the buffer used by OTA Requestor when downloading - and writing a new firmware image to flash. - -config CHIP_OTA_REQUESTOR_REBOOT_ON_APPLY - bool "Auto-reboot when firmware update is applied" - default y - depends on CHIP_OTA_REQUESTOR - imply REBOOT - help - Reboots the device automatically after downloading a new firmware update - to swap the old and the new firmware images. The reboot happens only when - a user consents to apply the firmware update. - # See config/zephyr/Kconfig for full definition config CHIP_OTA_IMAGE_BUILD bool @@ -196,14 +178,6 @@ config CHIP_FACTORY_RESET_ERASE_SETTINGS endif -config CHIP_LOG_SIZE_OPTIMIZATION - bool "Disable some detailed logs to decrease flash usage" - help - Disables some log levels for specific Matter log modules that provide - information that is too detailed to be used in most cases. You can find - full configuration enabled by this option in the - platform/telink/CHIPPlatformConfig.h file. - config CHIP_IPV4 bool "IPv4 support for Matter" default n diff --git a/config/telink/chip-module/Kconfig.defaults b/config/telink/chip-module/Kconfig.defaults index 273ccfa5ebd..dd656d6360c 100644 --- a/config/telink/chip-module/Kconfig.defaults +++ b/config/telink/chip-module/Kconfig.defaults @@ -244,6 +244,13 @@ config RISCV_MTVEC_VECTORED_MODE config CHIP_OTA_REQUESTOR default y +if CHIP_OTA_REQUESTOR + +config CHIP_OTA_REQUESTOR_BUFFER_SIZE + default 256 + +endif # CHIP_OTA_REQUESTOR + config MCUBOOT_SIGNATURE_KEY_FILE default "bootloader/mcuboot/root-ec-p256.pem" if BOARD_TLSR9118BDK40D || BOARD_TLSR9118BDK40D_V1 depends on BOOTLOADER_MCUBOOT diff --git a/config/zephyr/Kconfig b/config/zephyr/Kconfig index 583ed9d0044..c5a17c04d0f 100644 --- a/config/zephyr/Kconfig +++ b/config/zephyr/Kconfig @@ -50,6 +50,14 @@ config CHIP_APP_LOG_LEVEL option only within the application. To set the logging level for the Matter stack, use the MATTER_LOG_LEVEL configuration option. +config CHIP_LOG_SIZE_OPTIMIZATION + bool "Disable some detailed logs to decrease flash usage" + help + Disables some log levels for specific Matter log modules that provide + information that is too detailed to be used in most cases. You can find + full configuration enabled by this option in the + platform CHIPPlatformConfig.h file. + # Device and firmware identifers config CHIP_DEVICE_VENDOR_ID @@ -245,6 +253,44 @@ config CHIP_OTA_REQUESTOR Device Firmware Upgrade by quering and downloading a new firmware image from a peer OTA Provider node. +config CHIP_OTA_REQUESTOR_BUFFER_SIZE + int "OTA Requestor image buffer size" + default 1024 + depends on CHIP_OTA_REQUESTOR + help + Configures the size of the buffer used by OTA Requestor when downloading + and writing a new firmware image to flash. + +config CHIP_OTA_REQUESTOR_REBOOT_ON_APPLY + bool "Auto-reboot when firmware update is applied" + default y + depends on CHIP_OTA_REQUESTOR + imply REBOOT + help + Reboots the device automatically after downloading a new firmware update + to swap the old and the new firmware images. The reboot happens only when + a user consents to apply the firmware update. + +choice CHIP_OTA_REQUEST_UPGRADE_TYPE + prompt "Type of the upgrade to apply on new images" + default CHIP_OTA_REQUEST_UPGRADE_TEST + depends on CHIP_OTA_REQUESTOR + + config CHIP_OTA_REQUEST_UPGRADE_PERMANENT + bool "Mark the image as permanent" + help + The upgrade will be permanent on the next reboot. + No coming back to the old image. + + config CHIP_OTA_REQUEST_UPGRADE_TEST + bool "Mark the image as a test" + help + The upgrade will be marked as a test. + Image will be run on the next reboot, if confirmed it + becomes permanent, otherwise the new image is reverted. + +endchoice + config CHIP_ROTATING_DEVICE_ID bool "Generate rotating device ID" help @@ -460,6 +506,22 @@ config CHIP_OPENTHREAD_CONFIG is specified, it replaces the OpenThread configuration file supplied by Zephyr. +# Wi-Fi network features + +config CHIP_ENABLE_WIFI_STATION + bool "Enable Wi-Fi Station mode" + depends on WIFI + help + Enable Wi-Fi station (client) mode for Matter-over-Wi-Fi devices. + This allows the device to connect to an existing Wi-Fi network. + +config CHIP_ENABLE_WIFI_AP + bool "Enable Wi-Fi Access Point mode" + depends on WIFI + help + Enable Wi-Fi Access Point mode for SoftAP commissioning. + This allows the device to create its own Wi-Fi network for onboarding. + # Platform additions and configuration config CHIP_CERTIFICATION_DECLARATION_STORAGE @@ -527,6 +589,52 @@ config CHIP_MALLOC_SYS_HEAP_WATERMARKS_SUPPORT endif +config CHIP_SYSTEM_THREAD_LOCAL_STORAGE + bool "Enable thread-local storage for Matter System Layer" + default y + help + Enable use of thread-local storage (TLS) in the Matter System Layer. + +config CHIP_SYSTEM_USE_ZEPHYR_SOCKET_EXTENSIONS + bool "Use Zephyr socket extensions in Matter System Layer" + default y + help + Enables the use of Zephyr socket extensions in the Matter System Layer + socket implementation. + +config CHIP_TASK_PRIORITY + int "Matter task priority" + default 1 + help + Set the Zephyr thread priority for the Matter main task (CHIP event loop). + This value is passed to K_PRIO_PREEMPT(). Lower values mean higher priority. + +config CHIP_TASK_STACK_SIZE + int "Matter task stack size" + default 8192 + help + Set the stack size (in bytes) for the Matter main task (CHIP event loop). + +config MAX_EVENT_QUEUE_SIZE + int "Maximum Matter event queue size" + default 100 + help + Set the maximum number of events that can be queued in the Matter event loop. + +config CHIP_MRP_LOCAL_ACTIVE_RETRY_INTERVAL + int "MRP Local Active Retry Interval (ms)" + default 2000 if NET_L2_OPENTHREAD + default 300 + help + Sets the local active retry interval (in milliseconds) for Matter Message Reliability Protocol (MRP). + +config CHIP_MRP_LOCAL_IDLE_RETRY_INTERVAL + int "MRP Local Idle Retry Interval (ms)" + default 2000 if NET_L2_OPENTHREAD + default 500 + help + Sets the local idle retry interval (in milliseconds) for Matter Message Reliability Protocol (MRP). + module = MATTER module-str = Matter source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config" diff --git a/config/zephyr/chip-module/CMakeLists.txt b/config/zephyr/chip-module/CMakeLists.txt index e0b113a5bb3..8f303a9df96 100644 --- a/config/zephyr/chip-module/CMakeLists.txt +++ b/config/zephyr/chip-module/CMakeLists.txt @@ -100,6 +100,7 @@ if(CONFIG_CHIP) matter_add_gn_arg_bool("chip_malloc_sys_heap" CONFIG_CHIP_MALLOC_SYS_HEAP) matter_add_gn_arg_bool("chip_inet_config_enable_tcp_endpoint" FALSE) matter_add_gn_arg_bool("chip_enable_read_client" CONFIG_CHIP_ENABLE_READ_CLIENT) + matter_add_gn_arg_bool("chip_enable_ota_requestor" CONFIG_CHIP_OTA_REQUESTOR) if(BOARD STREQUAL "native_sim") matter_add_gn_arg_string("target_cpu" "x86") diff --git a/credentials/development/commissioner_dut/struct_cd_official_cd/cd.der b/credentials/development/commissioner_dut/struct_cd_official_cd/cd.der new file mode 100644 index 00000000000..5824db7f400 Binary files /dev/null and b/credentials/development/commissioner_dut/struct_cd_official_cd/cd.der differ diff --git a/credentials/development/commissioner_dut/struct_cd_official_cd/dac-Cert.der b/credentials/development/commissioner_dut/struct_cd_official_cd/dac-Cert.der new file mode 100644 index 00000000000..03f067d11d0 Binary files /dev/null and b/credentials/development/commissioner_dut/struct_cd_official_cd/dac-Cert.der differ diff --git a/credentials/development/commissioner_dut/struct_cd_official_cd/dac-Cert.pem b/credentials/development/commissioner_dut/struct_cd_official_cd/dac-Cert.pem new file mode 100644 index 00000000000..ae5a8d043f8 --- /dev/null +++ b/credentials/development/commissioner_dut/struct_cd_official_cd/dac-Cert.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIIB5DCCAYqgAwIBAgIIKyooBBJc5nQwCgYIKoZIzj0EAwIwRjEYMBYGA1UEAwwP +TWF0dGVyIFRlc3QgUEFJMRQwEgYKKwYBBAGConwCAQwERkZGMTEUMBIGCisGAQQB +gqJ8AgIMBDgwMDAwIBcNMjUxMjE4MDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMEYx +GDAWBgNVBAMMD01hdHRlciBUZXN0IERBQzEUMBIGCisGAQQBgqJ8AgEMBEZGRjEx +FDASBgorBgEEAYKifAICDAQ4MDAwMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +lQrwIKwOIC9saf8QqLh7pfTgpv68T0cVpgY5tgn0mEffbCTv3MLUOnPXLw6Sl/E3 +XMgqERWgHWWL9bkRgRkrXqNgMF4wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMC +B4AwHQYDVR0OBBYEFJPT5pkurVwfltlAsFi+sGxd9BuNMB8GA1UdIwQYMBaAFM+i +4fA2NWjPI+iIB+HaLxmtyYCsMAoGCCqGSM49BAMCA0gAMEUCIEJMLR8LjvF84oKU +Qz61KUtQbku67VWHvmZTAhGl5pkVAiEA9TSYENOJBfHCpOCNBJHxXz1QRgV8RElJ +v46VNdR+miE= +-----END CERTIFICATE----- diff --git a/credentials/development/commissioner_dut/struct_cd_official_cd/dac-Key.der b/credentials/development/commissioner_dut/struct_cd_official_cd/dac-Key.der new file mode 100644 index 00000000000..34b130f909b Binary files /dev/null and b/credentials/development/commissioner_dut/struct_cd_official_cd/dac-Key.der differ diff --git a/credentials/development/commissioner_dut/struct_cd_official_cd/dac-Key.pem b/credentials/development/commissioner_dut/struct_cd_official_cd/dac-Key.pem new file mode 100644 index 00000000000..27ab05fe567 --- /dev/null +++ b/credentials/development/commissioner_dut/struct_cd_official_cd/dac-Key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIH6lkj3Y/KwY/PaPmtbt4n7lVzImR4zbO4jFhnDeLhNloAoGCCqGSM49 +AwEHoUQDQgAElQrwIKwOIC9saf8QqLh7pfTgpv68T0cVpgY5tgn0mEffbCTv3MLU +OnPXLw6Sl/E3XMgqERWgHWWL9bkRgRkrXg== +-----END EC PRIVATE KEY----- diff --git a/credentials/development/commissioner_dut/struct_cd_official_cd/pai-Cert.der b/credentials/development/commissioner_dut/struct_cd_official_cd/pai-Cert.der new file mode 100644 index 00000000000..dccf80cc7ae Binary files /dev/null and b/credentials/development/commissioner_dut/struct_cd_official_cd/pai-Cert.der differ diff --git a/credentials/development/commissioner_dut/struct_cd_official_cd/pai-Cert.pem b/credentials/development/commissioner_dut/struct_cd_official_cd/pai-Cert.pem new file mode 100644 index 00000000000..e642e8373c9 --- /dev/null +++ b/credentials/development/commissioner_dut/struct_cd_official_cd/pai-Cert.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIB1DCCAXqgAwIBAgIIJMq+OwWnvTcwCgYIKoZIzj0EAwIwMDEYMBYGA1UEAwwP +TWF0dGVyIFRlc3QgUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTAgFw0yNTEyMTgw +MDAwMDBaGA85OTk5MTIzMTIzNTk1OVowRjEYMBYGA1UEAwwPTWF0dGVyIFRlc3Qg +UEFJMRQwEgYKKwYBBAGConwCAQwERkZGMTEUMBIGCisGAQQBgqJ8AgIMBDgwMDAw +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARy2GTqddl5i6AHh7vfbgDu7kZFqQ/3 +bqqmj27V9Jp36+8yIVmZ5gGnNvD1laeSTJQ+lQvIwZx7PWcQwsdVF5YZo2YwZDAS +BgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUz6Lh +8DY1aM8j6IgH4dovGa3JgKwwHwYDVR0jBBgwFoAUav0idx9RH+y/FkGXZxDc3DGh +cX4wCgYIKoZIzj0EAwIDSAAwRQIgfX7ptLB8sfl8l0gKYouAI5XP0FlYQ6KxANbq +WUN6SxoCIQD/iN5J2A6EJuFhnuRJIoUJNF71ek4+3Xmxq7eugY1gSw== +-----END CERTIFICATE----- diff --git a/credentials/development/commissioner_dut/struct_cd_official_cd/pai-Key.der b/credentials/development/commissioner_dut/struct_cd_official_cd/pai-Key.der new file mode 100644 index 00000000000..df84d665cba Binary files /dev/null and b/credentials/development/commissioner_dut/struct_cd_official_cd/pai-Key.der differ diff --git a/credentials/development/commissioner_dut/struct_cd_official_cd/pai-Key.pem b/credentials/development/commissioner_dut/struct_cd_official_cd/pai-Key.pem new file mode 100644 index 00000000000..6eb4b463968 --- /dev/null +++ b/credentials/development/commissioner_dut/struct_cd_official_cd/pai-Key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEII713s3R6MxdfTFw8zW4dhOxGTRzsC2BcLb/JR274ZeNoAoGCCqGSM49 +AwEHoUQDQgAEcthk6nXZeYugB4e7324A7u5GRakP926qpo9u1fSad+vvMiFZmeYB +pzbw9ZWnkkyUPpULyMGcez1nEMLHVReWGQ== +-----END EC PRIVATE KEY----- diff --git a/credentials/development/commissioner_dut/struct_cd_official_cd/test_case_vector.json b/credentials/development/commissioner_dut/struct_cd_official_cd/test_case_vector.json new file mode 100644 index 00000000000..27214fcfcd5 --- /dev/null +++ b/credentials/development/commissioner_dut/struct_cd_official_cd/test_case_vector.json @@ -0,0 +1,10 @@ +{ + "description": "CD Test Vector: CD certification type is official (signed by test key)", + "is_success_case": "false", + "basic_info_pid": 32768, + "dac_cert": "308201e43082018aa00302010202082b2a2804125ce674300a06082a8648ce3d04030230463118301606035504030c0f4d617474657220546573742050414931143012060a2b0601040182a27c02010c044646463131143012060a2b0601040182a27c02020c04383030303020170d3235313231383030303030305a180f39393939313233313233353935395a30463118301606035504030c0f4d617474657220546573742044414331143012060a2b0601040182a27c02010c044646463131143012060a2b0601040182a27c02020c04383030303059301306072a8648ce3d020106082a8648ce3d03010703420004950af020ac0e202f6c69ff10a8b87ba5f4e0a6febc4f4715a60639b609f49847df6c24efdcc2d43a73d72f0e9297f1375cc82a1115a01d658bf5b91181192b5ea360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e0416041493d3e6992ead5c1f96d940b058beb06c5df41b8d301f0603551d23041830168014cfa2e1f0363568cf23e88807e1da2f19adc980ac300a06082a8648ce3d04030203480030450220424c2d1f0b8ef17ce28294433eb5294b506e4bbaed5587be66530211a5e69915022100f5349810d38905f1c2a4e08d0491f15f3d5046057c444949bf8e9535d47e9a21", + "pai_cert": "308201d43082017aa003020102020824cabe3b05a7bd37300a06082a8648ce3d04030230303118301606035504030c0f4d617474657220546573742050414131143012060a2b0601040182a27c02010c04464646313020170d3235313231383030303030305a180f39393939313233313233353935395a30463118301606035504030c0f4d617474657220546573742050414931143012060a2b0601040182a27c02010c044646463131143012060a2b0601040182a27c02020c04383030303059301306072a8648ce3d020106082a8648ce3d0301070342000472d864ea75d9798ba00787bbdf6e00eeee4645a90ff76eaaa68f6ed5f49a77ebef32215999e601a736f0f595a7924c943e950bc8c19c7b3d6710c2c755179619a366306430120603551d130101ff040830060101ff020100300e0603551d0f0101ff040403020106301d0603551d0e04160414cfa2e1f0363568cf23e88807e1da2f19adc980ac301f0603551d230418301680146afd22771f511fecbf1641976710dcdc31a1717e300a06082a8648ce3d040302034800304502207d7ee9b4b07cb1f97c97480a628b802395cfd0595843a2b100d6ea59437a4b1a022100ff88de49d80e8426e1619ee449228509345ef57a4e3edd79b1abb7ae818d604b", + "certification_declaration": "3081ea06092a864886f70d010702a081dc3081d9020103310d300b0609608648016503040201304506092a864886f70d010701a0380436152400012501f1ff360205008018250334122c04135a494732303134315a423333303030312d32342405002406002507769824080218317e307c020103801462fa823359acfaa9963e1cfa140addf504f37160300b0609608648016503040201300a06082a8648ce3d04030204483046022100ffc0e45750c1700c00e53d8bc2027c6b6d9a280250c954afac0d7aa6f379ca48022100c98e261525b5751b6f57b0999f79e822ea35786164613a1a186ef363a7002ec4", + "dac_private_key": "7ea5923dd8fcac18fcf68f9ad6ede27ee5573226478cdb3b88c58670de2e1365", + "dac_public_key": "04950af020ac0e202f6c69ff10a8b87ba5f4e0a6febc4f4715a60639b609f49847df6c24efdcc2d43a73d72f0e9297f1375cc82a1115a01d658bf5b91181192b5e" +} diff --git a/credentials/development/commissioner_dut/struct_cd_provisional_cd/cd.der b/credentials/development/commissioner_dut/struct_cd_provisional_cd/cd.der new file mode 100644 index 00000000000..8424b0b19d5 Binary files /dev/null and b/credentials/development/commissioner_dut/struct_cd_provisional_cd/cd.der differ diff --git a/credentials/development/commissioner_dut/struct_cd_provisional_cd/dac-Cert.der b/credentials/development/commissioner_dut/struct_cd_provisional_cd/dac-Cert.der new file mode 100644 index 00000000000..22c2b1421bb Binary files /dev/null and b/credentials/development/commissioner_dut/struct_cd_provisional_cd/dac-Cert.der differ diff --git a/credentials/development/commissioner_dut/struct_cd_provisional_cd/dac-Cert.pem b/credentials/development/commissioner_dut/struct_cd_provisional_cd/dac-Cert.pem new file mode 100644 index 00000000000..bcb21aab7ad --- /dev/null +++ b/credentials/development/commissioner_dut/struct_cd_provisional_cd/dac-Cert.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIIB5DCCAYqgAwIBAgIIRyNVuEs6FO0wCgYIKoZIzj0EAwIwRjEYMBYGA1UEAwwP +TWF0dGVyIFRlc3QgUEFJMRQwEgYKKwYBBAGConwCAQwERkZGMTEUMBIGCisGAQQB +gqJ8AgIMBDgwMDAwIBcNMjUxMjE4MDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMEYx +GDAWBgNVBAMMD01hdHRlciBUZXN0IERBQzEUMBIGCisGAQQBgqJ8AgEMBEZGRjEx +FDASBgorBgEEAYKifAICDAQ4MDAwMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +P6zjjUwfL6emrqH80RES8rEfebRmtZdenDKfh2n1PFin6Lq9qFXWYvCXOQKrbrFj +UUbFHqLms0y4MsviWHo95KNgMF4wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMC +B4AwHQYDVR0OBBYEFONi5OQ45LYfTFXuzSBSCtU2w4v6MB8GA1UdIwQYMBaAFGKE +t597Pkz8pETDtazvdHk+2ZvGMAoGCCqGSM49BAMCA0gAMEUCIQCXi12KK8b0/TRX +s/n3trlfumL0j1o50K2u0OssZ5rM+QIgYQAVcME6Fo70u+8l/32aVMTwUuz7ltfs +ek9kxbBngEA= +-----END CERTIFICATE----- diff --git a/credentials/development/commissioner_dut/struct_cd_provisional_cd/dac-Key.der b/credentials/development/commissioner_dut/struct_cd_provisional_cd/dac-Key.der new file mode 100644 index 00000000000..cdef80526c3 Binary files /dev/null and b/credentials/development/commissioner_dut/struct_cd_provisional_cd/dac-Key.der differ diff --git a/credentials/development/commissioner_dut/struct_cd_provisional_cd/dac-Key.pem b/credentials/development/commissioner_dut/struct_cd_provisional_cd/dac-Key.pem new file mode 100644 index 00000000000..fd7f6d0d03b --- /dev/null +++ b/credentials/development/commissioner_dut/struct_cd_provisional_cd/dac-Key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIDwXMs1KWvnbsKT2wetgCz4ko/jDdGDoUDJWekMgygFHoAoGCCqGSM49 +AwEHoUQDQgAEP6zjjUwfL6emrqH80RES8rEfebRmtZdenDKfh2n1PFin6Lq9qFXW +YvCXOQKrbrFjUUbFHqLms0y4MsviWHo95A== +-----END EC PRIVATE KEY----- diff --git a/credentials/development/commissioner_dut/struct_cd_provisional_cd/pai-Cert.der b/credentials/development/commissioner_dut/struct_cd_provisional_cd/pai-Cert.der new file mode 100644 index 00000000000..886e238f8b3 Binary files /dev/null and b/credentials/development/commissioner_dut/struct_cd_provisional_cd/pai-Cert.der differ diff --git a/credentials/development/commissioner_dut/struct_cd_provisional_cd/pai-Cert.pem b/credentials/development/commissioner_dut/struct_cd_provisional_cd/pai-Cert.pem new file mode 100644 index 00000000000..23ebfe2e67d --- /dev/null +++ b/credentials/development/commissioner_dut/struct_cd_provisional_cd/pai-Cert.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIB0zCCAXqgAwIBAgIIfbKH8HQfBXIwCgYIKoZIzj0EAwIwMDEYMBYGA1UEAwwP +TWF0dGVyIFRlc3QgUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTAgFw0yNTEyMTgw +MDAwMDBaGA85OTk5MTIzMTIzNTk1OVowRjEYMBYGA1UEAwwPTWF0dGVyIFRlc3Qg +UEFJMRQwEgYKKwYBBAGConwCAQwERkZGMTEUMBIGCisGAQQBgqJ8AgIMBDgwMDAw +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR/F768JPlG0kXPayNjOVY5/Y5D5Wji +/d7k5k6C0p+2ZXJO4ddpgavqiofPkbJdUTNrYNknJCcMNn6e4byRAL6io2YwZDAS +BgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUYoS3 +n3s+TPykRMO1rO90eT7Zm8YwHwYDVR0jBBgwFoAUav0idx9RH+y/FkGXZxDc3DGh +cX4wCgYIKoZIzj0EAwIDRwAwRAIgPNXqv2WnkfF0+IQAnkRSgf/DHow+gjtFpIUy +TeVbhcoCIEDYM+fkb/15ymzaerCBh014tyGJqTOrEAjtDaf7rKF6 +-----END CERTIFICATE----- diff --git a/credentials/development/commissioner_dut/struct_cd_provisional_cd/pai-Key.der b/credentials/development/commissioner_dut/struct_cd_provisional_cd/pai-Key.der new file mode 100644 index 00000000000..4800747c857 Binary files /dev/null and b/credentials/development/commissioner_dut/struct_cd_provisional_cd/pai-Key.der differ diff --git a/credentials/development/commissioner_dut/struct_cd_provisional_cd/pai-Key.pem b/credentials/development/commissioner_dut/struct_cd_provisional_cd/pai-Key.pem new file mode 100644 index 00000000000..5581dea8e12 --- /dev/null +++ b/credentials/development/commissioner_dut/struct_cd_provisional_cd/pai-Key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEICOK6RcdmRNsr98k0O4+TrijwtIRyASYomIQ27m9vXV5oAoGCCqGSM49 +AwEHoUQDQgAEfxe+vCT5RtJFz2sjYzlWOf2OQ+Vo4v3e5OZOgtKftmVyTuHXaYGr +6oqHz5GyXVEza2DZJyQnDDZ+nuG8kQC+og== +-----END EC PRIVATE KEY----- diff --git a/credentials/development/commissioner_dut/struct_cd_provisional_cd/test_case_vector.json b/credentials/development/commissioner_dut/struct_cd_provisional_cd/test_case_vector.json new file mode 100644 index 00000000000..72c667fbf9f --- /dev/null +++ b/credentials/development/commissioner_dut/struct_cd_provisional_cd/test_case_vector.json @@ -0,0 +1,10 @@ +{ + "description": "CD Test Vector: CD certification type is provisional (signed by test key)", + "is_success_case": "true", + "basic_info_pid": 32768, + "dac_cert": "308201e43082018aa0030201020208472355b84b3a14ed300a06082a8648ce3d04030230463118301606035504030c0f4d617474657220546573742050414931143012060a2b0601040182a27c02010c044646463131143012060a2b0601040182a27c02020c04383030303020170d3235313231383030303030305a180f39393939313233313233353935395a30463118301606035504030c0f4d617474657220546573742044414331143012060a2b0601040182a27c02010c044646463131143012060a2b0601040182a27c02020c04383030303059301306072a8648ce3d020106082a8648ce3d030107034200043face38d4c1f2fa7a6aea1fcd11112f2b11f79b466b5975e9c329f8769f53c58a7e8babda855d662f0973902ab6eb1635146c51ea2e6b34cb832cbe2587a3de4a360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e04160414e362e4e438e4b61f4c55eecd20520ad536c38bfa301f0603551d230418301680146284b79f7b3e4cfca444c3b5acef74793ed99bc6300a06082a8648ce3d0403020348003045022100978b5d8a2bc6f4fd3457b3f9f7b6b95fba62f48f5a39d0adaed0eb2c679accf9022061001570c13a168ef4bbef25ff7d9a54c4f052ecfb96d7ec7a4f64c5b0678040", + "pai_cert": "308201d33082017aa00302010202087db287f0741f0572300a06082a8648ce3d04030230303118301606035504030c0f4d617474657220546573742050414131143012060a2b0601040182a27c02010c04464646313020170d3235313231383030303030305a180f39393939313233313233353935395a30463118301606035504030c0f4d617474657220546573742050414931143012060a2b0601040182a27c02010c044646463131143012060a2b0601040182a27c02020c04383030303059301306072a8648ce3d020106082a8648ce3d030107034200047f17bebc24f946d245cf6b2363395639fd8e43e568e2fddee4e64e82d29fb665724ee1d76981abea8a87cf91b25d51336b60d92724270c367e9ee1bc9100bea2a366306430120603551d130101ff040830060101ff020100300e0603551d0f0101ff040403020106301d0603551d0e041604146284b79f7b3e4cfca444c3b5acef74793ed99bc6301f0603551d230418301680146afd22771f511fecbf1641976710dcdc31a1717e300a06082a8648ce3d040302034700304402203cd5eabf65a791f174f884009e445281ffc31e8c3e823b45a485324de55b85ca022040d833e7e46ffd79ca6cda7ab081874d78b72189a933ab1008ed0da7fbaca17a", + "certification_declaration": "3081e906092a864886f70d010702a081db3081d8020103310d300b0609608648016503040201304506092a864886f70d010701a0380436152400012501f1ff360205008018250334122c04135a494732303134315a423333303030312d32342405002406002507769824080118317d307b020103801462fa823359acfaa9963e1cfa140addf504f37160300b0609608648016503040201300a06082a8648ce3d04030204473045022100a9e755726b990a5b86d22d7dc0df813fa54624d5494676e4e50ded9a8964be8002206831532ab38b2d7594823552a0ed22a4040dc75a517f45871b2fc6e2d2e7e4bf", + "dac_private_key": "3c1732cd4a5af9dbb0a4f6c1eb600b3e24a3f8c37460e85032567a4320ca0147", + "dac_public_key": "043face38d4c1f2fa7a6aea1fcd11112f2b11f79b466b5975e9c329f8769f53c58a7e8babda855d662f0973902ab6eb1635146c51ea2e6b34cb832cbe2587a3de4" +} diff --git a/credentials/fetch_paa_certs_from_dcl.py b/credentials/fetch_paa_certs_from_dcl.py index 3bcd74b6534..d37302e3aa3 100755 --- a/credentials/fetch_paa_certs_from_dcl.py +++ b/credentials/fetch_paa_certs_from_dcl.py @@ -136,9 +136,13 @@ def use_dcld(dcld, production, cmdlist): @optgroup.option('--use-test-net-http', is_flag=True, type=str, help="Use RESTful API with HTTPS against public TestNet observer.") @optgroup.group('Optional arguments') @optgroup.option('--paa-trust-store-path', default='paa-root-certs', type=str, metavar='PATH', help="PAA trust store path (default: paa-root-certs)") -def main(use_main_net_dcld, use_test_net_dcld, use_main_net_http, use_test_net_http, paa_trust_store_path): - """DCL PAA mirroring tools""" - fetch_paa_certs(use_main_net_dcld, use_test_net_dcld, use_main_net_http, use_test_net_http, paa_trust_store_path) +@optgroup.option('--cd-output-path') +def main(use_main_net_dcld, use_test_net_dcld, use_main_net_http, use_test_net_http, paa_trust_store_path, cd_output_path): + """DCL mirroring tools""" + if cd_output_path is not None: + fetch_cd_signing_certs(cd_output_path) + else: + fetch_paa_certs(use_main_net_dcld, use_test_net_dcld, use_main_net_http, use_test_net_http, paa_trust_store_path) def get_cert_from_rest(rest_node_url, subject, subject_key_id): diff --git a/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_001_O_CSA_vid_0xC5A0.der b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_001_O_CSA_vid_0xC5A0.der new file mode 100644 index 00000000000..0bcdc2c37db Binary files /dev/null and b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_001_O_CSA_vid_0xC5A0.der differ diff --git a/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_001_O_CSA_vid_0xC5A0.pem b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_001_O_CSA_vid_0xC5A0.pem new file mode 100644 index 00000000000..07bce8cc079 --- /dev/null +++ b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_001_O_CSA_vid_0xC5A0.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICBzCCAa2gAwIBAgIHY3NhY2RrMTAKBggqhkjOPQQDAjBSMQwwCgYDVQQKDAND +U0ExLDAqBgNVBAMMI01hdHRlciBDZXJ0aWZpY2F0aW9uIGFuZCBUZXN0aW5nIENB +MRQwEgYKKwYBBAGConwCAQwEQzVBMDAgFw0yMjEwMDMxOTI4NTVaGA8yMDcyMDky +MDE5Mjg1NVowWDEMMAoGA1UECgwDQ1NBMTIwMAYDVQQDDClDZXJ0aWZpY2F0aW9u +IERlY2xhcmF0aW9uIFNpZ25pbmcgS2V5IDAwMTEUMBIGCisGAQQBgqJ8AgEMBEM1 +QTAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATN7uk+RPi3K+PRqcB+IZaLmv/z +tAPwXhZp17Hlyu5vx3FLQufiNpXpLNdjVHOigK5ojze7lInhFim5uU/3sJkpo2Yw +ZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQU +/jQ/lZlHdjth7kU5ExM4SU/mfY4wHwYDVR0jBBgwFoAUl+Rp0MUEFMJvxwH3fpR3 +OQmN9qUwCgYIKoZIzj0EAwIDSAAwRQIgEDWOcdKsVGtUh3evHbBd1lq4aS7yQtOp +6GrOQ3/zXBsCIQDxorh2RXSaI8m2RCcoWaiWa0nLzQepNm3C2jrQVJmC2Q== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_002_O_CSA_vid_0xC5A0.der b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_002_O_CSA_vid_0xC5A0.der new file mode 100644 index 00000000000..3e6046ac47a Binary files /dev/null and b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_002_O_CSA_vid_0xC5A0.der differ diff --git a/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_002_O_CSA_vid_0xC5A0.pem b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_002_O_CSA_vid_0xC5A0.pem new file mode 100644 index 00000000000..c656bc86ee8 --- /dev/null +++ b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_002_O_CSA_vid_0xC5A0.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICCDCCAa2gAwIBAgIHY3NhY2RrMjAKBggqhkjOPQQDAjBSMQwwCgYDVQQKDAND +U0ExLDAqBgNVBAMMI01hdHRlciBDZXJ0aWZpY2F0aW9uIGFuZCBUZXN0aW5nIENB +MRQwEgYKKwYBBAGConwCAQwEQzVBMDAgFw0yMjEwMDMxOTM2NDZaGA8yMDcyMDky +MDE5MzY0NlowWDEMMAoGA1UECgwDQ1NBMTIwMAYDVQQDDClDZXJ0aWZpY2F0aW9u +IERlY2xhcmF0aW9uIFNpZ25pbmcgS2V5IDAwMjEUMBIGCisGAQQBgqJ8AgEMBEM1 +QTAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQDGTfo+UJRBF3ydFe7RiU+43VO +jBKuKFV9gCe51MNW2RtAjP8yJ1AXsl+Mi6IFFtXIOvK3JBKAE9/Mj5XSAKkLo2Yw +ZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQU +3QTbWFshTBxYFYfmVo30h7bdxwEwHwYDVR0jBBgwFoAUl+Rp0MUEFMJvxwH3fpR3 +OQmN9qUwCgYIKoZIzj0EAwIDSQAwRgIhAJruzxZ806cP/LoQ07PN9xAbjLdwUalV +h0Qfx304Tb92AiEAk+jnf2qtyfKyTEHpT3Xf3bfekqUOA+8ikB1yjL5oTsI= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_003_O_CSA_vid_0xC5A0.der b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_003_O_CSA_vid_0xC5A0.der new file mode 100644 index 00000000000..6fd2138beb4 Binary files /dev/null and b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_003_O_CSA_vid_0xC5A0.der differ diff --git a/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_003_O_CSA_vid_0xC5A0.pem b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_003_O_CSA_vid_0xC5A0.pem new file mode 100644 index 00000000000..68c930c44c9 --- /dev/null +++ b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_003_O_CSA_vid_0xC5A0.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICBjCCAa2gAwIBAgIHY3NhY2RrMzAKBggqhkjOPQQDAjBSMQwwCgYDVQQKDAND +U0ExLDAqBgNVBAMMI01hdHRlciBDZXJ0aWZpY2F0aW9uIGFuZCBUZXN0aW5nIENB +MRQwEgYKKwYBBAGConwCAQwEQzVBMDAgFw0yMjEwMDMxOTQxMDFaGA8yMDcyMDky +MDE5NDEwMVowWDEMMAoGA1UECgwDQ1NBMTIwMAYDVQQDDClDZXJ0aWZpY2F0aW9u +IERlY2xhcmF0aW9uIFNpZ25pbmcgS2V5IDAwMzEUMBIGCisGAQQBgqJ8AgEMBEM1 +QTAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASfV1zV/bdSHxCk3zHwc5ErYUco +8tN/W2uWvCy/fAsRlpBXfVVdIaCWYKiwgqM56lMPeoEthpO1b9dkGF+rzTL1o2Yw +ZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQU +RxA158BOqqi+fE1ME+PkwgmVqEswHwYDVR0jBBgwFoAUl+Rp0MUEFMJvxwH3fpR3 +OQmN9qUwCgYIKoZIzj0EAwIDRwAwRAIgIFecbY+1mVVNqxH9+8IMB8+safdyIJU2 +AqqtZ/w7AkQCIHiVlYTaCnJsnW5/cvj9GfIv7Eb0cjdmcAkrYGbnPQzX +-----END CERTIFICATE----- \ No newline at end of file diff --git a/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_004_O_CSA_vid_0xC5A0.der b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_004_O_CSA_vid_0xC5A0.der new file mode 100644 index 00000000000..8ac5b038ed8 Binary files /dev/null and b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_004_O_CSA_vid_0xC5A0.der differ diff --git a/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_004_O_CSA_vid_0xC5A0.pem b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_004_O_CSA_vid_0xC5A0.pem new file mode 100644 index 00000000000..afe9a365a39 --- /dev/null +++ b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_004_O_CSA_vid_0xC5A0.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICBjCCAa2gAwIBAgIHY3NhY2RrNDAKBggqhkjOPQQDAjBSMQwwCgYDVQQKDAND +U0ExLDAqBgNVBAMMI01hdHRlciBDZXJ0aWZpY2F0aW9uIGFuZCBUZXN0aW5nIENB +MRQwEgYKKwYBBAGConwCAQwEQzVBMDAgFw0yMjEwMDMxOTQzMjFaGA8yMDcyMDky +MDE5NDMyMVowWDEMMAoGA1UECgwDQ1NBMTIwMAYDVQQDDClDZXJ0aWZpY2F0aW9u +IERlY2xhcmF0aW9uIFNpZ25pbmcgS2V5IDAwNDEUMBIGCisGAQQBgqJ8AgEMBEM1 +QTAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR8/I2IEKic9PoZF3jyr+x4+FF6 +l6Plf8ITutiI42EedP+2hL3rqKaLJSNKXDWPNzurm20wThMG3XYgpSjRFhwLo2Yw +ZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQU +9oYDo2kumBByQZ6h4as4VL13ldMwHwYDVR0jBBgwFoAUl+Rp0MUEFMJvxwH3fpR3 +OQmN9qUwCgYIKoZIzj0EAwIDRwAwRAIgLqAfkbtLYYdmQsnbn0CWv3G1/lbE36nz +HbLbW5t6PY4CIE8oyIHsVhNSTPcb3mwRp+Vxhs8tKhbAdwv5BGgDaAHj +-----END CERTIFICATE----- \ No newline at end of file diff --git a/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_005_O_CSA_vid_0xC5A0.der b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_005_O_CSA_vid_0xC5A0.der new file mode 100644 index 00000000000..5ca3b5a6ccb Binary files /dev/null and b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_005_O_CSA_vid_0xC5A0.der differ diff --git a/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_005_O_CSA_vid_0xC5A0.pem b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_005_O_CSA_vid_0xC5A0.pem new file mode 100644 index 00000000000..6782c680895 --- /dev/null +++ b/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_005_O_CSA_vid_0xC5A0.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICBzCCAa2gAwIBAgIHY3NhY2RrNTAKBggqhkjOPQQDAjBSMQwwCgYDVQQKDAND +U0ExLDAqBgNVBAMMI01hdHRlciBDZXJ0aWZpY2F0aW9uIGFuZCBUZXN0aW5nIENB +MRQwEgYKKwYBBAGConwCAQwEQzVBMDAgFw0yMjEwMDMxOTQ3MTVaGA8yMDcyMDky +MDE5NDcxNVowWDEMMAoGA1UECgwDQ1NBMTIwMAYDVQQDDClDZXJ0aWZpY2F0aW9u +IERlY2xhcmF0aW9uIFNpZ25pbmcgS2V5IDAwNTEUMBIGCisGAQQBgqJ8AgEMBEM1 +QTAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARDilLGYqKm1yZH+V63UxNu5K4P +2zqpwWkxQms9CGf5EDrn16G4h+n4E6byb3a7zak1k3h8EneMqPKXXcRaIEL5o2Yw +ZDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQU +Y38mNK1i6v5q9mLvuW9v0vy//C8wHwYDVR0jBBgwFoAUl+Rp0MUEFMJvxwH3fpR3 +OQmN9qUwCgYIKoZIzj0EAwIDSAAwRQIhAM1HQpvkHKxLJByWaSYAPRZgh3Bis18W +AViq7c/mtzEAAiBZO0lVe6Qo9iQPIBWZaVx/S/YSNO9uKNa/pvFu3V+nIg== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/data_model/master/clusters/ACL-Cluster.xml b/data_model/1.5.1/clusters/ACL-Cluster.xml similarity index 100% rename from data_model/master/clusters/ACL-Cluster.xml rename to data_model/1.5.1/clusters/ACL-Cluster.xml diff --git a/data_model/master/clusters/AccountLogin.xml b/data_model/1.5.1/clusters/AccountLogin.xml similarity index 100% rename from data_model/master/clusters/AccountLogin.xml rename to data_model/1.5.1/clusters/AccountLogin.xml diff --git a/data_model/master/clusters/ActionsCluster.xml b/data_model/1.5.1/clusters/ActionsCluster.xml similarity index 100% rename from data_model/master/clusters/ActionsCluster.xml rename to data_model/1.5.1/clusters/ActionsCluster.xml diff --git a/data_model/master/clusters/AdminCommissioningCluster.xml b/data_model/1.5.1/clusters/AdminCommissioningCluster.xml similarity index 99% rename from data_model/master/clusters/AdminCommissioningCluster.xml rename to data_model/1.5.1/clusters/AdminCommissioningCluster.xml index 67e19d51e4e..dc059a4cceb 100644 --- a/data_model/master/clusters/AdminCommissioningCluster.xml +++ b/data_model/1.5.1/clusters/AdminCommissioningCluster.xml @@ -124,6 +124,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/master/clusters/AirQuality.xml b/data_model/1.5.1/clusters/AirQuality.xml similarity index 99% rename from data_model/master/clusters/AirQuality.xml rename to data_model/1.5.1/clusters/AirQuality.xml index 929921bacbd..1146fff31a5 100644 --- a/data_model/master/clusters/AirQuality.xml +++ b/data_model/1.5.1/clusters/AirQuality.xml @@ -113,7 +113,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/AlarmBase.xml b/data_model/1.5.1/clusters/AlarmBase.xml similarity index 88% rename from data_model/master/clusters/AlarmBase.xml rename to data_model/1.5.1/clusters/AlarmBase.xml index 626134d57cf..a8ac0426a74 100644 --- a/data_model/master/clusters/AlarmBase.xml +++ b/data_model/1.5.1/clusters/AlarmBase.xml @@ -75,22 +75,22 @@ Davis, CA 95616, USA - + - + - + - + @@ -102,14 +102,14 @@ Davis, CA 95616, USA - + - + @@ -118,16 +118,16 @@ Davis, CA 95616, USA - + - + - + - + diff --git a/data_model/master/clusters/ApplicationBasic.xml b/data_model/1.5.1/clusters/ApplicationBasic.xml similarity index 99% rename from data_model/master/clusters/ApplicationBasic.xml rename to data_model/1.5.1/clusters/ApplicationBasic.xml index f2ef33bfd11..8ea20956843 100644 --- a/data_model/master/clusters/ApplicationBasic.xml +++ b/data_model/1.5.1/clusters/ApplicationBasic.xml @@ -108,7 +108,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/ApplicationLauncher.xml b/data_model/1.5.1/clusters/ApplicationLauncher.xml similarity index 100% rename from data_model/master/clusters/ApplicationLauncher.xml rename to data_model/1.5.1/clusters/ApplicationLauncher.xml diff --git a/data_model/master/clusters/AudioOutput.xml b/data_model/1.5.1/clusters/AudioOutput.xml similarity index 97% rename from data_model/master/clusters/AudioOutput.xml rename to data_model/1.5.1/clusters/AudioOutput.xml index 243d1d4ae66..4d2b2e7f68d 100644 --- a/data_model/master/clusters/AudioOutput.xml +++ b/data_model/1.5.1/clusters/AudioOutput.xml @@ -103,6 +103,9 @@ Davis, CA 95616, USA + + + @@ -135,6 +138,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/master/clusters/BasicInformationCluster.xml b/data_model/1.5.1/clusters/BasicInformationCluster.xml similarity index 92% rename from data_model/master/clusters/BasicInformationCluster.xml rename to data_model/1.5.1/clusters/BasicInformationCluster.xml index b399975afc4..b516e60f4fe 100644 --- a/data_model/master/clusters/BasicInformationCluster.xml +++ b/data_model/1.5.1/clusters/BasicInformationCluster.xml @@ -63,7 +63,7 @@ Davis, CA 95616, USA - + @@ -83,7 +83,7 @@ Davis, CA 95616, USA - + @@ -159,13 +159,19 @@ Davis, CA 95616, USA - + + + + - + + + + @@ -320,7 +326,15 @@ Davis, CA 95616, USA - + + + + + + + + + @@ -333,12 +347,22 @@ Davis, CA 95616, USA - + + + + + + - + + + + + + @@ -346,25 +370,27 @@ Davis, CA 95616, USA - + + + + + + - - - - - - - - - + + + + + + diff --git a/data_model/master/clusters/Binding-Cluster.xml b/data_model/1.5.1/clusters/Binding-Cluster.xml similarity index 100% rename from data_model/master/clusters/Binding-Cluster.xml rename to data_model/1.5.1/clusters/Binding-Cluster.xml diff --git a/data_model/master/clusters/BooleanState.xml b/data_model/1.5.1/clusters/BooleanState.xml similarity index 97% rename from data_model/master/clusters/BooleanState.xml rename to data_model/1.5.1/clusters/BooleanState.xml index f9c269123d5..08b72d5e836 100644 --- a/data_model/master/clusters/BooleanState.xml +++ b/data_model/1.5.1/clusters/BooleanState.xml @@ -57,9 +57,10 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -68,7 +69,6 @@ Davis, CA 95616, USA - diff --git a/data_model/master/clusters/BooleanStateConfiguration.xml b/data_model/1.5.1/clusters/BooleanStateConfiguration.xml similarity index 94% rename from data_model/master/clusters/BooleanStateConfiguration.xml rename to data_model/1.5.1/clusters/BooleanStateConfiguration.xml index dfa4b0cda1c..5e73d643f5b 100644 --- a/data_model/master/clusters/BooleanStateConfiguration.xml +++ b/data_model/1.5.1/clusters/BooleanStateConfiguration.xml @@ -104,17 +104,25 @@ Davis, CA 95616, USA - + - + + + subtract + + + + + + - + @@ -134,10 +142,18 @@ Davis, CA 95616, USA - + + + subtract + + + + + + - + @@ -146,7 +162,7 @@ Davis, CA 95616, USA - + @@ -162,7 +178,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/BridgedDeviceBasicInformationCluster.xml b/data_model/1.5.1/clusters/BridgedDeviceBasicInformationCluster.xml similarity index 68% rename from data_model/master/clusters/BridgedDeviceBasicInformationCluster.xml rename to data_model/1.5.1/clusters/BridgedDeviceBasicInformationCluster.xml index 26f4b022402..aa400fae6e1 100644 --- a/data_model/master/clusters/BridgedDeviceBasicInformationCluster.xml +++ b/data_model/1.5.1/clusters/BridgedDeviceBasicInformationCluster.xml @@ -63,7 +63,7 @@ Davis, CA 95616, USA - + @@ -71,9 +71,130 @@ Davis, CA 95616, USA - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -215,7 +336,15 @@ Davis, CA 95616, USA - + + + + + + + + + @@ -228,7 +357,12 @@ Davis, CA 95616, USA - + + + + + + @@ -246,20 +380,17 @@ Davis, CA 95616, USA - - - - - - - - - + + + + + + @@ -287,24 +418,36 @@ Davis, CA 95616, USA - + + + + - + - + - + + + + + + + - + + + + diff --git a/data_model/master/clusters/CameraAVSettingsUserLevelManagement.xml b/data_model/1.5.1/clusters/CameraAVSettingsUserLevelManagement.xml similarity index 76% rename from data_model/master/clusters/CameraAVSettingsUserLevelManagement.xml rename to data_model/1.5.1/clusters/CameraAVSettingsUserLevelManagement.xml index d52507423d9..70c42a322c4 100644 --- a/data_model/master/clusters/CameraAVSettingsUserLevelManagement.xml +++ b/data_model/1.5.1/clusters/CameraAVSettingsUserLevelManagement.xml @@ -62,14 +62,12 @@ Davis, CA 95616, USA - - - + - + @@ -91,6 +89,22 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + @@ -114,7 +128,7 @@ Davis, CA 95616, USA - + @@ -129,7 +143,7 @@ Davis, CA 95616, USA - + @@ -144,7 +158,7 @@ Davis, CA 95616, USA - + @@ -162,6 +176,7 @@ Davis, CA 95616, USA + @@ -170,33 +185,35 @@ Davis, CA 95616, USA - + - + + - + - + - - + + + - + @@ -208,7 +225,7 @@ Davis, CA 95616, USA - + @@ -216,23 +233,23 @@ Davis, CA 95616, USA - + - + - + - + @@ -240,22 +257,32 @@ Davis, CA 95616, USA - + - + - + + + + + + + + + + + @@ -313,21 +340,47 @@ Davis, CA 95616, USA - + - + - - + + + multiply + + + + subtract + + + + + + + + + + + + + subtract + + + + + + + + @@ -337,8 +390,34 @@ Davis, CA 95616, USA - - + + + multiply + + + + subtract + + + + + + + + + + + + + subtract + + + + + + + + @@ -348,8 +427,30 @@ Davis, CA 95616, USA - - + + + multiply + + + + subtract + + + + + + + + + + + subtract + + + + + + diff --git a/data_model/master/clusters/CameraAVStreamManagement.xml b/data_model/1.5.1/clusters/CameraAVStreamManagement.xml similarity index 91% rename from data_model/master/clusters/CameraAVStreamManagement.xml rename to data_model/1.5.1/clusters/CameraAVStreamManagement.xml index 20400009fc9..1b2f249d4b0 100644 --- a/data_model/master/clusters/CameraAVStreamManagement.xml +++ b/data_model/1.5.1/clusters/CameraAVStreamManagement.xml @@ -62,9 +62,7 @@ Davis, CA 95616, USA - - - + @@ -120,6 +118,14 @@ Davis, CA 95616, USA + + + + + + + + @@ -137,20 +143,9 @@ Davis, CA 95616, USA - - - - - - + - - - - - - @@ -175,19 +170,41 @@ Davis, CA 95616, USA - + - + - + + + + + + + + + + + + + + + + + + + + + + + @@ -248,7 +265,7 @@ Davis, CA 95616, USA - + @@ -263,7 +280,7 @@ Davis, CA 95616, USA - + @@ -301,7 +318,7 @@ Davis, CA 95616, USA - + @@ -334,7 +351,7 @@ Davis, CA 95616, USA - + @@ -343,6 +360,16 @@ Davis, CA 95616, USA + + + + + + + + + + @@ -441,50 +468,26 @@ Davis, CA 95616, USA - - - - - - - - - + - - - + - + - + - - - - - - - - - - - - - - - + @@ -517,14 +520,14 @@ Davis, CA 95616, USA - + - + - + @@ -584,20 +587,20 @@ Davis, CA 95616, USA - + - + - + @@ -605,7 +608,7 @@ Davis, CA 95616, USA - + @@ -613,7 +616,7 @@ Davis, CA 95616, USA - + @@ -621,24 +624,22 @@ Davis, CA 95616, USA - + - - - + - + - + - + - + @@ -650,21 +651,15 @@ Davis, CA 95616, USA - - - - - - + + + - - - - + @@ -674,7 +669,7 @@ Davis, CA 95616, USA - + @@ -723,7 +718,7 @@ Davis, CA 95616, USA - + @@ -803,7 +798,7 @@ Davis, CA 95616, USA - + @@ -813,7 +808,7 @@ Davis, CA 95616, USA - + @@ -842,11 +837,26 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + - + @@ -907,6 +917,21 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + @@ -951,31 +976,21 @@ Davis, CA 95616, USA - - - - - - - - - + - - - + - + - + @@ -1004,14 +1019,14 @@ Davis, CA 95616, USA - + - + - + - + @@ -1052,12 +1067,12 @@ Davis, CA 95616, USA - + - + @@ -1086,14 +1101,14 @@ Davis, CA 95616, USA - + - + - + - + diff --git a/data_model/master/clusters/Channel.xml b/data_model/1.5.1/clusters/Channel.xml similarity index 100% rename from data_model/master/clusters/Channel.xml rename to data_model/1.5.1/clusters/Channel.xml diff --git a/data_model/master/clusters/Chime.xml b/data_model/1.5.1/clusters/Chime.xml similarity index 95% rename from data_model/master/clusters/Chime.xml rename to data_model/1.5.1/clusters/Chime.xml index 7eed47786f7..48bb721d885 100644 --- a/data_model/master/clusters/Chime.xml +++ b/data_model/1.5.1/clusters/Chime.xml @@ -62,9 +62,7 @@ Davis, CA 95616, USA - - - + @@ -96,12 +94,12 @@ Davis, CA 95616, USA - + - + diff --git a/data_model/master/clusters/ClosureControl.xml b/data_model/1.5.1/clusters/ClosureControl.xml similarity index 82% rename from data_model/master/clusters/ClosureControl.xml rename to data_model/1.5.1/clusters/ClosureControl.xml index 066d7d1d2bd..b7e3bfd50fe 100644 --- a/data_model/master/clusters/ClosureControl.xml +++ b/data_model/1.5.1/clusters/ClosureControl.xml @@ -62,9 +62,7 @@ Davis, CA 95616, USA - - - + @@ -114,7 +112,7 @@ Davis, CA 95616, USA - + @@ -127,6 +125,30 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + @@ -159,53 +181,41 @@ Davis, CA 95616, USA - - - - - + + - + - + - + - + - - - - - - - - + + - + - - + + - + - - - - - - - + + + + @@ -214,7 +224,7 @@ Davis, CA 95616, USA - + @@ -224,7 +234,6 @@ Davis, CA 95616, USA - @@ -232,26 +241,28 @@ Davis, CA 95616, USA - + - + - - + + + - + + - + @@ -262,7 +273,14 @@ Davis, CA 95616, USA - + + + + + + + + @@ -279,16 +297,23 @@ Davis, CA 95616, USA - + - + + + + + + + + @@ -300,20 +325,23 @@ Davis, CA 95616, USA - + - + - + + + + - + @@ -337,7 +365,9 @@ Davis, CA 95616, USA - + + + @@ -351,12 +381,7 @@ Davis, CA 95616, USA - - - - - - + diff --git a/data_model/master/clusters/ClosureDimension.xml b/data_model/1.5.1/clusters/ClosureDimension.xml similarity index 79% rename from data_model/master/clusters/ClosureDimension.xml rename to data_model/1.5.1/clusters/ClosureDimension.xml index eeff3d5df94..020c81ae6a5 100644 --- a/data_model/master/clusters/ClosureDimension.xml +++ b/data_model/1.5.1/clusters/ClosureDimension.xml @@ -62,13 +62,11 @@ Davis, CA 95616, USA - - - + - + @@ -89,9 +87,21 @@ Davis, CA 95616, USA - - - + + + + + + + + + + + + + + + @@ -155,37 +165,37 @@ Davis, CA 95616, USA - + - + - + - + - + - + - + - + - + - + - + @@ -234,21 +244,22 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - + + + + + + + + + + + + + + + @@ -256,7 +267,8 @@ Davis, CA 95616, USA - + + @@ -264,7 +276,7 @@ Davis, CA 95616, USA - + @@ -289,47 +301,17 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + @@ -337,7 +319,7 @@ Davis, CA 95616, USA - + @@ -345,7 +327,7 @@ Davis, CA 95616, USA - + @@ -353,8 +335,9 @@ Davis, CA 95616, USA - + + @@ -362,24 +345,26 @@ Davis, CA 95616, USA - + + - + + - + @@ -398,51 +383,59 @@ Davis, CA 95616, USA + + - - - - - - - - - + + + + + + + + + + + + - + - + - + + + + - + @@ -459,7 +452,9 @@ Davis, CA 95616, USA - + + + diff --git a/data_model/master/clusters/ColorControl.xml b/data_model/1.5.1/clusters/ColorControl.xml similarity index 89% rename from data_model/master/clusters/ColorControl.xml rename to data_model/1.5.1/clusters/ColorControl.xml index b2ecd8e5c67..b6108945d6b 100644 --- a/data_model/master/clusters/ColorControl.xml +++ b/data_model/1.5.1/clusters/ColorControl.xml @@ -57,7 +57,7 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + @@ -66,6 +66,8 @@ Davis, CA 95616, USA + + @@ -241,9 +243,9 @@ Davis, CA 95616, USA - + - + @@ -251,9 +253,9 @@ Davis, CA 95616, USA - + - + @@ -269,9 +271,9 @@ Davis, CA 95616, USA - + - + @@ -279,9 +281,9 @@ Davis, CA 95616, USA - + - + @@ -289,20 +291,20 @@ Davis, CA 95616, USA - + - + - + - + @@ -310,12 +312,12 @@ Davis, CA 95616, USA - + - + @@ -601,89 +603,89 @@ Davis, CA 95616, USA - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -694,35 +696,32 @@ Davis, CA 95616, USA - - - - + - + - + - + @@ -750,7 +749,7 @@ Davis, CA 95616, USA - + @@ -766,7 +765,7 @@ Davis, CA 95616, USA - + @@ -801,13 +800,13 @@ Davis, CA 95616, USA - + - + @@ -825,13 +824,13 @@ Davis, CA 95616, USA - + - + @@ -852,13 +851,13 @@ Davis, CA 95616, USA - + - + @@ -882,13 +881,13 @@ Davis, CA 95616, USA - + - + @@ -906,13 +905,13 @@ Davis, CA 95616, USA - + - + @@ -933,13 +932,13 @@ Davis, CA 95616, USA - + - + @@ -969,13 +968,13 @@ Davis, CA 95616, USA - + - + @@ -1005,13 +1004,13 @@ Davis, CA 95616, USA - + - + @@ -1029,13 +1028,13 @@ Davis, CA 95616, USA - + - + @@ -1059,13 +1058,13 @@ Davis, CA 95616, USA - + - + @@ -1089,13 +1088,13 @@ Davis, CA 95616, USA - + - + @@ -1119,13 +1118,13 @@ Davis, CA 95616, USA - + - + @@ -1146,13 +1145,13 @@ Davis, CA 95616, USA - + - + @@ -1179,13 +1178,13 @@ Davis, CA 95616, USA - + - + @@ -1212,13 +1211,13 @@ Davis, CA 95616, USA - + - + @@ -1245,13 +1244,13 @@ Davis, CA 95616, USA - + - + @@ -1267,13 +1266,13 @@ Davis, CA 95616, USA - + - + @@ -1303,13 +1302,13 @@ Davis, CA 95616, USA - + - + @@ -1345,13 +1344,13 @@ Davis, CA 95616, USA - + - + diff --git a/data_model/master/clusters/CommissionerControlCluster.xml b/data_model/1.5.1/clusters/CommissionerControlCluster.xml similarity index 98% rename from data_model/master/clusters/CommissionerControlCluster.xml rename to data_model/1.5.1/clusters/CommissionerControlCluster.xml index a0d392a652b..6082e2f905d 100644 --- a/data_model/master/clusters/CommissionerControlCluster.xml +++ b/data_model/1.5.1/clusters/CommissionerControlCluster.xml @@ -124,6 +124,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/master/clusters/CommodityMetering.xml b/data_model/1.5.1/clusters/CommodityMetering.xml similarity index 89% rename from data_model/master/clusters/CommodityMetering.xml rename to data_model/1.5.1/clusters/CommodityMetering.xml index 1ccb979c1e6..785d9112663 100644 --- a/data_model/master/clusters/CommodityMetering.xml +++ b/data_model/1.5.1/clusters/CommodityMetering.xml @@ -64,12 +64,15 @@ Davis, CA 95616, USA - + + + + @@ -82,16 +85,29 @@ Davis, CA 95616, USA + + + + + - + + + + + + + + + diff --git a/data_model/master/clusters/CommodityPrice.xml b/data_model/1.5.1/clusters/CommodityPrice.xml similarity index 89% rename from data_model/master/clusters/CommodityPrice.xml rename to data_model/1.5.1/clusters/CommodityPrice.xml index 233386dfcad..56ee9dc642d 100644 --- a/data_model/master/clusters/CommodityPrice.xml +++ b/data_model/1.5.1/clusters/CommodityPrice.xml @@ -65,9 +65,7 @@ Davis, CA 95616, USA - - - + @@ -108,19 +106,35 @@ Davis, CA 95616, USA + + + + add + + + + + + + - - + + + + + - + - + - + + + @@ -148,6 +162,9 @@ Davis, CA 95616, USA + + + @@ -168,6 +185,7 @@ Davis, CA 95616, USA + @@ -177,12 +195,16 @@ Davis, CA 95616, USA + + + + @@ -191,14 +213,7 @@ Davis, CA 95616, USA - - - - - - - - + diff --git a/data_model/master/clusters/CommodityTariff.xml b/data_model/1.5.1/clusters/CommodityTariff.xml similarity index 94% rename from data_model/master/clusters/CommodityTariff.xml rename to data_model/1.5.1/clusters/CommodityTariff.xml index 9570b5ed2a3..4638a72546c 100644 --- a/data_model/master/clusters/CommodityTariff.xml +++ b/data_model/1.5.1/clusters/CommodityTariff.xml @@ -227,7 +227,15 @@ Davis, CA 95616, USA - + + + subtract + + + + + + @@ -294,31 +302,31 @@ Davis, CA 95616, USA - + - + - + - + - + - + @@ -424,12 +432,18 @@ Davis, CA 95616, USA + + + + + + @@ -488,7 +502,10 @@ Davis, CA 95616, USA - + + + + @@ -497,7 +514,10 @@ Davis, CA 95616, USA - + + + + @@ -505,12 +525,18 @@ Davis, CA 95616, USA + + + + + + @@ -551,7 +577,10 @@ Davis, CA 95616, USA - + + + + diff --git a/data_model/master/clusters/ConcentrationMeasurement.xml b/data_model/1.5.1/clusters/ConcentrationMeasurement.xml similarity index 95% rename from data_model/master/clusters/ConcentrationMeasurement.xml rename to data_model/1.5.1/clusters/ConcentrationMeasurement.xml index ec8b39a55aa..190ffa82d2b 100644 --- a/data_model/master/clusters/ConcentrationMeasurement.xml +++ b/data_model/1.5.1/clusters/ConcentrationMeasurement.xml @@ -57,11 +57,12 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -181,9 +182,9 @@ Davis, CA 95616, USA - + - + @@ -198,14 +199,14 @@ Davis, CA 95616, USA - + - + @@ -217,9 +218,9 @@ Davis, CA 95616, USA - + - + @@ -234,9 +235,8 @@ Davis, CA 95616, USA - + - @@ -244,9 +244,9 @@ Davis, CA 95616, USA - + - + @@ -261,9 +261,8 @@ Davis, CA 95616, USA - + - @@ -280,19 +279,19 @@ Davis, CA 95616, USA - + - + - + diff --git a/data_model/master/clusters/ContentAppObserver.xml b/data_model/1.5.1/clusters/ContentAppObserver.xml similarity index 100% rename from data_model/master/clusters/ContentAppObserver.xml rename to data_model/1.5.1/clusters/ContentAppObserver.xml diff --git a/data_model/master/clusters/ContentControl.xml b/data_model/1.5.1/clusters/ContentControl.xml similarity index 100% rename from data_model/master/clusters/ContentControl.xml rename to data_model/1.5.1/clusters/ContentControl.xml diff --git a/data_model/master/clusters/ContentLauncher.xml b/data_model/1.5.1/clusters/ContentLauncher.xml similarity index 100% rename from data_model/master/clusters/ContentLauncher.xml rename to data_model/1.5.1/clusters/ContentLauncher.xml diff --git a/data_model/master/clusters/Descriptor-Cluster.xml b/data_model/1.5.1/clusters/Descriptor-Cluster.xml similarity index 98% rename from data_model/master/clusters/Descriptor-Cluster.xml rename to data_model/1.5.1/clusters/Descriptor-Cluster.xml index fbef6914fe4..475dd6f8d57 100644 --- a/data_model/master/clusters/Descriptor-Cluster.xml +++ b/data_model/1.5.1/clusters/Descriptor-Cluster.xml @@ -129,10 +129,7 @@ Davis, CA 95616, USA - - - - + diff --git a/data_model/master/clusters/DeviceEnergyManagement.xml b/data_model/1.5.1/clusters/DeviceEnergyManagement.xml similarity index 95% rename from data_model/master/clusters/DeviceEnergyManagement.xml rename to data_model/1.5.1/clusters/DeviceEnergyManagement.xml index 0fd114ced76..87946abe764 100644 --- a/data_model/master/clusters/DeviceEnergyManagement.xml +++ b/data_model/1.5.1/clusters/DeviceEnergyManagement.xml @@ -287,13 +287,13 @@ Davis, CA 95616, USA - + - + - + @@ -304,10 +304,10 @@ Davis, CA 95616, USA - + - + @@ -343,7 +343,7 @@ Davis, CA 95616, USA - + @@ -351,15 +351,15 @@ Davis, CA 95616, USA - + - + - + @@ -367,7 +367,7 @@ Davis, CA 95616, USA - + @@ -494,30 +494,27 @@ Davis, CA 95616, USA - - - - + - + - + - + @@ -526,14 +523,14 @@ Davis, CA 95616, USA - + - + @@ -543,7 +540,7 @@ Davis, CA 95616, USA - + @@ -684,7 +681,7 @@ Davis, CA 95616, USA - + @@ -705,7 +702,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/DiagnosticLogsCluster.xml b/data_model/1.5.1/clusters/DiagnosticLogsCluster.xml similarity index 98% rename from data_model/master/clusters/DiagnosticLogsCluster.xml rename to data_model/1.5.1/clusters/DiagnosticLogsCluster.xml index b5edc2489c9..74031d793ba 100644 --- a/data_model/master/clusters/DiagnosticLogsCluster.xml +++ b/data_model/1.5.1/clusters/DiagnosticLogsCluster.xml @@ -83,7 +83,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/DiagnosticsEthernet.xml b/data_model/1.5.1/clusters/DiagnosticsEthernet.xml similarity index 100% rename from data_model/master/clusters/DiagnosticsEthernet.xml rename to data_model/1.5.1/clusters/DiagnosticsEthernet.xml diff --git a/data_model/master/clusters/DiagnosticsGeneral.xml b/data_model/1.5.1/clusters/DiagnosticsGeneral.xml similarity index 99% rename from data_model/master/clusters/DiagnosticsGeneral.xml rename to data_model/1.5.1/clusters/DiagnosticsGeneral.xml index a5b75aeef4d..b8d6de81083 100644 --- a/data_model/master/clusters/DiagnosticsGeneral.xml +++ b/data_model/1.5.1/clusters/DiagnosticsGeneral.xml @@ -60,7 +60,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/DiagnosticsSoftware.xml b/data_model/1.5.1/clusters/DiagnosticsSoftware.xml similarity index 100% rename from data_model/master/clusters/DiagnosticsSoftware.xml rename to data_model/1.5.1/clusters/DiagnosticsSoftware.xml diff --git a/data_model/master/clusters/DiagnosticsThread.xml b/data_model/1.5.1/clusters/DiagnosticsThread.xml similarity index 99% rename from data_model/master/clusters/DiagnosticsThread.xml rename to data_model/1.5.1/clusters/DiagnosticsThread.xml index 9874ffcd080..c14db197e1c 100644 --- a/data_model/master/clusters/DiagnosticsThread.xml +++ b/data_model/1.5.1/clusters/DiagnosticsThread.xml @@ -317,6 +317,12 @@ Davis, CA 95616, USA + + + + + + diff --git a/data_model/master/clusters/DiagnosticsWiFi.xml b/data_model/1.5.1/clusters/DiagnosticsWiFi.xml similarity index 100% rename from data_model/master/clusters/DiagnosticsWiFi.xml rename to data_model/1.5.1/clusters/DiagnosticsWiFi.xml diff --git a/data_model/master/clusters/DishwasherAlarm.xml b/data_model/1.5.1/clusters/DishwasherAlarm.xml similarity index 100% rename from data_model/master/clusters/DishwasherAlarm.xml rename to data_model/1.5.1/clusters/DishwasherAlarm.xml diff --git a/data_model/master/clusters/DoorLock.xml b/data_model/1.5.1/clusters/DoorLock.xml similarity index 83% rename from data_model/master/clusters/DoorLock.xml rename to data_model/1.5.1/clusters/DoorLock.xml index f2b8d62ee4e..f8353b20d18 100644 --- a/data_model/master/clusters/DoorLock.xml +++ b/data_model/1.5.1/clusters/DoorLock.xml @@ -57,7 +57,7 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + @@ -68,6 +68,7 @@ Davis, CA 95616, USA + @@ -78,7 +79,10 @@ Davis, CA 95616, USA - + + + + @@ -102,19 +106,15 @@ Davis, CA 95616, USA - - + + + + + + - - - - - - - - - - + + @@ -125,10 +125,10 @@ Davis, CA 95616, USA - + - + @@ -215,17 +215,17 @@ Davis, CA 95616, USA - + - + - + @@ -509,7 +509,7 @@ Davis, CA 95616, USA - + @@ -711,7 +711,7 @@ Davis, CA 95616, USA - + @@ -719,7 +719,7 @@ Davis, CA 95616, USA - + @@ -738,7 +738,7 @@ Davis, CA 95616, USA - + @@ -764,28 +764,28 @@ Davis, CA 95616, USA - + - + - + - + @@ -795,7 +795,7 @@ Davis, CA 95616, USA - + @@ -805,7 +805,7 @@ Davis, CA 95616, USA - + @@ -815,42 +815,42 @@ Davis, CA 95616, USA - + - + - + - + - + - + @@ -859,7 +859,6 @@ Davis, CA 95616, USA - @@ -867,65 +866,54 @@ Davis, CA 95616, USA - - - - + - - + - - - - - - - + - @@ -939,9 +927,8 @@ Davis, CA 95616, USA - + - @@ -957,7 +944,6 @@ Davis, CA 95616, USA - @@ -967,9 +953,8 @@ Davis, CA 95616, USA - + - @@ -983,7 +968,6 @@ Davis, CA 95616, USA - @@ -994,7 +978,7 @@ Davis, CA 95616, USA - + @@ -1004,7 +988,7 @@ Davis, CA 95616, USA - + @@ -1024,7 +1008,7 @@ Davis, CA 95616, USA - + @@ -1039,7 +1023,7 @@ Davis, CA 95616, USA - + @@ -1049,7 +1033,7 @@ Davis, CA 95616, USA - + @@ -1064,21 +1048,21 @@ Davis, CA 95616, USA - + - + - + @@ -1130,197 +1114,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1430,7 +1223,7 @@ Davis, CA 95616, USA - + @@ -1583,7 +1376,7 @@ Davis, CA 95616, USA - + @@ -1685,7 +1478,7 @@ Davis, CA 95616, USA - + @@ -1724,197 +1517,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1944,21 +1546,18 @@ Davis, CA 95616, USA - + - + - - - @@ -1973,9 +1572,6 @@ Davis, CA 95616, USA - - - @@ -2015,9 +1611,6 @@ Davis, CA 95616, USA - - - @@ -2054,35 +1647,26 @@ Davis, CA 95616, USA - + - + - - - - - - - - - @@ -2183,9 +1767,6 @@ Davis, CA 95616, USA - - - @@ -2200,9 +1781,6 @@ Davis, CA 95616, USA - - - @@ -2252,7 +1830,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/EcosystemInformationCluster.xml b/data_model/1.5.1/clusters/EcosystemInformationCluster.xml similarity index 95% rename from data_model/master/clusters/EcosystemInformationCluster.xml rename to data_model/1.5.1/clusters/EcosystemInformationCluster.xml index f5ecc9a7a72..8a2e5e934a0 100644 --- a/data_model/master/clusters/EcosystemInformationCluster.xml +++ b/data_model/1.5.1/clusters/EcosystemInformationCluster.xml @@ -66,6 +66,17 @@ Davis, CA 95616, USA + + + + + + + + + + + diff --git a/data_model/master/clusters/ElectricalEnergyMeasurement.xml b/data_model/1.5.1/clusters/ElectricalEnergyMeasurement.xml similarity index 63% rename from data_model/master/clusters/ElectricalEnergyMeasurement.xml rename to data_model/1.5.1/clusters/ElectricalEnergyMeasurement.xml index 6ec89010b6a..5a6f1707e25 100644 --- a/data_model/master/clusters/ElectricalEnergyMeasurement.xml +++ b/data_model/1.5.1/clusters/ElectricalEnergyMeasurement.xml @@ -93,6 +93,59 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -135,7 +188,15 @@ Davis, CA 95616, USA - + + + add + + + + + + @@ -144,7 +205,15 @@ Davis, CA 95616, USA - + + + add + + + + + + @@ -176,6 +245,124 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + subtract + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -183,7 +370,7 @@ Davis, CA 95616, USA - + @@ -193,7 +380,7 @@ Davis, CA 95616, USA - + @@ -203,7 +390,7 @@ Davis, CA 95616, USA - + @@ -213,7 +400,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/ThreadBorderRouterDiagnostics.xml b/data_model/1.5.1/clusters/ElectricalGridConditions.xml similarity index 63% rename from data_model/master/clusters/ThreadBorderRouterDiagnostics.xml rename to data_model/1.5.1/clusters/ElectricalGridConditions.xml index a62d41572cc..11317fc3657 100644 --- a/data_model/master/clusters/ThreadBorderRouterDiagnostics.xml +++ b/data_model/1.5.1/clusters/ElectricalGridConditions.xml @@ -57,53 +57,94 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + - + - + - + + + + + + - - + + - + - + - - + + - - + + + - - + + + + add + + + + + + + + + - - + + - - + + + + + + + + - - + + + - - + + + + + + + + + - + + + + + + + + + + + diff --git a/data_model/master/clusters/ElectricalPowerMeasurement.xml b/data_model/1.5.1/clusters/ElectricalPowerMeasurement.xml similarity index 68% rename from data_model/master/clusters/ElectricalPowerMeasurement.xml rename to data_model/1.5.1/clusters/ElectricalPowerMeasurement.xml index c28e75a5be4..3349108215d 100644 --- a/data_model/master/clusters/ElectricalPowerMeasurement.xml +++ b/data_model/1.5.1/clusters/ElectricalPowerMeasurement.xml @@ -91,6 +91,59 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -103,13 +156,13 @@ Davis, CA 95616, USA - + - + @@ -120,6 +173,124 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + subtract + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -150,7 +321,15 @@ Davis, CA 95616, USA - + + + add + + + + + + @@ -163,7 +342,15 @@ Davis, CA 95616, USA - + + + add + + + + + + @@ -174,7 +361,15 @@ Davis, CA 95616, USA - + + + add + + + + + + @@ -187,7 +382,15 @@ Davis, CA 95616, USA - + + + add + + + + + + @@ -202,7 +405,7 @@ Davis, CA 95616, USA - + @@ -281,7 +484,7 @@ Davis, CA 95616, USA - + @@ -370,7 +573,7 @@ Davis, CA 95616, USA - + @@ -378,10 +581,10 @@ Davis, CA 95616, USA - + - + @@ -389,7 +592,7 @@ Davis, CA 95616, USA - + @@ -428,6 +631,14 @@ Davis, CA 95616, USA + + + + + + + + diff --git a/data_model/master/clusters/EnergyEVSE.xml b/data_model/1.5.1/clusters/EnergyEVSE.xml similarity index 95% rename from data_model/master/clusters/EnergyEVSE.xml rename to data_model/1.5.1/clusters/EnergyEVSE.xml index 203fab75022..8951f4228c7 100644 --- a/data_model/master/clusters/EnergyEVSE.xml +++ b/data_model/1.5.1/clusters/EnergyEVSE.xml @@ -57,11 +57,12 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -72,25 +73,16 @@ Davis, CA 95616, USA - - - - + - - - - + - - - - + @@ -243,7 +235,7 @@ Davis, CA 95616, USA - + @@ -284,19 +276,19 @@ Davis, CA 95616, USA - + - + - + @@ -304,7 +296,7 @@ Davis, CA 95616, USA - + @@ -312,7 +304,7 @@ Davis, CA 95616, USA - + @@ -320,7 +312,7 @@ Davis, CA 95616, USA - + @@ -346,21 +338,21 @@ Davis, CA 95616, USA - + - + - + @@ -370,7 +362,7 @@ Davis, CA 95616, USA - + @@ -387,14 +379,14 @@ Davis, CA 95616, USA - + - + @@ -404,7 +396,7 @@ Davis, CA 95616, USA - + @@ -414,17 +406,17 @@ Davis, CA 95616, USA - + - + - + @@ -432,7 +424,7 @@ Davis, CA 95616, USA - + @@ -463,7 +455,7 @@ Davis, CA 95616, USA - + @@ -485,7 +477,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/EnergyPreference.xml b/data_model/1.5.1/clusters/EnergyPreference.xml similarity index 99% rename from data_model/master/clusters/EnergyPreference.xml rename to data_model/1.5.1/clusters/EnergyPreference.xml index 26c17221027..3ee60dc5be5 100644 --- a/data_model/master/clusters/EnergyPreference.xml +++ b/data_model/1.5.1/clusters/EnergyPreference.xml @@ -91,7 +91,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/FanControl.xml b/data_model/1.5.1/clusters/FanControl.xml similarity index 91% rename from data_model/master/clusters/FanControl.xml rename to data_model/1.5.1/clusters/FanControl.xml index f45aef70174..cb10bc88925 100644 --- a/data_model/master/clusters/FanControl.xml +++ b/data_model/1.5.1/clusters/FanControl.xml @@ -57,13 +57,14 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -192,7 +193,7 @@ Davis, CA 95616, USA - + @@ -200,12 +201,12 @@ Davis, CA 95616, USA - + - + @@ -213,14 +214,14 @@ Davis, CA 95616, USA - + - + @@ -233,7 +234,7 @@ Davis, CA 95616, USA - + @@ -245,9 +246,8 @@ Davis, CA 95616, USA - + - @@ -257,7 +257,7 @@ Davis, CA 95616, USA - + @@ -267,9 +267,8 @@ Davis, CA 95616, USA - + - @@ -277,7 +276,7 @@ Davis, CA 95616, USA - + @@ -287,9 +286,8 @@ Davis, CA 95616, USA - + - @@ -297,9 +295,8 @@ Davis, CA 95616, USA - + - @@ -312,9 +309,6 @@ Davis, CA 95616, USA - - - diff --git a/data_model/master/clusters/FixedLabel-Cluster.xml b/data_model/1.5.1/clusters/FixedLabel-Cluster.xml similarity index 100% rename from data_model/master/clusters/FixedLabel-Cluster.xml rename to data_model/1.5.1/clusters/FixedLabel-Cluster.xml diff --git a/data_model/master/clusters/FlowMeasurement.xml b/data_model/1.5.1/clusters/FlowMeasurement.xml similarity index 92% rename from data_model/master/clusters/FlowMeasurement.xml rename to data_model/1.5.1/clusters/FlowMeasurement.xml index 705917c8a6a..e001c80913c 100644 --- a/data_model/master/clusters/FlowMeasurement.xml +++ b/data_model/1.5.1/clusters/FlowMeasurement.xml @@ -57,20 +57,21 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + - + - + @@ -96,7 +97,15 @@ Davis, CA 95616, USA - + + + add + + + + + + diff --git a/data_model/master/clusters/GeneralCommissioningCluster.xml b/data_model/1.5.1/clusters/GeneralCommissioningCluster.xml similarity index 89% rename from data_model/master/clusters/GeneralCommissioningCluster.xml rename to data_model/1.5.1/clusters/GeneralCommissioningCluster.xml index ed44f942d86..a68c4e1510d 100644 --- a/data_model/master/clusters/GeneralCommissioningCluster.xml +++ b/data_model/1.5.1/clusters/GeneralCommissioningCluster.xml @@ -68,10 +68,13 @@ Davis, CA 95616, USA - + - + + + + @@ -177,67 +180,39 @@ Davis, CA 95616, USA - - - - - - + + + - - - - - - + + + - - - - - - + + + - - - - - - + + + - - - - - - + + + - - - - - - - - - - - - - - + @@ -250,7 +225,7 @@ Davis, CA 95616, USA - + @@ -260,6 +235,13 @@ Davis, CA 95616, USA + + + + + + + @@ -324,12 +306,9 @@ Davis, CA 95616, USA - - - - - - + + + @@ -338,12 +317,9 @@ Davis, CA 95616, USA - - - - - - + + + diff --git a/data_model/master/clusters/Group-Key-Management-Cluster.xml b/data_model/1.5.1/clusters/Group-Key-Management-Cluster.xml similarity index 96% rename from data_model/master/clusters/Group-Key-Management-Cluster.xml rename to data_model/1.5.1/clusters/Group-Key-Management-Cluster.xml index 31b3fb153e8..1ebe5130841 100644 --- a/data_model/master/clusters/Group-Key-Management-Cluster.xml +++ b/data_model/1.5.1/clusters/Group-Key-Management-Cluster.xml @@ -129,11 +129,9 @@ Davis, CA 95616, USA - - @@ -141,12 +139,10 @@ Davis, CA 95616, USA - - @@ -154,12 +150,10 @@ Davis, CA 95616, USA - - @@ -167,17 +161,16 @@ Davis, CA 95616, USA - - + diff --git a/data_model/master/clusters/Groups.xml b/data_model/1.5.1/clusters/Groups.xml similarity index 99% rename from data_model/master/clusters/Groups.xml rename to data_model/1.5.1/clusters/Groups.xml index e580c607c27..1be23beef1f 100644 --- a/data_model/master/clusters/Groups.xml +++ b/data_model/1.5.1/clusters/Groups.xml @@ -81,7 +81,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/ICDManagement.xml b/data_model/1.5.1/clusters/ICDManagement.xml similarity index 100% rename from data_model/master/clusters/ICDManagement.xml rename to data_model/1.5.1/clusters/ICDManagement.xml diff --git a/data_model/master/clusters/Identify.xml b/data_model/1.5.1/clusters/Identify.xml similarity index 96% rename from data_model/master/clusters/Identify.xml rename to data_model/1.5.1/clusters/Identify.xml index 4e334059260..a919486e30f 100644 --- a/data_model/master/clusters/Identify.xml +++ b/data_model/1.5.1/clusters/Identify.xml @@ -57,13 +57,14 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -117,11 +118,12 @@ Davis, CA 95616, USA - + + - + diff --git a/data_model/master/clusters/IlluminanceMeasurement.xml b/data_model/1.5.1/clusters/IlluminanceMeasurement.xml similarity index 92% rename from data_model/master/clusters/IlluminanceMeasurement.xml rename to data_model/1.5.1/clusters/IlluminanceMeasurement.xml index 37d9b5b6779..89e74089a4e 100644 --- a/data_model/master/clusters/IlluminanceMeasurement.xml +++ b/data_model/1.5.1/clusters/IlluminanceMeasurement.xml @@ -57,11 +57,12 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -78,9 +79,9 @@ Davis, CA 95616, USA - + - + @@ -112,7 +113,15 @@ Davis, CA 95616, USA - + + + add + + + + + + diff --git a/data_model/master/clusters/JointFabricPKICluster.xml b/data_model/1.5.1/clusters/JointFabricAdministratorCluster.xml similarity index 50% rename from data_model/master/clusters/JointFabricPKICluster.xml rename to data_model/1.5.1/clusters/JointFabricAdministratorCluster.xml index 3e703831c6f..7a75190ee72 100644 --- a/data_model/master/clusters/JointFabricPKICluster.xml +++ b/data_model/1.5.1/clusters/JointFabricAdministratorCluster.xml @@ -57,41 +57,58 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + - + - + - + - + - - + + + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + @@ -106,42 +123,139 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + - - + + + + + - - - + + + + + + - - + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + - - + + + + + - + - + + + + + + + + + + + + + + diff --git a/data_model/master/clusters/JointFabricDatastoreCluster.xml b/data_model/1.5.1/clusters/JointFabricDatastoreCluster.xml similarity index 58% rename from data_model/master/clusters/JointFabricDatastoreCluster.xml rename to data_model/1.5.1/clusters/JointFabricDatastoreCluster.xml index 54f86420bfe..5af24d1cf97 100644 --- a/data_model/master/clusters/JointFabricDatastoreCluster.xml +++ b/data_model/1.5.1/clusters/JointFabricDatastoreCluster.xml @@ -68,6 +68,47 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -89,13 +130,54 @@ Davis, CA 95616, USA - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -116,7 +198,33 @@ Davis, CA 95616, USA - + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -128,7 +236,7 @@ Davis, CA 95616, USA - + @@ -137,7 +245,6 @@ Davis, CA 95616, USA - @@ -155,7 +262,6 @@ Davis, CA 95616, USA - @@ -170,7 +276,6 @@ Davis, CA 95616, USA - @@ -183,36 +288,82 @@ Davis, CA 95616, USA + - + + - - - - + + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -227,9 +378,8 @@ Davis, CA 95616, USA - - + @@ -239,116 +389,168 @@ Davis, CA 95616, USA - - + - + - - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - - + + + + + + - - + + + + + - - + + + + + - - + + + + + - - - + + + + + + - - + + + + + - - + + + + + - - - + + + + + + - - + + + + + - - + + + + + - - - + + + + + + - - - + + + + + + - - + + + + + - - + + + + + @@ -359,39 +561,42 @@ Davis, CA 95616, USA + - + + - - - - + + - + - + - - + + + + + @@ -416,10 +621,7 @@ Davis, CA 95616, USA - - - - + @@ -432,27 +634,52 @@ Davis, CA 95616, USA - + + - - + + + + + - - - + + + + + + + + + + + + + + + + + + + + + - - + + + + + @@ -473,15 +700,21 @@ Davis, CA 95616, USA - - + + + + + - - + + + + + @@ -493,15 +726,21 @@ Davis, CA 95616, USA - - + + + + + - - + + + + + @@ -513,15 +752,21 @@ Davis, CA 95616, USA - - + + + + + - - + + + + + @@ -536,8 +781,11 @@ Davis, CA 95616, USA - - + + + + + @@ -549,8 +797,11 @@ Davis, CA 95616, USA - - + + + + + @@ -562,21 +813,27 @@ Davis, CA 95616, USA - - + + + + + - + - - + + + + + @@ -588,18 +845,24 @@ Davis, CA 95616, USA - - + + + + + - + - - + + + + + diff --git a/data_model/master/clusters/KeypadInput.xml b/data_model/1.5.1/clusters/KeypadInput.xml similarity index 100% rename from data_model/master/clusters/KeypadInput.xml rename to data_model/1.5.1/clusters/KeypadInput.xml diff --git a/data_model/master/clusters/Label-Cluster.xml b/data_model/1.5.1/clusters/Label-Cluster.xml similarity index 98% rename from data_model/master/clusters/Label-Cluster.xml rename to data_model/1.5.1/clusters/Label-Cluster.xml index b9cd9e7f440..e116355b67e 100644 --- a/data_model/master/clusters/Label-Cluster.xml +++ b/data_model/1.5.1/clusters/Label-Cluster.xml @@ -82,7 +82,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/LaundryDryerControls.xml b/data_model/1.5.1/clusters/LaundryDryerControls.xml similarity index 99% rename from data_model/master/clusters/LaundryDryerControls.xml rename to data_model/1.5.1/clusters/LaundryDryerControls.xml index b7549bbeadf..37cf87d481b 100644 --- a/data_model/master/clusters/LaundryDryerControls.xml +++ b/data_model/1.5.1/clusters/LaundryDryerControls.xml @@ -93,7 +93,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/LaundryWasherControls.xml b/data_model/1.5.1/clusters/LaundryWasherControls.xml similarity index 98% rename from data_model/master/clusters/LaundryWasherControls.xml rename to data_model/1.5.1/clusters/LaundryWasherControls.xml index 350b5c0da4f..00cc966b119 100644 --- a/data_model/master/clusters/LaundryWasherControls.xml +++ b/data_model/1.5.1/clusters/LaundryWasherControls.xml @@ -113,7 +113,7 @@ Davis, CA 95616, USA - + @@ -123,7 +123,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/LevelControl.xml b/data_model/1.5.1/clusters/LevelControl.xml similarity index 87% rename from data_model/master/clusters/LevelControl.xml rename to data_model/1.5.1/clusters/LevelControl.xml index e25c7fc3bbd..bd9ef59feaf 100644 --- a/data_model/master/clusters/LevelControl.xml +++ b/data_model/1.5.1/clusters/LevelControl.xml @@ -57,7 +57,7 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + @@ -65,6 +65,7 @@ Davis, CA 95616, USA + @@ -115,7 +116,7 @@ Davis, CA 95616, USA - + @@ -130,7 +131,7 @@ Davis, CA 95616, USA - + @@ -139,30 +140,32 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - + + + + + + + + + + - + + + + + + + + + + @@ -172,9 +175,9 @@ Davis, CA 95616, USA - + - + @@ -189,13 +192,13 @@ Davis, CA 95616, USA - + - + @@ -206,7 +209,7 @@ Davis, CA 95616, USA - + @@ -217,7 +220,7 @@ Davis, CA 95616, USA - + @@ -250,7 +253,7 @@ Davis, CA 95616, USA - + @@ -275,13 +278,13 @@ Davis, CA 95616, USA - + - + @@ -301,13 +304,13 @@ Davis, CA 95616, USA - + - + @@ -330,13 +333,13 @@ Davis, CA 95616, USA - + - + @@ -346,13 +349,13 @@ Davis, CA 95616, USA - + - + @@ -380,7 +383,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/LocalizationConfiguration.xml b/data_model/1.5.1/clusters/LocalizationConfiguration.xml similarity index 100% rename from data_model/master/clusters/LocalizationConfiguration.xml rename to data_model/1.5.1/clusters/LocalizationConfiguration.xml diff --git a/data_model/master/clusters/LocalizationTimeFormat.xml b/data_model/1.5.1/clusters/LocalizationTimeFormat.xml similarity index 99% rename from data_model/master/clusters/LocalizationTimeFormat.xml rename to data_model/1.5.1/clusters/LocalizationTimeFormat.xml index a9b3c47acce..946d553194d 100644 --- a/data_model/master/clusters/LocalizationTimeFormat.xml +++ b/data_model/1.5.1/clusters/LocalizationTimeFormat.xml @@ -137,7 +137,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/LocalizationUnit.xml b/data_model/1.5.1/clusters/LocalizationUnit.xml similarity index 100% rename from data_model/master/clusters/LocalizationUnit.xml rename to data_model/1.5.1/clusters/LocalizationUnit.xml diff --git a/data_model/master/clusters/LowPower.xml b/data_model/1.5.1/clusters/LowPower.xml similarity index 100% rename from data_model/master/clusters/LowPower.xml rename to data_model/1.5.1/clusters/LowPower.xml diff --git a/data_model/master/clusters/MediaInput.xml b/data_model/1.5.1/clusters/MediaInput.xml similarity index 100% rename from data_model/master/clusters/MediaInput.xml rename to data_model/1.5.1/clusters/MediaInput.xml diff --git a/data_model/master/clusters/MediaPlayback.xml b/data_model/1.5.1/clusters/MediaPlayback.xml similarity index 100% rename from data_model/master/clusters/MediaPlayback.xml rename to data_model/1.5.1/clusters/MediaPlayback.xml diff --git a/data_model/master/clusters/Messages.xml b/data_model/1.5.1/clusters/Messages.xml similarity index 93% rename from data_model/master/clusters/Messages.xml rename to data_model/1.5.1/clusters/Messages.xml index 780b77f6b43..186e4cf81a6 100644 --- a/data_model/master/clusters/Messages.xml +++ b/data_model/1.5.1/clusters/Messages.xml @@ -166,20 +166,20 @@ Davis, CA 95616, USA - + - + - + - + @@ -191,7 +191,7 @@ Davis, CA 95616, USA - + @@ -205,7 +205,7 @@ Davis, CA 95616, USA - + @@ -213,7 +213,7 @@ Davis, CA 95616, USA - + @@ -232,17 +232,17 @@ Davis, CA 95616, USA - + - + - + - + @@ -252,7 +252,7 @@ Davis, CA 95616, USA - + @@ -304,13 +304,13 @@ Davis, CA 95616, USA - + - + @@ -319,7 +319,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/MeterIdentification.xml b/data_model/1.5.1/clusters/MeterIdentification.xml similarity index 98% rename from data_model/master/clusters/MeterIdentification.xml rename to data_model/1.5.1/clusters/MeterIdentification.xml index 378bab02464..ebb0bcf7e78 100644 --- a/data_model/master/clusters/MeterIdentification.xml +++ b/data_model/1.5.1/clusters/MeterIdentification.xml @@ -62,9 +62,7 @@ Davis, CA 95616, USA - - - + diff --git a/data_model/master/clusters/MicrowaveOvenControl.xml b/data_model/1.5.1/clusters/MicrowaveOvenControl.xml similarity index 93% rename from data_model/master/clusters/MicrowaveOvenControl.xml rename to data_model/1.5.1/clusters/MicrowaveOvenControl.xml index c21477f22ca..11ade34f267 100644 --- a/data_model/master/clusters/MicrowaveOvenControl.xml +++ b/data_model/1.5.1/clusters/MicrowaveOvenControl.xml @@ -82,7 +82,7 @@ Davis, CA 95616, USA - + @@ -94,7 +94,7 @@ Davis, CA 95616, USA - + @@ -105,7 +105,7 @@ Davis, CA 95616, USA - + @@ -114,7 +114,7 @@ Davis, CA 95616, USA - + @@ -127,7 +127,7 @@ Davis, CA 95616, USA - + @@ -135,12 +135,20 @@ Davis, CA 95616, USA - + + + add + + + + + + - + @@ -150,7 +158,7 @@ Davis, CA 95616, USA - + @@ -167,7 +175,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/ModeBase.xml b/data_model/1.5.1/clusters/ModeBase.xml similarity index 94% rename from data_model/master/clusters/ModeBase.xml rename to data_model/1.5.1/clusters/ModeBase.xml index cb5bb200468..f0fb5498f67 100644 --- a/data_model/master/clusters/ModeBase.xml +++ b/data_model/1.5.1/clusters/ModeBase.xml @@ -73,18 +73,18 @@ Davis, CA 95616, USA - + - + - + @@ -106,7 +106,7 @@ Davis, CA 95616, USA - + @@ -118,7 +118,7 @@ Davis, CA 95616, USA - + @@ -134,7 +134,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/ModeSelect.xml b/data_model/1.5.1/clusters/ModeSelect.xml similarity index 100% rename from data_model/master/clusters/ModeSelect.xml rename to data_model/1.5.1/clusters/ModeSelect.xml diff --git a/data_model/master/clusters/Mode_DeviceEnergyManagement.xml b/data_model/1.5.1/clusters/Mode_DeviceEnergyManagement.xml similarity index 100% rename from data_model/master/clusters/Mode_DeviceEnergyManagement.xml rename to data_model/1.5.1/clusters/Mode_DeviceEnergyManagement.xml diff --git a/data_model/master/clusters/Mode_Dishwasher.xml b/data_model/1.5.1/clusters/Mode_Dishwasher.xml similarity index 100% rename from data_model/master/clusters/Mode_Dishwasher.xml rename to data_model/1.5.1/clusters/Mode_Dishwasher.xml diff --git a/data_model/master/clusters/Mode_EVSE.xml b/data_model/1.5.1/clusters/Mode_EVSE.xml similarity index 100% rename from data_model/master/clusters/Mode_EVSE.xml rename to data_model/1.5.1/clusters/Mode_EVSE.xml diff --git a/data_model/master/clusters/Mode_LaundryWasher.xml b/data_model/1.5.1/clusters/Mode_LaundryWasher.xml similarity index 100% rename from data_model/master/clusters/Mode_LaundryWasher.xml rename to data_model/1.5.1/clusters/Mode_LaundryWasher.xml diff --git a/data_model/master/clusters/Mode_MicrowaveOven.xml b/data_model/1.5.1/clusters/Mode_MicrowaveOven.xml similarity index 100% rename from data_model/master/clusters/Mode_MicrowaveOven.xml rename to data_model/1.5.1/clusters/Mode_MicrowaveOven.xml diff --git a/data_model/master/clusters/Mode_Oven.xml b/data_model/1.5.1/clusters/Mode_Oven.xml similarity index 97% rename from data_model/master/clusters/Mode_Oven.xml rename to data_model/1.5.1/clusters/Mode_Oven.xml index d7180d0e634..669560acb02 100644 --- a/data_model/master/clusters/Mode_Oven.xml +++ b/data_model/1.5.1/clusters/Mode_Oven.xml @@ -93,6 +93,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/master/clusters/Mode_RVCClean.xml b/data_model/1.5.1/clusters/Mode_RVCClean.xml similarity index 95% rename from data_model/master/clusters/Mode_RVCClean.xml rename to data_model/1.5.1/clusters/Mode_RVCClean.xml index 03cc03a7fd7..3a27a4f7702 100644 --- a/data_model/master/clusters/Mode_RVCClean.xml +++ b/data_model/1.5.1/clusters/Mode_RVCClean.xml @@ -57,12 +57,13 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -73,10 +74,7 @@ Davis, CA 95616, USA - - - - + @@ -96,6 +94,11 @@ Davis, CA 95616, USA + + + + + diff --git a/data_model/master/clusters/Mode_RVCRun.xml b/data_model/1.5.1/clusters/Mode_RVCRun.xml similarity index 86% rename from data_model/master/clusters/Mode_RVCRun.xml rename to data_model/1.5.1/clusters/Mode_RVCRun.xml index ce5b6a28bfb..e4c4540ba42 100644 --- a/data_model/master/clusters/Mode_RVCRun.xml +++ b/data_model/1.5.1/clusters/Mode_RVCRun.xml @@ -57,11 +57,12 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -72,10 +73,7 @@ Davis, CA 95616, USA - - - - + @@ -94,6 +92,32 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data_model/master/clusters/Mode_Refrigerator.xml b/data_model/1.5.1/clusters/Mode_Refrigerator.xml similarity index 100% rename from data_model/master/clusters/Mode_Refrigerator.xml rename to data_model/1.5.1/clusters/Mode_Refrigerator.xml diff --git a/data_model/master/clusters/Mode_WaterHeater.xml b/data_model/1.5.1/clusters/Mode_WaterHeater.xml similarity index 100% rename from data_model/master/clusters/Mode_WaterHeater.xml rename to data_model/1.5.1/clusters/Mode_WaterHeater.xml diff --git a/data_model/master/clusters/NetworkCommissioningCluster.xml b/data_model/1.5.1/clusters/NetworkCommissioningCluster.xml similarity index 83% rename from data_model/master/clusters/NetworkCommissioningCluster.xml rename to data_model/1.5.1/clusters/NetworkCommissioningCluster.xml index 71c2ef2ec94..b08f8d9fe4a 100644 --- a/data_model/master/clusters/NetworkCommissioningCluster.xml +++ b/data_model/1.5.1/clusters/NetworkCommissioningCluster.xml @@ -57,11 +57,10 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + - @@ -77,14 +76,6 @@ Davis, CA 95616, USA - - - - - - - - @@ -181,12 +172,6 @@ Davis, CA 95616, USA - - - - - - @@ -201,36 +186,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -508,36 +463,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -602,23 +527,15 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - + + + subtract + + + + + + @@ -688,50 +605,5 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/clusters/OTAProvider.xml b/data_model/1.5.1/clusters/OTAProvider.xml similarity index 96% rename from data_model/master/clusters/OTAProvider.xml rename to data_model/1.5.1/clusters/OTAProvider.xml index 8676524416f..cc1bbb2e2fb 100644 --- a/data_model/master/clusters/OTAProvider.xml +++ b/data_model/1.5.1/clusters/OTAProvider.xml @@ -150,13 +150,16 @@ Davis, CA 95616, USA - - - - - - - + + + + + + + + + + diff --git a/data_model/master/clusters/OTARequestor.xml b/data_model/1.5.1/clusters/OTARequestor.xml similarity index 100% rename from data_model/master/clusters/OTARequestor.xml rename to data_model/1.5.1/clusters/OTARequestor.xml diff --git a/data_model/master/clusters/OccupancySensing.xml b/data_model/1.5.1/clusters/OccupancySensing.xml similarity index 98% rename from data_model/master/clusters/OccupancySensing.xml rename to data_model/1.5.1/clusters/OccupancySensing.xml index 80619ad421a..09dd01fd6e9 100644 --- a/data_model/master/clusters/OccupancySensing.xml +++ b/data_model/1.5.1/clusters/OccupancySensing.xml @@ -57,13 +57,14 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -135,6 +136,14 @@ Davis, CA 95616, USA + + + + + 10 + + + @@ -154,7 +163,6 @@ Davis, CA 95616, USA - diff --git a/data_model/master/clusters/OnOff.xml b/data_model/1.5.1/clusters/OnOff.xml similarity index 97% rename from data_model/master/clusters/OnOff.xml rename to data_model/1.5.1/clusters/OnOff.xml index a58d4fcdf65..a8fc72fb245 100644 --- a/data_model/master/clusters/OnOff.xml +++ b/data_model/1.5.1/clusters/OnOff.xml @@ -139,30 +139,30 @@ Davis, CA 95616, USA - + - + - + - + - + @@ -205,7 +205,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/OperationalCredentialCluster.xml b/data_model/1.5.1/clusters/OperationalCredentialCluster.xml similarity index 96% rename from data_model/master/clusters/OperationalCredentialCluster.xml rename to data_model/1.5.1/clusters/OperationalCredentialCluster.xml index 0a1c2df3e26..e2550060f71 100644 --- a/data_model/master/clusters/OperationalCredentialCluster.xml +++ b/data_model/1.5.1/clusters/OperationalCredentialCluster.xml @@ -60,7 +60,7 @@ Davis, CA 95616, USA - + @@ -139,10 +139,7 @@ Davis, CA 95616, USA - - - - + @@ -164,10 +161,7 @@ Davis, CA 95616, USA - - - - + @@ -424,10 +418,7 @@ Davis, CA 95616, USA - - - - + @@ -446,10 +437,7 @@ Davis, CA 95616, USA - - - - + @@ -467,10 +455,7 @@ Davis, CA 95616, USA - - - - + diff --git a/data_model/master/clusters/OperationalState.xml b/data_model/1.5.1/clusters/OperationalState.xml similarity index 100% rename from data_model/master/clusters/OperationalState.xml rename to data_model/1.5.1/clusters/OperationalState.xml diff --git a/data_model/master/clusters/OperationalState_Oven.xml b/data_model/1.5.1/clusters/OperationalState_Oven.xml similarity index 100% rename from data_model/master/clusters/OperationalState_Oven.xml rename to data_model/1.5.1/clusters/OperationalState_Oven.xml diff --git a/data_model/master/clusters/OperationalState_RVC.xml b/data_model/1.5.1/clusters/OperationalState_RVC.xml similarity index 87% rename from data_model/master/clusters/OperationalState_RVC.xml rename to data_model/1.5.1/clusters/OperationalState_RVC.xml index f5bfbfac193..a4e1110d28a 100644 --- a/data_model/master/clusters/OperationalState_RVC.xml +++ b/data_model/1.5.1/clusters/OperationalState_RVC.xml @@ -106,46 +106,25 @@ Davis, CA 95616, USA - - - - + - - - - + - - - - + - - - - - + + - - - - + - - - - + - - - - + @@ -171,28 +150,16 @@ Davis, CA 95616, USA - - - - + - - - - + - - - - + - - - - + diff --git a/data_model/master/clusters/PowerSourceCluster.xml b/data_model/1.5.1/clusters/PowerSourceCluster.xml similarity index 100% rename from data_model/master/clusters/PowerSourceCluster.xml rename to data_model/1.5.1/clusters/PowerSourceCluster.xml diff --git a/data_model/master/clusters/PowerSourceConfigurationCluster.xml b/data_model/1.5.1/clusters/PowerSourceConfigurationCluster.xml similarity index 100% rename from data_model/master/clusters/PowerSourceConfigurationCluster.xml rename to data_model/1.5.1/clusters/PowerSourceConfigurationCluster.xml diff --git a/data_model/master/clusters/PowerTopology.xml b/data_model/1.5.1/clusters/PowerTopology.xml similarity index 91% rename from data_model/master/clusters/PowerTopology.xml rename to data_model/1.5.1/clusters/PowerTopology.xml index 077100432e5..09c20f78208 100644 --- a/data_model/master/clusters/PowerTopology.xml +++ b/data_model/1.5.1/clusters/PowerTopology.xml @@ -81,6 +81,23 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + diff --git a/data_model/master/clusters/PressureMeasurement.xml b/data_model/1.5.1/clusters/PressureMeasurement.xml similarity index 88% rename from data_model/master/clusters/PressureMeasurement.xml rename to data_model/1.5.1/clusters/PressureMeasurement.xml index 49d99fc6824..31296b89da1 100644 --- a/data_model/master/clusters/PressureMeasurement.xml +++ b/data_model/1.5.1/clusters/PressureMeasurement.xml @@ -57,11 +57,12 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -75,7 +76,7 @@ Davis, CA 95616, USA - + @@ -102,7 +103,15 @@ Davis, CA 95616, USA - + + + add + + + + + + @@ -114,7 +123,7 @@ Davis, CA 95616, USA - + @@ -131,7 +140,7 @@ Davis, CA 95616, USA - + @@ -141,7 +150,7 @@ Davis, CA 95616, USA - + @@ -149,7 +158,15 @@ Davis, CA 95616, USA - + + + add + + + + + + @@ -163,7 +180,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/PumpConfigurationControl.xml b/data_model/1.5.1/clusters/PumpConfigurationControl.xml similarity index 99% rename from data_model/master/clusters/PumpConfigurationControl.xml rename to data_model/1.5.1/clusters/PumpConfigurationControl.xml index b652c5286f4..ceda5550b5a 100644 --- a/data_model/master/clusters/PumpConfigurationControl.xml +++ b/data_model/1.5.1/clusters/PumpConfigurationControl.xml @@ -57,12 +57,13 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -318,7 +319,6 @@ Davis, CA 95616, USA - @@ -342,7 +342,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/PushAVStreamTransport.xml b/data_model/1.5.1/clusters/PushAVStreamTransport.xml similarity index 62% rename from data_model/master/clusters/PushAVStreamTransport.xml rename to data_model/1.5.1/clusters/PushAVStreamTransport.xml index 5fbaedc2726..87667a60da1 100644 --- a/data_model/master/clusters/PushAVStreamTransport.xml +++ b/data_model/1.5.1/clusters/PushAVStreamTransport.xml @@ -57,14 +57,13 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + - - - + @@ -80,6 +79,23 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + @@ -103,16 +119,28 @@ Davis, CA 95616, USA - + + + + + + + - + - + - + + + + + + + @@ -145,28 +173,87 @@ Davis, CA 95616, USA + + + - - + + - - - - + + + + + + + + - - + + - + - - + + + + + + + + + + + + + + + + + divide + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + @@ -180,14 +267,28 @@ Davis, CA 95616, USA - + + + + + + + + + + + + + + + @@ -198,22 +299,22 @@ Davis, CA 95616, USA - + - + - + - + @@ -223,14 +324,20 @@ Davis, CA 95616, USA - + - + - + + + + + + + @@ -247,37 +354,70 @@ Davis, CA 95616, USA - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + @@ -295,7 +435,7 @@ Davis, CA 95616, USA - + @@ -304,22 +444,22 @@ Davis, CA 95616, USA - + - + - + - + @@ -331,19 +471,32 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + - - - - - - + + + + + - + @@ -374,6 +527,12 @@ Davis, CA 95616, USA + + + + + + @@ -381,6 +540,12 @@ Davis, CA 95616, USA + + + + + + @@ -402,6 +567,12 @@ Davis, CA 95616, USA + + + + + + @@ -409,14 +580,22 @@ Davis, CA 95616, USA + + + + + + + + - + - + @@ -434,6 +613,12 @@ Davis, CA 95616, USA + + + + + + @@ -442,25 +627,53 @@ Davis, CA 95616, USA - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + diff --git a/data_model/master/clusters/RefrigeratorAlarm.xml b/data_model/1.5.1/clusters/RefrigeratorAlarm.xml similarity index 100% rename from data_model/master/clusters/RefrigeratorAlarm.xml rename to data_model/1.5.1/clusters/RefrigeratorAlarm.xml diff --git a/data_model/master/clusters/ResourceMonitoring.xml b/data_model/1.5.1/clusters/ResourceMonitoring.xml similarity index 99% rename from data_model/master/clusters/ResourceMonitoring.xml rename to data_model/1.5.1/clusters/ResourceMonitoring.xml index 9fe85266ecb..462ad35e71f 100644 --- a/data_model/master/clusters/ResourceMonitoring.xml +++ b/data_model/1.5.1/clusters/ResourceMonitoring.xml @@ -149,7 +149,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/Scenes.xml b/data_model/1.5.1/clusters/Scenes.xml similarity index 96% rename from data_model/master/clusters/Scenes.xml rename to data_model/1.5.1/clusters/Scenes.xml index ed5da7e063d..4f2303181b7 100644 --- a/data_model/master/clusters/Scenes.xml +++ b/data_model/1.5.1/clusters/Scenes.xml @@ -62,9 +62,7 @@ Davis, CA 95616, USA - - - + @@ -120,25 +118,25 @@ Davis, CA 95616, USA - + - + - + - + - + @@ -149,9 +147,10 @@ Davis, CA 95616, USA + - + diff --git a/data_model/master/clusters/ServiceArea.xml b/data_model/1.5.1/clusters/ServiceArea.xml similarity index 100% rename from data_model/master/clusters/ServiceArea.xml rename to data_model/1.5.1/clusters/ServiceArea.xml diff --git a/data_model/master/clusters/SmokeCOAlarm.xml b/data_model/1.5.1/clusters/SmokeCOAlarm.xml similarity index 100% rename from data_model/master/clusters/SmokeCOAlarm.xml rename to data_model/1.5.1/clusters/SmokeCOAlarm.xml diff --git a/data_model/master/clusters/SoilMeasurement.xml b/data_model/1.5.1/clusters/SoilMeasurement.xml similarity index 90% rename from data_model/master/clusters/SoilMeasurement.xml rename to data_model/1.5.1/clusters/SoilMeasurement.xml index 7ab20bce177..89065f9e3ba 100644 --- a/data_model/master/clusters/SoilMeasurement.xml +++ b/data_model/1.5.1/clusters/SoilMeasurement.xml @@ -62,20 +62,14 @@ Davis, CA 95616, USA - - - + - - + - - - @@ -84,10 +78,14 @@ Davis, CA 95616, USA - + + + - + + + diff --git a/data_model/master/clusters/Switch.xml b/data_model/1.5.1/clusters/Switch.xml similarity index 81% rename from data_model/master/clusters/Switch.xml rename to data_model/1.5.1/clusters/Switch.xml index 07a7e4a2bdc..5c989c7d8fa 100644 --- a/data_model/master/clusters/Switch.xml +++ b/data_model/1.5.1/clusters/Switch.xml @@ -114,7 +114,7 @@ Davis, CA 95616, USA - + @@ -122,15 +122,23 @@ Davis, CA 95616, USA - + - + + + subtract + + + + + + - + @@ -152,7 +160,15 @@ Davis, CA 95616, USA - + + + subtract + + + + + + @@ -167,7 +183,15 @@ Davis, CA 95616, USA - + + + subtract + + + + + + @@ -182,7 +206,15 @@ Davis, CA 95616, USA - + + + subtract + + + + + + @@ -197,7 +229,15 @@ Davis, CA 95616, USA - + + + subtract + + + + + + @@ -212,7 +252,15 @@ Davis, CA 95616, USA - + + + subtract + + + + + + @@ -232,7 +280,15 @@ Davis, CA 95616, USA - + + + subtract + + + + + + @@ -258,7 +314,15 @@ Davis, CA 95616, USA - + + + subtract + + + + + + diff --git a/data_model/master/clusters/TLSCertificateManagement.xml b/data_model/1.5.1/clusters/TLSCertificateManagement.xml similarity index 82% rename from data_model/master/clusters/TLSCertificateManagement.xml rename to data_model/1.5.1/clusters/TLSCertificateManagement.xml index df72e3dff57..1033bd89555 100644 --- a/data_model/master/clusters/TLSCertificateManagement.xml +++ b/data_model/1.5.1/clusters/TLSCertificateManagement.xml @@ -62,9 +62,7 @@ Davis, CA 95616, USA - - - + @@ -73,6 +71,12 @@ Davis, CA 95616, USA + + + + + + @@ -85,8 +89,15 @@ Davis, CA 95616, USA + + + + + + + @@ -107,7 +118,7 @@ Davis, CA 95616, USA - + @@ -129,13 +140,13 @@ Davis, CA 95616, USA - + - + @@ -163,7 +174,7 @@ Davis, CA 95616, USA - + @@ -173,13 +184,19 @@ Davis, CA 95616, USA + + + + + + - + @@ -216,6 +233,12 @@ Davis, CA 95616, USA + + + + + + @@ -224,24 +247,46 @@ Davis, CA 95616, USA + + + + + + - + - + + + + + + + + + + + - + + + + + + + @@ -249,7 +294,7 @@ Davis, CA 95616, USA - + @@ -262,9 +307,32 @@ Davis, CA 95616, USA + + + + + + - + + + + + + + + + + + + + + + + + + @@ -308,6 +376,12 @@ Davis, CA 95616, USA + + + + + + @@ -316,6 +390,12 @@ Davis, CA 95616, USA + + + + + + diff --git a/data_model/master/clusters/TLSClientManagement.xml b/data_model/1.5.1/clusters/TLSClientManagement.xml similarity index 75% rename from data_model/master/clusters/TLSClientManagement.xml rename to data_model/1.5.1/clusters/TLSClientManagement.xml index a3e1f9d817e..09b2435539b 100644 --- a/data_model/master/clusters/TLSClientManagement.xml +++ b/data_model/1.5.1/clusters/TLSClientManagement.xml @@ -62,24 +62,37 @@ Davis, CA 95616, USA - - - + - - + + - + + + + + + + + + + + + + + + + @@ -92,22 +105,34 @@ Davis, CA 95616, USA + + + + + + + + + + + + - + - + - + @@ -124,9 +149,7 @@ Davis, CA 95616, USA - - - + @@ -146,15 +169,27 @@ Davis, CA 95616, USA + + + + + + + + + + + + - + - + @@ -164,6 +199,12 @@ Davis, CA 95616, USA + + + + + + @@ -172,6 +213,12 @@ Davis, CA 95616, USA + + + + + + @@ -179,6 +226,12 @@ Davis, CA 95616, USA + + + + + + @@ -187,6 +240,12 @@ Davis, CA 95616, USA + + + + + + diff --git a/data_model/master/clusters/TargetNavigator.xml b/data_model/1.5.1/clusters/TargetNavigator.xml similarity index 100% rename from data_model/master/clusters/TargetNavigator.xml rename to data_model/1.5.1/clusters/TargetNavigator.xml diff --git a/data_model/master/clusters/TemperatureControl.xml b/data_model/1.5.1/clusters/TemperatureControl.xml similarity index 92% rename from data_model/master/clusters/TemperatureControl.xml rename to data_model/1.5.1/clusters/TemperatureControl.xml index e0633027869..92f8be5084c 100644 --- a/data_model/master/clusters/TemperatureControl.xml +++ b/data_model/1.5.1/clusters/TemperatureControl.xml @@ -102,7 +102,15 @@ Davis, CA 95616, USA - + + + subtract + + + + + + @@ -122,7 +130,20 @@ Davis, CA 95616, USA - + + + + + subtract + + + + + + + + + diff --git a/data_model/master/clusters/TemperatureMeasurement.xml b/data_model/1.5.1/clusters/TemperatureMeasurement.xml similarity index 93% rename from data_model/master/clusters/TemperatureMeasurement.xml rename to data_model/1.5.1/clusters/TemperatureMeasurement.xml index 7742526f923..ccf9f909c1a 100644 --- a/data_model/master/clusters/TemperatureMeasurement.xml +++ b/data_model/1.5.1/clusters/TemperatureMeasurement.xml @@ -57,12 +57,13 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -71,7 +72,7 @@ Davis, CA 95616, USA - + @@ -100,7 +101,15 @@ Davis, CA 95616, USA - + + + add + + + + + + diff --git a/data_model/master/clusters/Thermostat.xml b/data_model/1.5.1/clusters/Thermostat.xml similarity index 65% rename from data_model/master/clusters/Thermostat.xml rename to data_model/1.5.1/clusters/Thermostat.xml index 0b46bde3878..603032e4799 100644 --- a/data_model/master/clusters/Thermostat.xml +++ b/data_model/1.5.1/clusters/Thermostat.xml @@ -67,7 +67,7 @@ Davis, CA 95616, USA - + @@ -93,16 +93,8 @@ Davis, CA 95616, USA - - - - - - - - - - + + @@ -116,20 +108,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - @@ -269,10 +247,7 @@ Davis, CA 95616, USA - - - - + @@ -401,20 +376,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - @@ -527,50 +488,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -730,29 +647,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - - @@ -773,7 +667,7 @@ Davis, CA 95616, USA - + @@ -781,7 +675,7 @@ Davis, CA 95616, USA - + @@ -827,41 +721,16 @@ Davis, CA 95616, USA - - - - - - - - - - - - + + - - - - - - - - - - - - + + - - - + - - - - + @@ -968,7 +837,7 @@ Davis, CA 95616, USA - + @@ -1004,45 +873,13 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - @@ -1061,13 +898,12 @@ Davis, CA 95616, USA - - + @@ -1086,108 +922,29 @@ Davis, CA 95616, USA - + - - - - - - - - - - - - - - - - + + - - - - - - - - - - - + + - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - + + - + @@ -1246,7 +1003,7 @@ Davis, CA 95616, USA - + @@ -1254,10 +1011,13 @@ Davis, CA 95616, USA - + + + + - + @@ -1265,38 +1025,53 @@ Davis, CA 95616, USA - + + + + - + + + + - + + + + - + + + + - + + + + - + @@ -1306,7 +1081,7 @@ Davis, CA 95616, USA - + @@ -1316,7 +1091,7 @@ Davis, CA 95616, USA - + @@ -1329,7 +1104,7 @@ Davis, CA 95616, USA - + @@ -1337,7 +1112,9 @@ Davis, CA 95616, USA - + + + @@ -1345,36 +1122,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1390,85 +1137,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1494,242 +1162,5 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/clusters/ThermostatUserInterfaceConfiguration.xml b/data_model/1.5.1/clusters/ThermostatUserInterfaceConfiguration.xml similarity index 97% rename from data_model/master/clusters/ThermostatUserInterfaceConfiguration.xml rename to data_model/1.5.1/clusters/ThermostatUserInterfaceConfiguration.xml index 228218d5bc5..2f7b9f41fee 100644 --- a/data_model/master/clusters/ThermostatUserInterfaceConfiguration.xml +++ b/data_model/1.5.1/clusters/ThermostatUserInterfaceConfiguration.xml @@ -106,16 +106,10 @@ Davis, CA 95616, USA - - - - - - diff --git a/data_model/master/clusters/ThreadBorderRouterManagement.xml b/data_model/1.5.1/clusters/ThreadBorderRouterManagement.xml similarity index 97% rename from data_model/master/clusters/ThreadBorderRouterManagement.xml rename to data_model/1.5.1/clusters/ThreadBorderRouterManagement.xml index b0d2ee580f0..9cc69f53df1 100644 --- a/data_model/master/clusters/ThreadBorderRouterManagement.xml +++ b/data_model/1.5.1/clusters/ThreadBorderRouterManagement.xml @@ -88,22 +88,22 @@ Davis, CA 95616, USA - + - + - + - + diff --git a/data_model/master/clusters/ThreadNetworkDirectory.xml b/data_model/1.5.1/clusters/ThreadNetworkDirectory.xml similarity index 99% rename from data_model/master/clusters/ThreadNetworkDirectory.xml rename to data_model/1.5.1/clusters/ThreadNetworkDirectory.xml index a8011648f8f..49edc8952c0 100644 --- a/data_model/master/clusters/ThreadNetworkDirectory.xml +++ b/data_model/1.5.1/clusters/ThreadNetworkDirectory.xml @@ -91,7 +91,7 @@ Davis, CA 95616, USA - + @@ -110,7 +110,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/TimeSync.xml b/data_model/1.5.1/clusters/TimeSync.xml similarity index 98% rename from data_model/master/clusters/TimeSync.xml rename to data_model/1.5.1/clusters/TimeSync.xml index e4ed10f824b..74c130ff526 100644 --- a/data_model/master/clusters/TimeSync.xml +++ b/data_model/1.5.1/clusters/TimeSync.xml @@ -268,7 +268,7 @@ Davis, CA 95616, USA - + @@ -454,6 +454,12 @@ Davis, CA 95616, USA + + + + + + diff --git a/data_model/master/clusters/UserLabel-Cluster.xml b/data_model/1.5.1/clusters/UserLabel-Cluster.xml similarity index 98% rename from data_model/master/clusters/UserLabel-Cluster.xml rename to data_model/1.5.1/clusters/UserLabel-Cluster.xml index 449e0b38b98..3f108704ce2 100644 --- a/data_model/master/clusters/UserLabel-Cluster.xml +++ b/data_model/1.5.1/clusters/UserLabel-Cluster.xml @@ -71,6 +71,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/master/clusters/ValveConfigurationControl.xml b/data_model/1.5.1/clusters/ValveConfigurationControl.xml similarity index 96% rename from data_model/master/clusters/ValveConfigurationControl.xml rename to data_model/1.5.1/clusters/ValveConfigurationControl.xml index 84d00962f57..dcc594bf9a4 100644 --- a/data_model/master/clusters/ValveConfigurationControl.xml +++ b/data_model/1.5.1/clusters/ValveConfigurationControl.xml @@ -112,7 +112,7 @@ Davis, CA 95616, USA - + @@ -120,7 +120,7 @@ Davis, CA 95616, USA - + @@ -128,36 +128,36 @@ Davis, CA 95616, USA - + - + - + - + - + - + diff --git a/data_model/master/clusters/WakeOnLAN.xml b/data_model/1.5.1/clusters/WakeOnLAN.xml similarity index 98% rename from data_model/master/clusters/WakeOnLAN.xml rename to data_model/1.5.1/clusters/WakeOnLAN.xml index e004fd9b2be..f684f49fcec 100644 --- a/data_model/master/clusters/WakeOnLAN.xml +++ b/data_model/1.5.1/clusters/WakeOnLAN.xml @@ -81,6 +81,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/master/clusters/WaterContentMeasurement.xml b/data_model/1.5.1/clusters/WaterContentMeasurement.xml similarity index 92% rename from data_model/master/clusters/WaterContentMeasurement.xml rename to data_model/1.5.1/clusters/WaterContentMeasurement.xml index b8abeaa984b..a1a1f07ca7e 100644 --- a/data_model/master/clusters/WaterContentMeasurement.xml +++ b/data_model/1.5.1/clusters/WaterContentMeasurement.xml @@ -57,11 +57,12 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -70,7 +71,7 @@ Davis, CA 95616, USA - + @@ -97,7 +98,15 @@ Davis, CA 95616, USA - + + + add + + + + + + diff --git a/data_model/master/clusters/WaterHeaterManagement.xml b/data_model/1.5.1/clusters/WaterHeaterManagement.xml similarity index 96% rename from data_model/master/clusters/WaterHeaterManagement.xml rename to data_model/1.5.1/clusters/WaterHeaterManagement.xml index 52f87ab2b54..1c1ca48ebfe 100644 --- a/data_model/master/clusters/WaterHeaterManagement.xml +++ b/data_model/1.5.1/clusters/WaterHeaterManagement.xml @@ -151,22 +151,22 @@ Davis, CA 95616, USA - + - + - + - + @@ -175,16 +175,13 @@ Davis, CA 95616, USA - + - - - diff --git a/data_model/master/clusters/WebRTC_Provider.xml b/data_model/1.5.1/clusters/WebRTC_Provider.xml similarity index 71% rename from data_model/master/clusters/WebRTC_Provider.xml rename to data_model/1.5.1/clusters/WebRTC_Provider.xml index 8c37e4d8ae4..7c21530e2d5 100644 --- a/data_model/master/clusters/WebRTC_Provider.xml +++ b/data_model/1.5.1/clusters/WebRTC_Provider.xml @@ -57,14 +57,13 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + - - - + @@ -76,116 +75,28 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - - - - - - - - - + - - - - - - - + - - + + - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -208,11 +119,11 @@ Davis, CA 95616, USA - + - + @@ -232,6 +143,48 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -263,7 +216,7 @@ Davis, CA 95616, USA - + @@ -278,11 +231,11 @@ Davis, CA 95616, USA - + - + @@ -302,6 +255,60 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -360,9 +367,6 @@ Davis, CA 95616, USA - - - diff --git a/data_model/master/clusters/WebRTC_Requestor.xml b/data_model/1.5.1/clusters/WebRTC_Requestor.xml similarity index 94% rename from data_model/master/clusters/WebRTC_Requestor.xml rename to data_model/1.5.1/clusters/WebRTC_Requestor.xml index fecac1776d3..bf1783b952a 100644 --- a/data_model/master/clusters/WebRTC_Requestor.xml +++ b/data_model/1.5.1/clusters/WebRTC_Requestor.xml @@ -57,18 +57,17 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + - - - + - + @@ -133,9 +132,6 @@ Davis, CA 95616, USA - - - diff --git a/data_model/master/clusters/WiFiNetworkManagement.xml b/data_model/1.5.1/clusters/WiFiNetworkManagement.xml similarity index 98% rename from data_model/master/clusters/WiFiNetworkManagement.xml rename to data_model/1.5.1/clusters/WiFiNetworkManagement.xml index 115978a5f38..10fb5f9a89f 100644 --- a/data_model/master/clusters/WiFiNetworkManagement.xml +++ b/data_model/1.5.1/clusters/WiFiNetworkManagement.xml @@ -66,7 +66,7 @@ Davis, CA 95616, USA - + @@ -77,7 +77,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/clusters/WindowCovering.xml b/data_model/1.5.1/clusters/WindowCovering.xml similarity index 77% rename from data_model/master/clusters/WindowCovering.xml rename to data_model/1.5.1/clusters/WindowCovering.xml index a6df50eea61..c946cfad46e 100644 --- a/data_model/master/clusters/WindowCovering.xml +++ b/data_model/1.5.1/clusters/WindowCovering.xml @@ -57,13 +57,16 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + + + @@ -81,9 +84,6 @@ Davis, CA 95616, USA - - - @@ -313,70 +313,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -401,7 +337,7 @@ Davis, CA 95616, USA - + @@ -411,7 +347,7 @@ Davis, CA 95616, USA - + @@ -421,12 +357,14 @@ Davis, CA 95616, USA - + + + - + @@ -436,7 +374,7 @@ Davis, CA 95616, USA - + @@ -454,7 +392,7 @@ Davis, CA 95616, USA - + @@ -467,7 +405,7 @@ Davis, CA 95616, USA - + @@ -478,85 +416,16 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - @@ -576,21 +445,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - @@ -611,21 +465,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - diff --git a/data_model/master/clusters/ZoneManagement.xml b/data_model/1.5.1/clusters/ZoneManagement.xml similarity index 87% rename from data_model/master/clusters/ZoneManagement.xml rename to data_model/1.5.1/clusters/ZoneManagement.xml index cd9fa055b15..47386ef9d69 100644 --- a/data_model/master/clusters/ZoneManagement.xml +++ b/data_model/1.5.1/clusters/ZoneManagement.xml @@ -62,14 +62,12 @@ Davis, CA 95616, USA - - - + - + @@ -81,6 +79,11 @@ Davis, CA 95616, USA + + + + + @@ -118,14 +121,16 @@ Davis, CA 95616, USA - + + + - + - + @@ -169,12 +174,23 @@ Davis, CA 95616, USA + + + + + + + + + + + - + @@ -183,7 +199,7 @@ Davis, CA 95616, USA - + @@ -191,7 +207,7 @@ Davis, CA 95616, USA - + @@ -199,10 +215,10 @@ Davis, CA 95616, USA - + - + @@ -236,9 +252,10 @@ Davis, CA 95616, USA - + + @@ -249,9 +266,10 @@ Davis, CA 95616, USA - + + @@ -262,7 +280,7 @@ Davis, CA 95616, USA - + @@ -273,8 +291,9 @@ Davis, CA 95616, USA - + + @@ -289,6 +308,13 @@ Davis, CA 95616, USA + + + + + + + @@ -329,26 +355,7 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - + @@ -357,14 +364,14 @@ Davis, CA 95616, USA - + - + diff --git a/data_model/master/clusters/cluster_ids.json b/data_model/1.5.1/clusters/cluster_ids.json similarity index 96% rename from data_model/master/clusters/cluster_ids.json rename to data_model/1.5.1/clusters/cluster_ids.json index ee875e32c1c..82e63b90bd7 100644 --- a/data_model/master/clusters/cluster_ids.json +++ b/data_model/1.5.1/clusters/cluster_ids.json @@ -62,7 +62,6 @@ "145": "Electrical Energy Measurement", "148": "Water Heater Management", "149": "Commodity Price", - "150": "Demand Response Load Control", "151": "Messages", "152": "Device Energy Management", "153": "Energy EVSE", @@ -71,6 +70,7 @@ "157": "Energy EVSE Mode", "158": "Water Heater Mode", "159": "Device Energy Management Mode", + "160": "Electrical Grid Conditions", "257": "Door Lock", "258": "Window Covering", "260": "Closure Control", @@ -80,7 +80,6 @@ "513": "Thermostat", "514": "Fan Control", "516": "Thermostat User Interface Configuration", - "517": "Humidistat", "768": "Color Control", "1024": "Illuminance Measurement", "1026": "Temperature Measurement", @@ -99,7 +98,6 @@ "1070": "Total Volatile Organic Compounds Concentration Measurement", "1071": "Radon Concentration Measurement", "1072": "Soil Measurement", - "1104": "Network Identity Management", "1105": "Wi-Fi Network Management", "1106": "Thread Border Router Management", "1107": "Thread Network Directory", @@ -128,7 +126,7 @@ "1872": "Ecosystem Information", "1873": "Commissioner Control", "1874": "Joint Fabric Datastore", - "1875": "Joint Fabric PKI", + "1875": "Joint Fabric Administrator", "2049": "TLS Certificate Management", "2050": "TLS Client Management", "2822": "Meter Identification", diff --git a/data_model/master/device_types/Aggregator.xml b/data_model/1.5.1/device_types/Aggregator.xml similarity index 100% rename from data_model/master/device_types/Aggregator.xml rename to data_model/1.5.1/device_types/Aggregator.xml diff --git a/data_model/master/device_types/AirPurifier.xml b/data_model/1.5.1/device_types/AirPurifier.xml similarity index 100% rename from data_model/master/device_types/AirPurifier.xml rename to data_model/1.5.1/device_types/AirPurifier.xml diff --git a/data_model/master/device_types/AirQualitySensor.xml b/data_model/1.5.1/device_types/AirQualitySensor.xml similarity index 100% rename from data_model/master/device_types/AirQualitySensor.xml rename to data_model/1.5.1/device_types/AirQualitySensor.xml diff --git a/data_model/1.5.1/device_types/AudioDoorbell.xml b/data_model/1.5.1/device_types/AudioDoorbell.xml new file mode 100644 index 00000000000..4a34dabbea9 --- /dev/null +++ b/data_model/1.5.1/device_types/AudioDoorbell.xml @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data_model/master/device_types/BaseDeviceType.xml b/data_model/1.5.1/device_types/BaseDeviceType.xml similarity index 93% rename from data_model/master/device_types/BaseDeviceType.xml rename to data_model/1.5.1/device_types/BaseDeviceType.xml index 292faf5db70..426ea6e1b46 100644 --- a/data_model/master/device_types/BaseDeviceType.xml +++ b/data_model/1.5.1/device_types/BaseDeviceType.xml @@ -57,18 +57,13 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + - - - - - - @@ -97,7 +92,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/device_types/BasicVideoPlayer.xml b/data_model/1.5.1/device_types/BasicVideoPlayer.xml similarity index 97% rename from data_model/master/device_types/BasicVideoPlayer.xml rename to data_model/1.5.1/device_types/BasicVideoPlayer.xml index acf88741ac0..5f2872c2bb7 100644 --- a/data_model/master/device_types/BasicVideoPlayer.xml +++ b/data_model/1.5.1/device_types/BasicVideoPlayer.xml @@ -67,13 +67,13 @@ Davis, CA 95616, USA - + - + diff --git a/data_model/master/device_types/BatteryStorage.xml b/data_model/1.5.1/device_types/BatteryStorage.xml similarity index 79% rename from data_model/master/device_types/BatteryStorage.xml rename to data_model/1.5.1/device_types/BatteryStorage.xml index 5c538446ba2..0bcb110f5f8 100644 --- a/data_model/master/device_types/BatteryStorage.xml +++ b/data_model/1.5.1/device_types/BatteryStorage.xml @@ -57,9 +57,10 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -67,4 +68,27 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data_model/master/device_types/BridgedNode.xml b/data_model/1.5.1/device_types/BridgedNode.xml similarity index 100% rename from data_model/master/device_types/BridgedNode.xml rename to data_model/1.5.1/device_types/BridgedNode.xml diff --git a/data_model/master/device_types/Camera.xml b/data_model/1.5.1/device_types/Camera.xml similarity index 82% rename from data_model/master/device_types/Camera.xml rename to data_model/1.5.1/device_types/Camera.xml index 365d1454226..efed03dc6bf 100644 --- a/data_model/master/device_types/Camera.xml +++ b/data_model/1.5.1/device_types/Camera.xml @@ -62,32 +62,53 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + - + - + - + @@ -98,6 +119,9 @@ Davis, CA 95616, USA + + + @@ -107,11 +131,5 @@ Davis, CA 95616, USA - - - - - - diff --git a/data_model/master/device_types/CameraController.xml b/data_model/1.5.1/device_types/CameraController.xml similarity index 94% rename from data_model/master/device_types/CameraController.xml rename to data_model/1.5.1/device_types/CameraController.xml index 399e6331dfb..85529ff5609 100644 --- a/data_model/master/device_types/CameraController.xml +++ b/data_model/1.5.1/device_types/CameraController.xml @@ -66,10 +66,7 @@ Davis, CA 95616, USA - - - - + @@ -84,10 +81,10 @@ Davis, CA 95616, USA - + - + diff --git a/data_model/master/device_types/CastingVideoClient.xml b/data_model/1.5.1/device_types/CastingVideoClient.xml similarity index 97% rename from data_model/master/device_types/CastingVideoClient.xml rename to data_model/1.5.1/device_types/CastingVideoClient.xml index 5ff5a3e1d23..e166b1df0e9 100644 --- a/data_model/master/device_types/CastingVideoClient.xml +++ b/data_model/1.5.1/device_types/CastingVideoClient.xml @@ -64,7 +64,7 @@ Davis, CA 95616, USA - + @@ -73,7 +73,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/device_types/CastingVideoPlayer.xml b/data_model/1.5.1/device_types/CastingVideoPlayer.xml similarity index 97% rename from data_model/master/device_types/CastingVideoPlayer.xml rename to data_model/1.5.1/device_types/CastingVideoPlayer.xml index db440168344..9b498538b91 100644 --- a/data_model/master/device_types/CastingVideoPlayer.xml +++ b/data_model/1.5.1/device_types/CastingVideoPlayer.xml @@ -68,13 +68,13 @@ Davis, CA 95616, USA - + - + @@ -108,7 +108,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/device_types/Chime.xml b/data_model/1.5.1/device_types/Chime.xml similarity index 100% rename from data_model/master/device_types/Chime.xml rename to data_model/1.5.1/device_types/Chime.xml diff --git a/data_model/master/device_types/Closure.xml b/data_model/1.5.1/device_types/Closure.xml similarity index 94% rename from data_model/master/device_types/Closure.xml rename to data_model/1.5.1/device_types/Closure.xml index 728e71046ff..89b88a69295 100644 --- a/data_model/master/device_types/Closure.xml +++ b/data_model/1.5.1/device_types/Closure.xml @@ -61,16 +61,19 @@ Davis, CA 95616, USA - + - - + + + + + diff --git a/data_model/master/device_types/ClosureController.xml b/data_model/1.5.1/device_types/ClosureController.xml similarity index 100% rename from data_model/master/device_types/ClosureController.xml rename to data_model/1.5.1/device_types/ClosureController.xml diff --git a/data_model/master/device_types/ClosurePanel.xml b/data_model/1.5.1/device_types/ClosurePanel.xml similarity index 94% rename from data_model/master/device_types/ClosurePanel.xml rename to data_model/1.5.1/device_types/ClosurePanel.xml index c744baea4df..5d621ba877e 100644 --- a/data_model/master/device_types/ClosurePanel.xml +++ b/data_model/1.5.1/device_types/ClosurePanel.xml @@ -63,6 +63,12 @@ Davis, CA 95616, USA + + + + + + diff --git a/data_model/master/device_types/ColorDimmerSwitch.xml b/data_model/1.5.1/device_types/ColorDimmerSwitch.xml similarity index 97% rename from data_model/master/device_types/ColorDimmerSwitch.xml rename to data_model/1.5.1/device_types/ColorDimmerSwitch.xml index bc80755034f..5d7b72f0671 100644 --- a/data_model/master/device_types/ColorDimmerSwitch.xml +++ b/data_model/1.5.1/device_types/ColorDimmerSwitch.xml @@ -81,10 +81,7 @@ Davis, CA 95616, USA - - - - + diff --git a/data_model/master/device_types/ColorTemperatureLight.xml b/data_model/1.5.1/device_types/ColorTemperatureLight.xml similarity index 93% rename from data_model/master/device_types/ColorTemperatureLight.xml rename to data_model/1.5.1/device_types/ColorTemperatureLight.xml index 003a2a1b4a7..7397396df48 100644 --- a/data_model/master/device_types/ColorTemperatureLight.xml +++ b/data_model/1.5.1/device_types/ColorTemperatureLight.xml @@ -80,7 +80,7 @@ Davis, CA 95616, USA - + @@ -88,10 +88,10 @@ Davis, CA 95616, USA - + - + @@ -117,23 +117,17 @@ Davis, CA 95616, USA - - - - + - - - - + - + diff --git a/data_model/master/device_types/ContactSensor.xml b/data_model/1.5.1/device_types/ContactSensor.xml similarity index 100% rename from data_model/master/device_types/ContactSensor.xml rename to data_model/1.5.1/device_types/ContactSensor.xml diff --git a/data_model/master/device_types/ContentApp.xml b/data_model/1.5.1/device_types/ContentApp.xml similarity index 95% rename from data_model/master/device_types/ContentApp.xml rename to data_model/1.5.1/device_types/ContentApp.xml index 0fe38d96e43..e43081d9a85 100644 --- a/data_model/master/device_types/ContentApp.xml +++ b/data_model/1.5.1/device_types/ContentApp.xml @@ -67,11 +67,6 @@ Davis, CA 95616, USA - - - - - @@ -90,7 +85,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/device_types/ControlBridge.xml b/data_model/1.5.1/device_types/ControlBridge.xml similarity index 97% rename from data_model/master/device_types/ControlBridge.xml rename to data_model/1.5.1/device_types/ControlBridge.xml index 2c0d694f7e2..17642c0c930 100644 --- a/data_model/master/device_types/ControlBridge.xml +++ b/data_model/1.5.1/device_types/ControlBridge.xml @@ -81,10 +81,7 @@ Davis, CA 95616, USA - - - - + diff --git a/data_model/master/device_types/CookSurface.xml b/data_model/1.5.1/device_types/CookSurface.xml similarity index 96% rename from data_model/master/device_types/CookSurface.xml rename to data_model/1.5.1/device_types/CookSurface.xml index b5fe7efe0a8..1027efbb9ec 100644 --- a/data_model/master/device_types/CookSurface.xml +++ b/data_model/1.5.1/device_types/CookSurface.xml @@ -67,7 +67,7 @@ Davis, CA 95616, USA - + @@ -75,10 +75,10 @@ Davis, CA 95616, USA - + - + diff --git a/data_model/master/device_types/Cooktop.xml b/data_model/1.5.1/device_types/Cooktop.xml similarity index 98% rename from data_model/master/device_types/Cooktop.xml rename to data_model/1.5.1/device_types/Cooktop.xml index 744e7af1d5a..09f014328d6 100644 --- a/data_model/master/device_types/Cooktop.xml +++ b/data_model/1.5.1/device_types/Cooktop.xml @@ -69,7 +69,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/device_types/DeviceEnergyManagement.xml b/data_model/1.5.1/device_types/DeviceEnergyManagement.xml similarity index 92% rename from data_model/master/device_types/DeviceEnergyManagement.xml rename to data_model/1.5.1/device_types/DeviceEnergyManagement.xml index 529c19f1de8..e4a3ee475cc 100644 --- a/data_model/master/device_types/DeviceEnergyManagement.xml +++ b/data_model/1.5.1/device_types/DeviceEnergyManagement.xml @@ -57,10 +57,11 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -70,27 +71,27 @@ Davis, CA 95616, USA - + - + - + - + - + @@ -105,5 +106,8 @@ Davis, CA 95616, USA + + + diff --git a/data_model/master/device_types/DimmableLight.xml b/data_model/1.5.1/device_types/DimmableLight.xml similarity index 93% rename from data_model/master/device_types/DimmableLight.xml rename to data_model/1.5.1/device_types/DimmableLight.xml index a59c966a9ec..0b7552c70f2 100644 --- a/data_model/master/device_types/DimmableLight.xml +++ b/data_model/1.5.1/device_types/DimmableLight.xml @@ -79,7 +79,7 @@ Davis, CA 95616, USA - + @@ -87,10 +87,10 @@ Davis, CA 95616, USA - + - + @@ -116,16 +116,10 @@ Davis, CA 95616, USA - - - - + - - - - + diff --git a/data_model/master/device_types/DimmablePlug-InUnit.xml b/data_model/1.5.1/device_types/DimmablePlug-InUnit.xml similarity index 93% rename from data_model/master/device_types/DimmablePlug-InUnit.xml rename to data_model/1.5.1/device_types/DimmablePlug-InUnit.xml index 3eb4d93dc5f..80b664a75cf 100644 --- a/data_model/master/device_types/DimmablePlug-InUnit.xml +++ b/data_model/1.5.1/device_types/DimmablePlug-InUnit.xml @@ -57,12 +57,13 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -80,7 +81,7 @@ Davis, CA 95616, USA - + @@ -88,10 +89,10 @@ Davis, CA 95616, USA - + - + @@ -117,16 +118,10 @@ Davis, CA 95616, USA - - - - + - - - - + diff --git a/data_model/master/device_types/DimmerSwitch.xml b/data_model/1.5.1/device_types/DimmerSwitch.xml similarity index 97% rename from data_model/master/device_types/DimmerSwitch.xml rename to data_model/1.5.1/device_types/DimmerSwitch.xml index 64e82939a44..8f08475e1f0 100644 --- a/data_model/master/device_types/DimmerSwitch.xml +++ b/data_model/1.5.1/device_types/DimmerSwitch.xml @@ -81,10 +81,7 @@ Davis, CA 95616, USA - - - - + diff --git a/data_model/master/device_types/Dishwasher.xml b/data_model/1.5.1/device_types/Dishwasher.xml similarity index 98% rename from data_model/master/device_types/Dishwasher.xml rename to data_model/1.5.1/device_types/Dishwasher.xml index 49dfb7be223..d45194910ba 100644 --- a/data_model/master/device_types/Dishwasher.xml +++ b/data_model/1.5.1/device_types/Dishwasher.xml @@ -70,7 +70,7 @@ Davis, CA 95616, USA - + @@ -81,7 +81,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/device_types/DoorLock.xml b/data_model/1.5.1/device_types/DoorLock.xml similarity index 86% rename from data_model/master/device_types/DoorLock.xml rename to data_model/1.5.1/device_types/DoorLock.xml index 5279cd6b7c6..de978b4c0c6 100644 --- a/data_model/master/device_types/DoorLock.xml +++ b/data_model/1.5.1/device_types/DoorLock.xml @@ -1,4 +1,4 @@ - + - + + + + + + + + + + + + + + + @@ -76,25 +90,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/device_types/DoorLockController.xml b/data_model/1.5.1/device_types/DoorLockController.xml similarity index 93% rename from data_model/master/device_types/DoorLockController.xml rename to data_model/1.5.1/device_types/DoorLockController.xml index 4b54fcdc00c..f838b55a93b 100644 --- a/data_model/master/device_types/DoorLockController.xml +++ b/data_model/1.5.1/device_types/DoorLockController.xml @@ -61,21 +61,22 @@ Davis, CA 95616, USA - + + + + + + + + - - - - - - - + diff --git a/data_model/master/device_types/HumidifierDehumidifier.xml b/data_model/1.5.1/device_types/Doorbell.xml similarity index 87% rename from data_model/master/device_types/HumidifierDehumidifier.xml rename to data_model/1.5.1/device_types/Doorbell.xml index e882e809653..1ea37e128a7 100644 --- a/data_model/master/device_types/HumidifierDehumidifier.xml +++ b/data_model/1.5.1/device_types/Doorbell.xml @@ -57,26 +57,25 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + - + - - - - - - - + - + + + + + + - - + + diff --git a/data_model/master/device_types/EVSE.xml b/data_model/1.5.1/device_types/EVSE.xml similarity index 82% rename from data_model/master/device_types/EVSE.xml rename to data_model/1.5.1/device_types/EVSE.xml index da8e26b374f..4d440608f76 100644 --- a/data_model/master/device_types/EVSE.xml +++ b/data_model/1.5.1/device_types/EVSE.xml @@ -77,4 +77,30 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data_model/master/device_types/ElectricalEnergyTariff.xml b/data_model/1.5.1/device_types/ElectricalEnergyTariff.xml similarity index 84% rename from data_model/master/device_types/ElectricalEnergyTariff.xml rename to data_model/1.5.1/device_types/ElectricalEnergyTariff.xml index eb48b66af95..6ec2a784c36 100644 --- a/data_model/master/device_types/ElectricalEnergyTariff.xml +++ b/data_model/1.5.1/device_types/ElectricalEnergyTariff.xml @@ -66,39 +66,14 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + diff --git a/data_model/master/device_types/ElectricalMeter.xml b/data_model/1.5.1/device_types/ElectricalMeter.xml similarity index 93% rename from data_model/master/device_types/ElectricalMeter.xml rename to data_model/1.5.1/device_types/ElectricalMeter.xml index eff7f873659..ee31dc4c9f8 100644 --- a/data_model/master/device_types/ElectricalMeter.xml +++ b/data_model/1.5.1/device_types/ElectricalMeter.xml @@ -63,11 +63,17 @@ Davis, CA 95616, USA - + - + + + + + + + diff --git a/data_model/master/device_types/ElectricalSensor.xml b/data_model/1.5.1/device_types/ElectricalSensor.xml similarity index 100% rename from data_model/master/device_types/ElectricalSensor.xml rename to data_model/1.5.1/device_types/ElectricalSensor.xml diff --git a/data_model/master/device_types/ElectricalUtilityMeter.xml b/data_model/1.5.1/device_types/ElectricalUtilityMeter.xml similarity index 94% rename from data_model/master/device_types/ElectricalUtilityMeter.xml rename to data_model/1.5.1/device_types/ElectricalUtilityMeter.xml index 19467c033a0..5693b741880 100644 --- a/data_model/master/device_types/ElectricalUtilityMeter.xml +++ b/data_model/1.5.1/device_types/ElectricalUtilityMeter.xml @@ -62,10 +62,14 @@ Davis, CA 95616, USA + + + + + + + - - - diff --git a/data_model/master/device_types/ExtendedColorLight.xml b/data_model/1.5.1/device_types/ExtendedColorLight.xml similarity index 91% rename from data_model/master/device_types/ExtendedColorLight.xml rename to data_model/1.5.1/device_types/ExtendedColorLight.xml index 1a37ac7a6fb..f3de5ede46f 100644 --- a/data_model/master/device_types/ExtendedColorLight.xml +++ b/data_model/1.5.1/device_types/ExtendedColorLight.xml @@ -80,7 +80,7 @@ Davis, CA 95616, USA - + @@ -88,10 +88,10 @@ Davis, CA 95616, USA - + - + @@ -117,35 +117,29 @@ Davis, CA 95616, USA - - - - + - - - - + - + - + - + - + - + diff --git a/data_model/master/device_types/ExtractorHood.xml b/data_model/1.5.1/device_types/ExtractorHood.xml similarity index 97% rename from data_model/master/device_types/ExtractorHood.xml rename to data_model/1.5.1/device_types/ExtractorHood.xml index ff3b4819c7c..c55bc9abd16 100644 --- a/data_model/master/device_types/ExtractorHood.xml +++ b/data_model/1.5.1/device_types/ExtractorHood.xml @@ -75,13 +75,13 @@ Davis, CA 95616, USA - + - + - + diff --git a/data_model/master/device_types/Fan.xml b/data_model/1.5.1/device_types/Fan.xml similarity index 92% rename from data_model/master/device_types/Fan.xml rename to data_model/1.5.1/device_types/Fan.xml index eae97cb4119..4e9ee06dc4f 100644 --- a/data_model/master/device_types/Fan.xml +++ b/data_model/1.5.1/device_types/Fan.xml @@ -57,11 +57,12 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -76,15 +77,6 @@ Davis, CA 95616, USA - - - - - - - - - diff --git a/data_model/master/device_types/FloodlightCamera.xml b/data_model/1.5.1/device_types/FloodlightCamera.xml similarity index 100% rename from data_model/master/device_types/FloodlightCamera.xml rename to data_model/1.5.1/device_types/FloodlightCamera.xml diff --git a/data_model/master/device_types/FlowSensor.xml b/data_model/1.5.1/device_types/FlowSensor.xml similarity index 95% rename from data_model/master/device_types/FlowSensor.xml rename to data_model/1.5.1/device_types/FlowSensor.xml index 36c3d919ae1..e27c8ab5830 100644 --- a/data_model/master/device_types/FlowSensor.xml +++ b/data_model/1.5.1/device_types/FlowSensor.xml @@ -57,21 +57,17 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + - - - - - diff --git a/data_model/master/device_types/GenericSwitch.xml b/data_model/1.5.1/device_types/GenericSwitch.xml similarity index 100% rename from data_model/master/device_types/GenericSwitch.xml rename to data_model/1.5.1/device_types/GenericSwitch.xml diff --git a/data_model/master/device_types/HeatPump.xml b/data_model/1.5.1/device_types/HeatPump.xml similarity index 81% rename from data_model/master/device_types/HeatPump.xml rename to data_model/1.5.1/device_types/HeatPump.xml index 5d8666d0903..778d66f2e4a 100644 --- a/data_model/master/device_types/HeatPump.xml +++ b/data_model/1.5.1/device_types/HeatPump.xml @@ -70,4 +70,31 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data_model/master/device_types/HumiditySensor.xml b/data_model/1.5.1/device_types/HumiditySensor.xml similarity index 95% rename from data_model/master/device_types/HumiditySensor.xml rename to data_model/1.5.1/device_types/HumiditySensor.xml index 685bcb45bbc..f05948b9e55 100644 --- a/data_model/master/device_types/HumiditySensor.xml +++ b/data_model/1.5.1/device_types/HumiditySensor.xml @@ -57,21 +57,17 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + - - - - - diff --git a/data_model/master/device_types/Intercom.xml b/data_model/1.5.1/device_types/Intercom.xml similarity index 81% rename from data_model/master/device_types/Intercom.xml rename to data_model/1.5.1/device_types/Intercom.xml index c2857525bdd..85411d329d8 100644 --- a/data_model/master/device_types/Intercom.xml +++ b/data_model/1.5.1/device_types/Intercom.xml @@ -57,31 +57,45 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + + + + + + + + + + + + + + + + + + + + - - - - - - - + - + - + @@ -92,14 +106,17 @@ Davis, CA 95616, USA + + + - - + + diff --git a/data_model/master/device_types/IrrigationSystem.xml b/data_model/1.5.1/device_types/IrrigationSystem.xml similarity index 100% rename from data_model/master/device_types/IrrigationSystem.xml rename to data_model/1.5.1/device_types/IrrigationSystem.xml diff --git a/data_model/master/device_types/JointFabricAdmin.xml b/data_model/1.5.1/device_types/JointFabricAdmin.xml similarity index 98% rename from data_model/master/device_types/JointFabricAdmin.xml rename to data_model/1.5.1/device_types/JointFabricAdmin.xml index 81d372a77c9..a6aa0a5f7c9 100644 --- a/data_model/master/device_types/JointFabricAdmin.xml +++ b/data_model/1.5.1/device_types/JointFabricAdmin.xml @@ -66,7 +66,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/device_types/LaundryDryer.xml b/data_model/1.5.1/device_types/LaundryDryer.xml similarity index 98% rename from data_model/master/device_types/LaundryDryer.xml rename to data_model/1.5.1/device_types/LaundryDryer.xml index 2354c5e154c..74cce08a250 100644 --- a/data_model/master/device_types/LaundryDryer.xml +++ b/data_model/1.5.1/device_types/LaundryDryer.xml @@ -70,7 +70,7 @@ Davis, CA 95616, USA - + @@ -81,7 +81,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/device_types/LaundryWasher.xml b/data_model/1.5.1/device_types/LaundryWasher.xml similarity index 98% rename from data_model/master/device_types/LaundryWasher.xml rename to data_model/1.5.1/device_types/LaundryWasher.xml index 68b3909adc7..1aaff12b044 100644 --- a/data_model/master/device_types/LaundryWasher.xml +++ b/data_model/1.5.1/device_types/LaundryWasher.xml @@ -70,7 +70,7 @@ Davis, CA 95616, USA - + @@ -78,7 +78,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/device_types/LightSensor.xml b/data_model/1.5.1/device_types/LightSensor.xml similarity index 95% rename from data_model/master/device_types/LightSensor.xml rename to data_model/1.5.1/device_types/LightSensor.xml index 7fcfb1257e9..41580de4400 100644 --- a/data_model/master/device_types/LightSensor.xml +++ b/data_model/1.5.1/device_types/LightSensor.xml @@ -57,22 +57,18 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + - - - - - diff --git a/data_model/master/device_types/MeterReferencePoint.xml b/data_model/1.5.1/device_types/MeterReferencePoint.xml similarity index 94% rename from data_model/master/device_types/MeterReferencePoint.xml rename to data_model/1.5.1/device_types/MeterReferencePoint.xml index 3d8f2305f8a..6cce132b79f 100644 --- a/data_model/master/device_types/MeterReferencePoint.xml +++ b/data_model/1.5.1/device_types/MeterReferencePoint.xml @@ -65,15 +65,16 @@ Davis, CA 95616, USA + + + + + + + - - - - - - diff --git a/data_model/master/device_types/MicrowaveOven.xml b/data_model/1.5.1/device_types/MicrowaveOven.xml similarity index 98% rename from data_model/master/device_types/MicrowaveOven.xml rename to data_model/1.5.1/device_types/MicrowaveOven.xml index 53092902c2f..1ce8b1e0ac9 100644 --- a/data_model/master/device_types/MicrowaveOven.xml +++ b/data_model/1.5.1/device_types/MicrowaveOven.xml @@ -89,10 +89,10 @@ Davis, CA 95616, USA - + - + diff --git a/data_model/master/device_types/ModeSelectDeviceType.xml b/data_model/1.5.1/device_types/ModeSelectDeviceType.xml similarity index 100% rename from data_model/master/device_types/ModeSelectDeviceType.xml rename to data_model/1.5.1/device_types/ModeSelectDeviceType.xml diff --git a/data_model/master/device_types/MountedDimmableLoadControl.xml b/data_model/1.5.1/device_types/MountedDimmableLoadControl.xml similarity index 92% rename from data_model/master/device_types/MountedDimmableLoadControl.xml rename to data_model/1.5.1/device_types/MountedDimmableLoadControl.xml index 6a4b2a81048..7a76a23c6ac 100644 --- a/data_model/master/device_types/MountedDimmableLoadControl.xml +++ b/data_model/1.5.1/device_types/MountedDimmableLoadControl.xml @@ -57,9 +57,10 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -77,7 +78,7 @@ Davis, CA 95616, USA - + @@ -85,10 +86,10 @@ Davis, CA 95616, USA - + - + @@ -114,16 +115,10 @@ Davis, CA 95616, USA - - - - + - - - - + diff --git a/data_model/master/device_types/MountedOnOffControl.xml b/data_model/1.5.1/device_types/MountedOnOffControl.xml similarity index 92% rename from data_model/master/device_types/MountedOnOffControl.xml rename to data_model/1.5.1/device_types/MountedOnOffControl.xml index ae0900168e8..7d5834fcf5d 100644 --- a/data_model/master/device_types/MountedOnOffControl.xml +++ b/data_model/1.5.1/device_types/MountedOnOffControl.xml @@ -57,9 +57,10 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -77,7 +78,7 @@ Davis, CA 95616, USA - + @@ -85,10 +86,10 @@ Davis, CA 95616, USA - + - + @@ -114,16 +115,10 @@ Davis, CA 95616, USA - - - - + - - - - + diff --git a/data_model/master/device_types/NetworkInfraManager.xml b/data_model/1.5.1/device_types/NetworkInfraManager.xml similarity index 93% rename from data_model/master/device_types/NetworkInfraManager.xml rename to data_model/1.5.1/device_types/NetworkInfraManager.xml index ab96a0e9794..477e7797004 100644 --- a/data_model/master/device_types/NetworkInfraManager.xml +++ b/data_model/1.5.1/device_types/NetworkInfraManager.xml @@ -60,19 +60,20 @@ Davis, CA 95616, USA - + + + + + + + + - - - - - - diff --git a/data_model/master/device_types/OccupancySensor.xml b/data_model/1.5.1/device_types/OccupancySensor.xml similarity index 98% rename from data_model/master/device_types/OccupancySensor.xml rename to data_model/1.5.1/device_types/OccupancySensor.xml index 47d35935c55..8a7286963c9 100644 --- a/data_model/master/device_types/OccupancySensor.xml +++ b/data_model/1.5.1/device_types/OccupancySensor.xml @@ -62,7 +62,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/device_types/OnOffLight.xml b/data_model/1.5.1/device_types/OnOffLight.xml similarity index 93% rename from data_model/master/device_types/OnOffLight.xml rename to data_model/1.5.1/device_types/OnOffLight.xml index 6d463ffbd16..5bbd1b28478 100644 --- a/data_model/master/device_types/OnOffLight.xml +++ b/data_model/1.5.1/device_types/OnOffLight.xml @@ -79,7 +79,7 @@ Davis, CA 95616, USA - + @@ -87,10 +87,10 @@ Davis, CA 95616, USA - + - + @@ -116,16 +116,10 @@ Davis, CA 95616, USA - - - - + - - - - + diff --git a/data_model/master/device_types/OnOffLightSwitch.xml b/data_model/1.5.1/device_types/OnOffLightSwitch.xml similarity index 97% rename from data_model/master/device_types/OnOffLightSwitch.xml rename to data_model/1.5.1/device_types/OnOffLightSwitch.xml index b0d2c4b72e1..0d4f9df19fc 100644 --- a/data_model/master/device_types/OnOffLightSwitch.xml +++ b/data_model/1.5.1/device_types/OnOffLightSwitch.xml @@ -78,10 +78,7 @@ Davis, CA 95616, USA - - - - + diff --git a/data_model/master/device_types/OnOffPlug-inUnit.xml b/data_model/1.5.1/device_types/OnOffPlug-inUnit.xml similarity index 92% rename from data_model/master/device_types/OnOffPlug-inUnit.xml rename to data_model/1.5.1/device_types/OnOffPlug-inUnit.xml index 8eaf090f913..9d3c5b818fa 100644 --- a/data_model/master/device_types/OnOffPlug-inUnit.xml +++ b/data_model/1.5.1/device_types/OnOffPlug-inUnit.xml @@ -57,11 +57,12 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -79,7 +80,7 @@ Davis, CA 95616, USA - + @@ -87,10 +88,10 @@ Davis, CA 95616, USA - + - + @@ -116,16 +117,10 @@ Davis, CA 95616, USA - - - - + - - - - + diff --git a/data_model/master/device_types/OnOffSensor.xml b/data_model/1.5.1/device_types/OnOffSensor.xml similarity index 97% rename from data_model/master/device_types/OnOffSensor.xml rename to data_model/1.5.1/device_types/OnOffSensor.xml index 97f6fb5e92c..8a1a7a9add4 100644 --- a/data_model/master/device_types/OnOffSensor.xml +++ b/data_model/1.5.1/device_types/OnOffSensor.xml @@ -81,10 +81,7 @@ Davis, CA 95616, USA - - - - + diff --git a/data_model/master/device_types/OtaProvider.xml b/data_model/1.5.1/device_types/OtaProvider.xml similarity index 100% rename from data_model/master/device_types/OtaProvider.xml rename to data_model/1.5.1/device_types/OtaProvider.xml diff --git a/data_model/master/device_types/OtaRequestor.xml b/data_model/1.5.1/device_types/OtaRequestor.xml similarity index 100% rename from data_model/master/device_types/OtaRequestor.xml rename to data_model/1.5.1/device_types/OtaRequestor.xml diff --git a/data_model/master/device_types/Oven.xml b/data_model/1.5.1/device_types/Oven.xml similarity index 94% rename from data_model/master/device_types/Oven.xml rename to data_model/1.5.1/device_types/Oven.xml index 01ee5222f3f..193ce51d779 100644 --- a/data_model/master/device_types/Oven.xml +++ b/data_model/1.5.1/device_types/Oven.xml @@ -63,6 +63,13 @@ Davis, CA 95616, USA + + + + + + + diff --git a/data_model/master/device_types/PowerSource.xml b/data_model/1.5.1/device_types/PowerSource.xml similarity index 100% rename from data_model/master/device_types/PowerSource.xml rename to data_model/1.5.1/device_types/PowerSource.xml diff --git a/data_model/master/device_types/PressureSensor.xml b/data_model/1.5.1/device_types/PressureSensor.xml similarity index 95% rename from data_model/master/device_types/PressureSensor.xml rename to data_model/1.5.1/device_types/PressureSensor.xml index bc58e53e291..bacc9b3b9a1 100644 --- a/data_model/master/device_types/PressureSensor.xml +++ b/data_model/1.5.1/device_types/PressureSensor.xml @@ -57,21 +57,17 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + - - - - - diff --git a/data_model/master/device_types/Pump.xml b/data_model/1.5.1/device_types/Pump.xml similarity index 97% rename from data_model/master/device_types/Pump.xml rename to data_model/1.5.1/device_types/Pump.xml index c27122ba2f2..d4c97472fa8 100644 --- a/data_model/master/device_types/Pump.xml +++ b/data_model/1.5.1/device_types/Pump.xml @@ -78,10 +78,7 @@ Davis, CA 95616, USA - - - - + diff --git a/data_model/master/device_types/PumpController.xml b/data_model/1.5.1/device_types/PumpController.xml similarity index 97% rename from data_model/master/device_types/PumpController.xml rename to data_model/1.5.1/device_types/PumpController.xml index 8dc958c3a5a..d06239adafa 100644 --- a/data_model/master/device_types/PumpController.xml +++ b/data_model/1.5.1/device_types/PumpController.xml @@ -82,10 +82,7 @@ Davis, CA 95616, USA - - - - + diff --git a/data_model/master/device_types/RainSensor.xml b/data_model/1.5.1/device_types/RainSensor.xml similarity index 100% rename from data_model/master/device_types/RainSensor.xml rename to data_model/1.5.1/device_types/RainSensor.xml diff --git a/data_model/master/device_types/Refrigerator.xml b/data_model/1.5.1/device_types/Refrigerator.xml similarity index 94% rename from data_model/master/device_types/Refrigerator.xml rename to data_model/1.5.1/device_types/Refrigerator.xml index 9cbbc124103..6d22572b3fc 100644 --- a/data_model/master/device_types/Refrigerator.xml +++ b/data_model/1.5.1/device_types/Refrigerator.xml @@ -63,6 +63,13 @@ Davis, CA 95616, USA + + + + + + + @@ -70,7 +77,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/device_types/RoboticVacuumCleaner.xml b/data_model/1.5.1/device_types/RoboticVacuumCleaner.xml similarity index 98% rename from data_model/master/device_types/RoboticVacuumCleaner.xml rename to data_model/1.5.1/device_types/RoboticVacuumCleaner.xml index d657d01d198..b4561bd9ed3 100644 --- a/data_model/master/device_types/RoboticVacuumCleaner.xml +++ b/data_model/1.5.1/device_types/RoboticVacuumCleaner.xml @@ -78,7 +78,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/device_types/RoomAirConditioner.xml b/data_model/1.5.1/device_types/RoomAirConditioner.xml similarity index 92% rename from data_model/master/device_types/RoomAirConditioner.xml rename to data_model/1.5.1/device_types/RoomAirConditioner.xml index 60ced5dac42..0cb9a3998a1 100644 --- a/data_model/master/device_types/RoomAirConditioner.xml +++ b/data_model/1.5.1/device_types/RoomAirConditioner.xml @@ -57,10 +57,11 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -73,16 +74,19 @@ Davis, CA 95616, USA - + - - - - + + + + + + + diff --git a/data_model/master/device_types/RootNodeDeviceType.xml b/data_model/1.5.1/device_types/RootNodeDeviceType.xml similarity index 55% rename from data_model/master/device_types/RootNodeDeviceType.xml rename to data_model/1.5.1/device_types/RootNodeDeviceType.xml index 7208e9a4e1d..e9db0c1cf17 100644 --- a/data_model/master/device_types/RootNodeDeviceType.xml +++ b/data_model/1.5.1/device_types/RootNodeDeviceType.xml @@ -1,4 +1,4 @@ - + - + + + + + + + + + + - + + + + + + + + @@ -149,13 +165,118 @@ Davis, CA 95616, USA - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -172,12 +293,30 @@ Davis, CA 95616, USA - + + + + + + + + + + + + + + + + + + + diff --git a/data_model/master/device_types/SecondaryNetworkInterface.xml b/data_model/1.5.1/device_types/SecondaryNetworkInterface.xml similarity index 100% rename from data_model/master/device_types/SecondaryNetworkInterface.xml rename to data_model/1.5.1/device_types/SecondaryNetworkInterface.xml diff --git a/data_model/master/device_types/SmokeCOAlarm.xml b/data_model/1.5.1/device_types/SmokeCOAlarm.xml similarity index 100% rename from data_model/master/device_types/SmokeCOAlarm.xml rename to data_model/1.5.1/device_types/SmokeCOAlarm.xml diff --git a/data_model/master/device_types/SnapshotCamera.xml b/data_model/1.5.1/device_types/SnapshotCamera.xml similarity index 89% rename from data_model/master/device_types/SnapshotCamera.xml rename to data_model/1.5.1/device_types/SnapshotCamera.xml index b7dd302dfe3..f39717fcff0 100644 --- a/data_model/master/device_types/SnapshotCamera.xml +++ b/data_model/1.5.1/device_types/SnapshotCamera.xml @@ -62,32 +62,41 @@ Davis, CA 95616, USA + + + + + + + + + + - - - - - - + + + + + - + - + - + diff --git a/data_model/master/device_types/SoilSensor.xml b/data_model/1.5.1/device_types/SoilSensor.xml similarity index 100% rename from data_model/master/device_types/SoilSensor.xml rename to data_model/1.5.1/device_types/SoilSensor.xml diff --git a/data_model/master/device_types/SolarPower.xml b/data_model/1.5.1/device_types/SolarPower.xml similarity index 84% rename from data_model/master/device_types/SolarPower.xml rename to data_model/1.5.1/device_types/SolarPower.xml index 21bedacedfe..d0875d1f864 100644 --- a/data_model/master/device_types/SolarPower.xml +++ b/data_model/1.5.1/device_types/SolarPower.xml @@ -67,4 +67,24 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + diff --git a/data_model/master/device_types/Speaker.xml b/data_model/1.5.1/device_types/Speaker.xml similarity index 98% rename from data_model/master/device_types/Speaker.xml rename to data_model/1.5.1/device_types/Speaker.xml index fa2712c29c5..62889337917 100644 --- a/data_model/master/device_types/Speaker.xml +++ b/data_model/1.5.1/device_types/Speaker.xml @@ -63,7 +63,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/master/device_types/TemperatureControlledCabinet.xml b/data_model/1.5.1/device_types/TemperatureControlledCabinet.xml similarity index 95% rename from data_model/master/device_types/TemperatureControlledCabinet.xml rename to data_model/1.5.1/device_types/TemperatureControlledCabinet.xml index 91b8052b919..06ce9f3cdf3 100644 --- a/data_model/master/device_types/TemperatureControlledCabinet.xml +++ b/data_model/1.5.1/device_types/TemperatureControlledCabinet.xml @@ -84,7 +84,7 @@ Davis, CA 95616, USA - + @@ -94,7 +94,7 @@ Davis, CA 95616, USA - + @@ -104,12 +104,12 @@ Davis, CA 95616, USA - + - + @@ -122,10 +122,10 @@ Davis, CA 95616, USA - + - + diff --git a/data_model/master/device_types/TemperatureSensor.xml b/data_model/1.5.1/device_types/TemperatureSensor.xml similarity index 95% rename from data_model/master/device_types/TemperatureSensor.xml rename to data_model/1.5.1/device_types/TemperatureSensor.xml index 6d4b65d2956..728edf50222 100644 --- a/data_model/master/device_types/TemperatureSensor.xml +++ b/data_model/1.5.1/device_types/TemperatureSensor.xml @@ -61,20 +61,20 @@ Davis, CA 95616, USA - + - - - - - + + + + + diff --git a/data_model/master/device_types/Thermostat.xml b/data_model/1.5.1/device_types/Thermostat.xml similarity index 88% rename from data_model/master/device_types/Thermostat.xml rename to data_model/1.5.1/device_types/Thermostat.xml index 4ef8aca4b14..f2cfa562d8c 100644 --- a/data_model/master/device_types/Thermostat.xml +++ b/data_model/1.5.1/device_types/Thermostat.xml @@ -57,12 +57,13 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + @@ -74,32 +75,11 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/device_types/ThermostatController.xml b/data_model/1.5.1/device_types/ThermostatController.xml similarity index 97% rename from data_model/master/device_types/ThermostatController.xml rename to data_model/1.5.1/device_types/ThermostatController.xml index 5ea3dbe35e3..2970767667f 100644 --- a/data_model/master/device_types/ThermostatController.xml +++ b/data_model/1.5.1/device_types/ThermostatController.xml @@ -70,10 +70,7 @@ Davis, CA 95616, USA - - - - + diff --git a/data_model/master/device_types/ThreadBorderRouter.xml b/data_model/1.5.1/device_types/ThreadBorderRouter.xml similarity index 95% rename from data_model/master/device_types/ThreadBorderRouter.xml rename to data_model/1.5.1/device_types/ThreadBorderRouter.xml index e1f6326d6bf..724a3146845 100644 --- a/data_model/master/device_types/ThreadBorderRouter.xml +++ b/data_model/1.5.1/device_types/ThreadBorderRouter.xml @@ -57,15 +57,13 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + - - - diff --git a/data_model/master/device_types/VideoDoorbell.xml b/data_model/1.5.1/device_types/VideoDoorbell.xml similarity index 100% rename from data_model/master/device_types/VideoDoorbell.xml rename to data_model/1.5.1/device_types/VideoDoorbell.xml diff --git a/data_model/master/device_types/VideoRemoteControl.xml b/data_model/1.5.1/device_types/VideoRemoteControl.xml similarity index 97% rename from data_model/master/device_types/VideoRemoteControl.xml rename to data_model/1.5.1/device_types/VideoRemoteControl.xml index 57e29b9e838..823cd861d3f 100644 --- a/data_model/master/device_types/VideoRemoteControl.xml +++ b/data_model/1.5.1/device_types/VideoRemoteControl.xml @@ -64,13 +64,13 @@ Davis, CA 95616, USA - + - + diff --git a/data_model/master/device_types/WaterFreezeDetector.xml b/data_model/1.5.1/device_types/WaterFreezeDetector.xml similarity index 100% rename from data_model/master/device_types/WaterFreezeDetector.xml rename to data_model/1.5.1/device_types/WaterFreezeDetector.xml diff --git a/data_model/master/device_types/WaterHeater.xml b/data_model/1.5.1/device_types/WaterHeater.xml similarity index 81% rename from data_model/master/device_types/WaterHeater.xml rename to data_model/1.5.1/device_types/WaterHeater.xml index 014d5d934bc..5f04901b9e3 100644 --- a/data_model/master/device_types/WaterHeater.xml +++ b/data_model/1.5.1/device_types/WaterHeater.xml @@ -69,19 +69,47 @@ Davis, CA 95616, USA - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + diff --git a/data_model/master/device_types/WaterLeakDetector.xml b/data_model/1.5.1/device_types/WaterLeakDetector.xml similarity index 100% rename from data_model/master/device_types/WaterLeakDetector.xml rename to data_model/1.5.1/device_types/WaterLeakDetector.xml diff --git a/data_model/master/device_types/WaterValve.xml b/data_model/1.5.1/device_types/WaterValve.xml similarity index 100% rename from data_model/master/device_types/WaterValve.xml rename to data_model/1.5.1/device_types/WaterValve.xml diff --git a/data_model/master/device_types/WindowCovering.xml b/data_model/1.5.1/device_types/WindowCovering.xml similarity index 91% rename from data_model/master/device_types/WindowCovering.xml rename to data_model/1.5.1/device_types/WindowCovering.xml index e63757104db..85cc80cea60 100644 --- a/data_model/master/device_types/WindowCovering.xml +++ b/data_model/1.5.1/device_types/WindowCovering.xml @@ -57,12 +57,14 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + + + @@ -79,13 +81,12 @@ Davis, CA 95616, USA - - - - - - - + + + + + + diff --git a/data_model/master/device_types/WindowCoveringController.xml b/data_model/1.5.1/device_types/WindowCoveringController.xml similarity index 93% rename from data_model/master/device_types/WindowCoveringController.xml rename to data_model/1.5.1/device_types/WindowCoveringController.xml index 7b127dbca08..696b5cbe527 100644 --- a/data_model/master/device_types/WindowCoveringController.xml +++ b/data_model/1.5.1/device_types/WindowCoveringController.xml @@ -62,7 +62,7 @@ Davis, CA 95616, USA - + @@ -82,13 +82,6 @@ Davis, CA 95616, USA - - - - - - - diff --git a/data_model/1.5.1/device_types/device_type_ids.json b/data_model/1.5.1/device_types/device_type_ids.json new file mode 100644 index 00000000000..d47eef2eb82 --- /dev/null +++ b/data_model/1.5.1/device_types/device_type_ids.json @@ -0,0 +1,93 @@ +{ + "10": "Door Lock", + "11": "Door Lock Controller", + "14": "Aggregator", + "15": "Generic Switch", + "17": "Power Source", + "18": "OTA Requestor", + "19": "Bridged Node", + "20": "OTA Provider", + "21": "Contact Sensor", + "22": "Root Node", + "23": "Solar Power", + "24": "Battery Storage", + "25": "Secondary Network Interface", + "34": "Speaker", + "35": "Casting Video Player", + "36": "Content App", + "39": "Mode Select", + "40": "Basic Video Player", + "41": "Casting Video Client", + "42": "Video Remote Control", + "43": "Fan", + "44": "Air Quality Sensor", + "45": "Air Purifier", + "64": "Irrigation System", + "65": "Water Freeze Detector", + "66": "Water Valve", + "67": "Water Leak Detector", + "68": "Rain Sensor", + "69": "Soil Sensor", + "112": "Refrigerator", + "113": "Temperature Controlled Cabinet", + "114": "Room Air Conditioner", + "115": "Laundry Washer", + "116": "Robotic Vacuum Cleaner", + "117": "Dishwasher", + "118": "Smoke CO Alarm", + "119": "Cook Surface", + "120": "Cooktop", + "121": "Microwave Oven", + "122": "Extractor Hood", + "123": "Oven", + "124": "Laundry Dryer", + "144": "Network Infrastructure Manager", + "145": "Thread Border Router", + "256": "On/Off Light", + "257": "Dimmable Light", + "259": "On/Off Light Switch", + "260": "Dimmer Switch", + "261": "Color Dimmer Switch", + "262": "Light Sensor", + "263": "Occupancy Sensor", + "266": "On/Off Plug-in Unit", + "267": "Dimmable Plug-In Unit", + "268": "Color Temperature Light", + "269": "Extended Color Light", + "271": "Mounted On/Off Control", + "272": "Mounted Dimmable Load Control", + "304": "Joint Fabric Administrator", + "320": "Intercom", + "321": "Audio Doorbell", + "322": "Camera", + "323": "Video Doorbell", + "324": "Floodlight Camera", + "325": "Snapshot Camera", + "326": "Chime", + "327": "Camera Controller", + "328": "Doorbell", + "514": "Window Covering", + "515": "Window Covering Controller", + "560": "Closure", + "561": "Closure Panel", + "574": "Closure Controller", + "769": "Thermostat", + "770": "Temperature Sensor", + "771": "Pump", + "772": "Pump Controller", + "773": "Pressure Sensor", + "774": "Flow Sensor", + "775": "Humidity Sensor", + "777": "Heat Pump", + "778": "Thermostat Controller", + "1292": "Energy EVSE", + "1293": "Device Energy Management", + "1295": "Water Heater", + "1296": "Electrical Sensor", + "1297": "Electrical Utility Meter", + "1298": "Meter Reference Point", + "1299": "Electrical Energy Tariff", + "1300": "Electrical Meter", + "2112": "Control Bridge", + "2128": "On/Off Sensor" +} diff --git a/data_model/master/clusters/Label-Cluster-LabelCluster.xml b/data_model/1.5.1/globals/Bitmaps.xml similarity index 66% rename from data_model/master/clusters/Label-Cluster-LabelCluster.xml rename to data_model/1.5.1/globals/Bitmaps.xml index b9cd9e7f440..ab815523e17 100644 --- a/data_model/master/clusters/Label-Cluster-LabelCluster.xml +++ b/data_model/1.5.1/globals/Bitmaps.xml @@ -1,6 +1,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data_model/master/clusters/Label-Cluster-UserLabelCluster.xml b/data_model/1.5.1/globals/Commands.xml similarity index 75% rename from data_model/master/clusters/Label-Cluster-UserLabelCluster.xml rename to data_model/1.5.1/globals/Commands.xml index 449e0b38b98..f7a69315211 100644 --- a/data_model/master/clusters/Label-Cluster-UserLabelCluster.xml +++ b/data_model/1.5.1/globals/Commands.xml @@ -1,6 +1,6 @@ - - - - - - - - - - - - - + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data_model/1.5.1/globals/Enums.xml b/data_model/1.5.1/globals/Enums.xml new file mode 100644 index 00000000000..75539883819 --- /dev/null +++ b/data_model/1.5.1/globals/Enums.xml @@ -0,0 +1,247 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data_model/1.5.1/globals/Structs.xml b/data_model/1.5.1/globals/Structs.xml new file mode 100644 index 00000000000..60fba440dd6 --- /dev/null +++ b/data_model/1.5.1/globals/Structs.xml @@ -0,0 +1,371 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + subtract + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data_model/master/device_types/AudioDoorbell.xml b/data_model/1.5.1/globals/TypeDefs.xml similarity index 89% rename from data_model/master/device_types/AudioDoorbell.xml rename to data_model/1.5.1/globals/TypeDefs.xml index a78235dbc46..d6c6b2a73c3 100644 --- a/data_model/master/device_types/AudioDoorbell.xml +++ b/data_model/1.5.1/globals/TypeDefs.xml @@ -1,6 +1,6 @@ - - - - - - + + + diff --git a/data_model/master/namespaces/Namespace-Closure-Cabinet.xml b/data_model/1.5.1/namespaces/Namespace-Closure-Cabinet.xml similarity index 100% rename from data_model/master/namespaces/Namespace-Closure-Cabinet.xml rename to data_model/1.5.1/namespaces/Namespace-Closure-Cabinet.xml diff --git a/data_model/master/namespaces/Namespace-Closure-Covering.xml b/data_model/1.5.1/namespaces/Namespace-Closure-Covering.xml similarity index 100% rename from data_model/master/namespaces/Namespace-Closure-Covering.xml rename to data_model/1.5.1/namespaces/Namespace-Closure-Covering.xml diff --git a/data_model/master/namespaces/Namespace-Closure-Window.xml b/data_model/1.5.1/namespaces/Namespace-Closure-Window.xml similarity index 100% rename from data_model/master/namespaces/Namespace-Closure-Window.xml rename to data_model/1.5.1/namespaces/Namespace-Closure-Window.xml diff --git a/data_model/master/namespaces/Namespace-Closure.xml b/data_model/1.5.1/namespaces/Namespace-Closure.xml similarity index 99% rename from data_model/master/namespaces/Namespace-Closure.xml rename to data_model/1.5.1/namespaces/Namespace-Closure.xml index eb34a46ba22..bb13f60596e 100644 --- a/data_model/master/namespaces/Namespace-Closure.xml +++ b/data_model/1.5.1/namespaces/Namespace-Closure.xml @@ -74,7 +74,7 @@ Davis, CA 95616, USA A movable barrier that controls entry or exit through an opening in a fence, wall, or enclosure. - + A large, movable barrier that provides access to a garage. diff --git a/data_model/master/namespaces/Namespace-ClosurePanel.xml b/data_model/1.5.1/namespaces/Namespace-ClosurePanel.xml similarity index 100% rename from data_model/master/namespaces/Namespace-ClosurePanel.xml rename to data_model/1.5.1/namespaces/Namespace-ClosurePanel.xml diff --git a/data_model/master/namespaces/Namespace-CommodityTariff-Chronology.xml b/data_model/1.5.1/namespaces/Namespace-CommodityTariff-Chronology.xml similarity index 100% rename from data_model/master/namespaces/Namespace-CommodityTariff-Chronology.xml rename to data_model/1.5.1/namespaces/Namespace-CommodityTariff-Chronology.xml diff --git a/data_model/master/namespaces/Namespace-CommodityTariff-Commodity.xml b/data_model/1.5.1/namespaces/Namespace-CommodityTariff-Commodity.xml similarity index 100% rename from data_model/master/namespaces/Namespace-CommodityTariff-Commodity.xml rename to data_model/1.5.1/namespaces/Namespace-CommodityTariff-Commodity.xml diff --git a/data_model/master/namespaces/Namespace-CommodityTariff-Flow.xml b/data_model/1.5.1/namespaces/Namespace-CommodityTariff-Flow.xml similarity index 100% rename from data_model/master/namespaces/Namespace-CommodityTariff-Flow.xml rename to data_model/1.5.1/namespaces/Namespace-CommodityTariff-Flow.xml diff --git a/data_model/master/namespaces/Namespace-Common-Area.xml b/data_model/1.5.1/namespaces/Namespace-Common-Area.xml similarity index 99% rename from data_model/master/namespaces/Namespace-Common-Area.xml rename to data_model/1.5.1/namespaces/Namespace-Common-Area.xml index c25dab0d855..0f13aab8dc1 100644 --- a/data_model/master/namespaces/Namespace-Common-Area.xml +++ b/data_model/1.5.1/namespaces/Namespace-Common-Area.xml @@ -128,10 +128,10 @@ Davis, CA 95616, USA - + A space used to remove soiled garments prior to entering the domicile proper - + diff --git a/data_model/master/clusters/Label-Cluster-FixedLabelCluster.xml b/data_model/1.5.1/namespaces/Namespace-Common-Closure.xml similarity index 81% rename from data_model/master/clusters/Label-Cluster-FixedLabelCluster.xml rename to data_model/1.5.1/namespaces/Namespace-Common-Closure.xml index 12bec55222c..6cc806308e3 100644 --- a/data_model/master/clusters/Label-Cluster-FixedLabelCluster.xml +++ b/data_model/1.5.1/namespaces/Namespace-Common-Closure.xml @@ -57,20 +57,16 @@ Davis, CA 95616, USA :xrefstyle: basic --> - - - - - - - - - - - - - - - - - + + + + Move toward open position + + + Move toward closed position + + + Stop any movement + + + diff --git a/data_model/master/namespaces/Namespace-Common-CompassDirection.xml b/data_model/1.5.1/namespaces/Namespace-Common-CompassDirection.xml similarity index 100% rename from data_model/master/namespaces/Namespace-Common-CompassDirection.xml rename to data_model/1.5.1/namespaces/Namespace-Common-CompassDirection.xml diff --git a/data_model/master/namespaces/Namespace-Common-CompassLocation.xml b/data_model/1.5.1/namespaces/Namespace-Common-CompassLocation.xml similarity index 100% rename from data_model/master/namespaces/Namespace-Common-CompassLocation.xml rename to data_model/1.5.1/namespaces/Namespace-Common-CompassLocation.xml diff --git a/data_model/master/namespaces/Namespace-Common-Direction.xml b/data_model/1.5.1/namespaces/Namespace-Common-Direction.xml similarity index 100% rename from data_model/master/namespaces/Namespace-Common-Direction.xml rename to data_model/1.5.1/namespaces/Namespace-Common-Direction.xml diff --git a/data_model/master/namespaces/Namespace-Common-Landmark.xml b/data_model/1.5.1/namespaces/Namespace-Common-Landmark.xml similarity index 100% rename from data_model/master/namespaces/Namespace-Common-Landmark.xml rename to data_model/1.5.1/namespaces/Namespace-Common-Landmark.xml diff --git a/data_model/master/namespaces/Namespace-Common-Level.xml b/data_model/1.5.1/namespaces/Namespace-Common-Level.xml similarity index 100% rename from data_model/master/namespaces/Namespace-Common-Level.xml rename to data_model/1.5.1/namespaces/Namespace-Common-Level.xml diff --git a/data_model/master/namespaces/Namespace-Common-Location.xml b/data_model/1.5.1/namespaces/Namespace-Common-Location.xml similarity index 95% rename from data_model/master/namespaces/Namespace-Common-Location.xml rename to data_model/1.5.1/namespaces/Namespace-Common-Location.xml index fce22bcb512..453ea6e1581 100644 --- a/data_model/master/namespaces/Namespace-Common-Location.xml +++ b/data_model/1.5.1/namespaces/Namespace-Common-Location.xml @@ -69,7 +69,10 @@ Davis, CA 95616, USA Element is located inside the equipment (e.g. a sensor "inside" a cabinet). - Element is located outside the equipment (e.g. a sensor "outside" a cabinet) + Element is located outside the equipment (e.g. a sensor "outside" a cabinet). + + + Element is a part of a location divided into zones (e.g. a yard irrigation zone). diff --git a/data_model/master/namespaces/Namespace-Common-Number.xml b/data_model/1.5.1/namespaces/Namespace-Common-Number.xml similarity index 83% rename from data_model/master/namespaces/Namespace-Common-Number.xml rename to data_model/1.5.1/namespaces/Namespace-Common-Number.xml index 53917dcb9cc..2e54510f51d 100644 --- a/data_model/master/namespaces/Namespace-Common-Number.xml +++ b/data_model/1.5.1/namespaces/Namespace-Common-Number.xml @@ -70,5 +70,25 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + diff --git a/data_model/master/namespaces/Namespace-Common-Position.xml b/data_model/1.5.1/namespaces/Namespace-Common-Position.xml similarity index 100% rename from data_model/master/namespaces/Namespace-Common-Position.xml rename to data_model/1.5.1/namespaces/Namespace-Common-Position.xml diff --git a/data_model/master/namespaces/Namespace-Common-RelativePosition.xml b/data_model/1.5.1/namespaces/Namespace-Common-RelativePosition.xml similarity index 100% rename from data_model/master/namespaces/Namespace-Common-RelativePosition.xml rename to data_model/1.5.1/namespaces/Namespace-Common-RelativePosition.xml diff --git a/data_model/master/namespaces/Namespace-ElectricalMeasurement.xml b/data_model/1.5.1/namespaces/Namespace-ElectricalMeasurement.xml similarity index 100% rename from data_model/master/namespaces/Namespace-ElectricalMeasurement.xml rename to data_model/1.5.1/namespaces/Namespace-ElectricalMeasurement.xml diff --git a/data_model/master/namespaces/Namespace-Laundry.xml b/data_model/1.5.1/namespaces/Namespace-Laundry.xml similarity index 100% rename from data_model/master/namespaces/Namespace-Laundry.xml rename to data_model/1.5.1/namespaces/Namespace-Laundry.xml diff --git a/data_model/master/namespaces/Namespace-PowerSource.xml b/data_model/1.5.1/namespaces/Namespace-PowerSource.xml similarity index 100% rename from data_model/master/namespaces/Namespace-PowerSource.xml rename to data_model/1.5.1/namespaces/Namespace-PowerSource.xml diff --git a/data_model/master/namespaces/Namespace-Refrigerator.xml b/data_model/1.5.1/namespaces/Namespace-Refrigerator.xml similarity index 100% rename from data_model/master/namespaces/Namespace-Refrigerator.xml rename to data_model/1.5.1/namespaces/Namespace-Refrigerator.xml diff --git a/data_model/master/namespaces/Namespace-RoomAirConditioner.xml b/data_model/1.5.1/namespaces/Namespace-RoomAirConditioner.xml similarity index 100% rename from data_model/master/namespaces/Namespace-RoomAirConditioner.xml rename to data_model/1.5.1/namespaces/Namespace-RoomAirConditioner.xml diff --git a/data_model/master/namespaces/Namespace-Switches.xml b/data_model/1.5.1/namespaces/Namespace-Switches.xml similarity index 100% rename from data_model/master/namespaces/Namespace-Switches.xml rename to data_model/1.5.1/namespaces/Namespace-Switches.xml diff --git a/data_model/1.5.1/scraper_version b/data_model/1.5.1/scraper_version new file mode 100644 index 00000000000..1a2c94536a4 --- /dev/null +++ b/data_model/1.5.1/scraper_version @@ -0,0 +1 @@ +alchemy version: v1.6.8 diff --git a/data_model/1.5.1/spec_sha b/data_model/1.5.1/spec_sha new file mode 100644 index 00000000000..687c391f80d --- /dev/null +++ b/data_model/1.5.1/spec_sha @@ -0,0 +1 @@ +7426ff7f7dd256532c45611762cae3a3b81cda32 diff --git a/data_model/1.5.1/spec_tag b/data_model/1.5.1/spec_tag new file mode 100644 index 00000000000..0240264d15e --- /dev/null +++ b/data_model/1.5.1/spec_tag @@ -0,0 +1 @@ +0.9-winter-2026 diff --git a/data_model/master/clusters/AmbientContextSensing.xml b/data_model/master/clusters/AmbientContextSensing.xml deleted file mode 100644 index fc0bdee2b84..00000000000 --- a/data_model/master/clusters/AmbientContextSensing.xml +++ /dev/null @@ -1,163 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/clusters/DemandResponseLoadControl.xml b/data_model/master/clusters/DemandResponseLoadControl.xml deleted file mode 100644 index d7776e73eb9..00000000000 --- a/data_model/master/clusters/DemandResponseLoadControl.xml +++ /dev/null @@ -1,519 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/clusters/Humidistat.xml b/data_model/master/clusters/Humidistat.xml deleted file mode 100644 index fec8bafb05d..00000000000 --- a/data_model/master/clusters/Humidistat.xml +++ /dev/null @@ -1,298 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/clusters/NetworkIdentityManagement.xml b/data_model/master/clusters/NetworkIdentityManagement.xml deleted file mode 100644 index 12a87243d94..00000000000 --- a/data_model/master/clusters/NetworkIdentityManagement.xml +++ /dev/null @@ -1,206 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/clusters/bridge-clusters-ActionsCluster.xml b/data_model/master/clusters/bridge-clusters-ActionsCluster.xml deleted file mode 100644 index d60bcd1e2d9..00000000000 --- a/data_model/master/clusters/bridge-clusters-ActionsCluster.xml +++ /dev/null @@ -1,413 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/clusters/bridge-clusters-BridgedDeviceBasicInformationCluster.xml b/data_model/master/clusters/bridge-clusters-BridgedDeviceBasicInformationCluster.xml deleted file mode 100644 index 303ba3f5802..00000000000 --- a/data_model/master/clusters/bridge-clusters-BridgedDeviceBasicInformationCluster.xml +++ /dev/null @@ -1,316 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/device_types/ClosureBaseDeviceTypes-Awning.xml b/data_model/master/device_types/ClosureBaseDeviceTypes-Awning.xml deleted file mode 100644 index c4c18459fd1..00000000000 --- a/data_model/master/device_types/ClosureBaseDeviceTypes-Awning.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/device_types/ClosureBaseDeviceTypes-Barrier.xml b/data_model/master/device_types/ClosureBaseDeviceTypes-Barrier.xml deleted file mode 100644 index c8389a85030..00000000000 --- a/data_model/master/device_types/ClosureBaseDeviceTypes-Barrier.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/device_types/ClosureBaseDeviceTypes-Blind.xml b/data_model/master/device_types/ClosureBaseDeviceTypes-Blind.xml deleted file mode 100644 index e148b80fdcf..00000000000 --- a/data_model/master/device_types/ClosureBaseDeviceTypes-Blind.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/device_types/ClosureBaseDeviceTypes-Cabinet.xml b/data_model/master/device_types/ClosureBaseDeviceTypes-Cabinet.xml deleted file mode 100644 index 775397161fc..00000000000 --- a/data_model/master/device_types/ClosureBaseDeviceTypes-Cabinet.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/device_types/ClosureBaseDeviceTypes-ClosureBase.xml b/data_model/master/device_types/ClosureBaseDeviceTypes-ClosureBase.xml deleted file mode 100644 index b17d5325460..00000000000 --- a/data_model/master/device_types/ClosureBaseDeviceTypes-ClosureBase.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/device_types/ClosureBaseDeviceTypes-Curtain.xml b/data_model/master/device_types/ClosureBaseDeviceTypes-Curtain.xml deleted file mode 100644 index 2a5d5633889..00000000000 --- a/data_model/master/device_types/ClosureBaseDeviceTypes-Curtain.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/device_types/ClosureBaseDeviceTypes-Door.xml b/data_model/master/device_types/ClosureBaseDeviceTypes-Door.xml deleted file mode 100644 index c6d7bb8fce1..00000000000 --- a/data_model/master/device_types/ClosureBaseDeviceTypes-Door.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/device_types/ClosureBaseDeviceTypes-GarageDoor.xml b/data_model/master/device_types/ClosureBaseDeviceTypes-GarageDoor.xml deleted file mode 100644 index ac72e15a76a..00000000000 --- a/data_model/master/device_types/ClosureBaseDeviceTypes-GarageDoor.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/device_types/ClosureBaseDeviceTypes-Gate.xml b/data_model/master/device_types/ClosureBaseDeviceTypes-Gate.xml deleted file mode 100644 index 0fac9ef75b1..00000000000 --- a/data_model/master/device_types/ClosureBaseDeviceTypes-Gate.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/device_types/ClosureBaseDeviceTypes-Pergola.xml b/data_model/master/device_types/ClosureBaseDeviceTypes-Pergola.xml deleted file mode 100644 index 7c1f2bd72db..00000000000 --- a/data_model/master/device_types/ClosureBaseDeviceTypes-Pergola.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/device_types/ClosureBaseDeviceTypes-Screen.xml b/data_model/master/device_types/ClosureBaseDeviceTypes-Screen.xml deleted file mode 100644 index 4ddec2e7c02..00000000000 --- a/data_model/master/device_types/ClosureBaseDeviceTypes-Screen.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/device_types/ClosureBaseDeviceTypes-Shade.xml b/data_model/master/device_types/ClosureBaseDeviceTypes-Shade.xml deleted file mode 100644 index 1346498e562..00000000000 --- a/data_model/master/device_types/ClosureBaseDeviceTypes-Shade.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/device_types/ClosureBaseDeviceTypes-Shutter.xml b/data_model/master/device_types/ClosureBaseDeviceTypes-Shutter.xml deleted file mode 100644 index c421c5ec51c..00000000000 --- a/data_model/master/device_types/ClosureBaseDeviceTypes-Shutter.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/device_types/ClosureBaseDeviceTypes-Window.xml b/data_model/master/device_types/ClosureBaseDeviceTypes-Window.xml deleted file mode 100644 index 8d53f6c6a0f..00000000000 --- a/data_model/master/device_types/ClosureBaseDeviceTypes-Window.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/master/scraper_version b/data_model/master/scraper_version deleted file mode 100644 index 6f7f0a8cb98..00000000000 --- a/data_model/master/scraper_version +++ /dev/null @@ -1 +0,0 @@ -alchemy version: v1.5.17 diff --git a/data_model/master/spec_sha b/data_model/master/spec_sha deleted file mode 100644 index f34f0787686..00000000000 --- a/data_model/master/spec_sha +++ /dev/null @@ -1 +0,0 @@ -9bd1d5052d58eb6d76e3b48afe1ae8ecd6f93271 diff --git a/docs/ids_and_codes/spec_clusters.md b/docs/ids_and_codes/spec_clusters.md index 1d286f3d6e0..88277d1f3bb 100644 --- a/docs/ids_and_codes/spec_clusters.md +++ b/docs/ids_and_codes/spec_clusters.md @@ -1,153 +1,151 @@ # List of currently defined spec clusters -This file was **AUTOMATICALLY** generated by `python scripts/generate_spec_xml.py`. DO NOT EDIT BY HAND! +This file was **AUTOMATICALLY** generated by +`python scripts/generate_spec_xml.py`. DO NOT EDIT BY HAND! -The following markers are used in this document (matches the ID master list): -| State | Description | -|-------|--------------------------------| -| blank | Not supported in this revision | -| C | Certifiable | -| P | Provisional | +The following markers are used in this document (matches the ID master list): | +State | Description | |-------|--------------------------------| | blank | Not +supported in this revision | | C | Certifiable | | P | Provisional | -| ID (Decimal) | ID (hex) | Name | PICS Code |1.2|1.3|1.4|1.4.1|1.4.2-mve-1|1.5| -|--------------|----------|----------------------------------------------------------|---------------|---|---|---|-----|-----------|---| -|3 |0x0003 |Identify |I |C |C |C |C |C |C | -|4 |0x0004 |Groups |G |C |C |C |C |C |C | -|5 |0x0005 |Scenes |S |C | | | | | | -|6 |0x0006 |On/Off |OO |C |C |C |C |C |C | -|8 |0x0008 |Level Control |LVL |C |C |C |C |C |C | -|28 |0x001C |Pulse Width Modulation |PWM |C |P | | | | | -|29 |0x001D |Descriptor |DESC |C |C |C |C |C |C | -|30 |0x001E |Binding |BIND |C |C |C |C |C |C | -|31 |0x001F |Access Control |ACL |C |C |C |C |C |C | -|37 |0x0025 |Actions |ACT |C |C |C |C |C |C | -|40 |0x0028 |Basic Information |BINFO |C |C |C |C |C |C | -|41 |0x0029 |OTA Software Update Provider |OTAP |C |C |C |C |C |C | -|42 |0x002A |OTA Software Update Requestor |OTAR |C |C |C |C |C |C | -|43 |0x002B |Localization Configuration |LCFG |C |C |C |C |C |C | -|44 |0x002C |Time Format Localization |LTIME |C |C |C |C |C |C | -|45 |0x002D |Unit Localization |LUNIT |C |C |C |C |C |C | -|46 |0x002E |Power Source Configuration |PSCFG |C |C |C |C |C |C | -|47 |0x002F |Power Source |PS |C |C |C |C |C |C | -|48 |0x0030 |General Commissioning |CGEN |C |C |C |C |C |C | -|49 |0x0031 |Network Commissioning |CNET |C |C |C |C |C |C | -|50 |0x0032 |Diagnostic Logs |DLOG |C |C |C |C |C |C | -|51 |0x0033 |General Diagnostics |DGGEN |C |C |C |C |C |C | -|52 |0x0034 |Software Diagnostics |DGSW |C |C |C |C |C |C | -|53 |0x0035 |Thread Network Diagnostics |DGTHREAD |C |C |C |C |C |C | -|54 |0x0036 |Wi-Fi Network Diagnostics |DGWIFI |C |C |C |C |C |C | -|55 |0x0037 |Ethernet Network Diagnostics |DGETH |C |C |C |C |C |C | -|56 |0x0038 |Time Synchronization |TIMESYNC |C |C |C |C |C |C | -|57 |0x0039 |Bridged Device Basic Information |BRBINFO |C |C |C |C |C |C | -|59 |0x003B |Switch |SWTCH |C |C |C |C |C |C | -|60 |0x003C |Administrator Commissioning |CADMIN |C |C |C |C |C |C | -|62 |0x003E |Operational Credentials |OPCREDS |C |C |C |C |C |C | -|63 |0x003F |Group Key Management |GRPKEY |C |C |C |C |C |C | -|64 |0x0040 |Fixed Label |FLABEL |C |C |C |C |C |C | -|65 |0x0041 |User Label |ULABEL |C |C |C |C |C |C | -|66 |0x0042 |Proxy Configuration |PXCFG |C |P |P |P | | | -|67 |0x0043 |Proxy Discovery |PXDSC |C |P |P |P | | | -|68 |0x0044 |Valid Proxies |PXVALID |C |P |P |P | | | -|69 |0x0045 |Boolean State |BOOL |C |C |C |C |C |C | -|70 |0x0046 |ICD Management |ICDM |C |C |C |C |C |C | -|72 |0x0048 |Oven Cavity Operational State |OVENOPSTATE | |C |C |C |C |C | -|73 |0x0049 |Oven Mode |OTCCM | |C |C |C |C |C | -|74 |0x004A |Laundry Dryer Controls |DRYERCTRL | |C |C |C |C |C | -|80 |0x0050 |Mode Select |MOD |C |C |C |C |C |C | -|81 |0x0051 |Laundry Washer Mode |LWM |C |C |C |C |C |C | -|82 |0x0052 |Refrigerator And Temperature Controlled Cabinet Mode |TCCM |C |C |C |C |C |C | -|83 |0x0053 |Laundry Washer Controls |WASHERCTRL |C |C |C |C |C |C | -|84 |0x0054 |RVC Run Mode |RVCRUNM |C |C |C |C |C |C | -|85 |0x0055 |RVC Clean Mode |RVCCLEANM |C |C |C |C |C |C | -|86 |0x0056 |Temperature Control |TCTL |C |C |C |C |C |C | -|87 |0x0057 |Refrigerator Alarm |REFALM |C |C |C |C |C |C | -|89 |0x0059 |Dishwasher Mode |DISHM |C |C |C |C |C |C | -|91 |0x005B |Air Quality |AIRQUAL |C |C |C |C |C |C | -|92 |0x005C |Smoke CO Alarm |SMOKECO |C |C |C |C |C |C | -|93 |0x005D |Dishwasher Alarm |DISHALM |C |C |C |C |C |C | -|94 |0x005E |Microwave Oven Mode |MWOM | |C |C |C |C |C | -|95 |0x005F |Microwave Oven Control |MWOCTRL | |C |C |C |C |C | -|96 |0x0060 |Operational State |OPSTATE |C |C |C |C |C |C | -|97 |0x0061 |RVC Operational State |RVCOPSTATE |C |C |C |C |C |C | -|98 |0x0062 |Scenes Management |S | |P |P |P |C |C | -|113 |0x0071 |HEPA Filter Monitoring |HEPAFREMON |C |C |C |C |C |C | -|114 |0x0072 |Activated Carbon Filter Monitoring |ACFREMON |C |C |C |C |C |C | -|121 |0x0079 |Water Tank Level Monitoring |REPM | | |C |C |C |C | -|128 |0x0080 |Boolean State Configuration |BOOLCFG | |C |C |C |C |C | -|129 |0x0081 |Valve Configuration and Control |VALCC | |C |C |C |C |C | -|144 |0x0090 |Electrical Power Measurement |EPM | |C |C |C |C |C | -|145 |0x0091 |Electrical Energy Measurement |EEM | |C |C |C |C |C | -|148 |0x0094 |Water Heater Management |EWATERHTR | | |C |C |C |C | -|149 |0x0095 |Commodity Price |SEPR | | | | | |C | -|151 |0x0097 |Messages |MESS | |C |C |C |C |C | -|152 |0x0098 |Device Energy Management |DEM | |P |C |C |C |C | -|153 |0x0099 |Energy EVSE |EEVSE | |C |C |C |C |C | -|155 |0x009B |Energy Preference |EPREF | |P |P |P |P |P | -|156 |0x009C |Power Topology |PWRTL | |C |C |C |C |C | -|157 |0x009D |Energy EVSE Mode |EEVSEM | |C |C |C |C |C | -|158 |0x009E |Water Heater Mode |WHM | | |C |C |C |C | -|159 |0x009F |Device Energy Management Mode |DEMM | |P |C |C |C |C | -|160 |0x00A0 |Electrical Grid Conditions |EGC | | | | | |C | -|257 |0x0101 |Door Lock |DRLK |C |C |C |C |C |C | -|258 |0x0102 |Window Covering |WNCV |C |C |C |C |C |C | -|260 |0x0104 |Closure Control |CLCTRL | | | | | |C | -|261 |0x0105 |Closure Dimension |CLDIM | | | | | |C | -|336 |0x0150 |Service Area |SEAR | | |C |C |C |C | -|512 |0x0200 |Pump Configuration and Control |PCC |C |C |C |C |C |C | -|513 |0x0201 |Thermostat |TSTAT |C |C |C |C |C |C | -|514 |0x0202 |Fan Control |FAN |C |C |C |C |C |C | -|516 |0x0204 |Thermostat User Interface Configuration |TSUIC |C |C |C |C |C |C | -|768 |0x0300 |Color Control |CC |C |C |C |C |C |C | -|769 |0x0301 |Ballast Configuration |BC |C |P |P |P | | | -|1024 |0x0400 |Illuminance Measurement |ILL |C |C |C |C |C |C | -|1026 |0x0402 |Temperature Measurement |TMP |C |C |C |C |C |C | -|1027 |0x0403 |Pressure Measurement |PRS |C |C |C |C |C |C | -|1028 |0x0404 |Flow Measurement |FLW |C |C |C |C |C |C | -|1029 |0x0405 |Relative Humidity Measurement |RH |C |C |C |C |C |C | -|1030 |0x0406 |Occupancy Sensing |OCC |C |C |C |C |C |C | -|1031 |0x0407 |Leaf Wetness Measurement |RH |C | | | | | | -|1032 |0x0408 |Soil Moisture Measurement |RH |C | | | | | | -|1036 |0x040C |Carbon Monoxide Concentration Measurement |CMOCONC |C |C |C |C |C |C | -|1037 |0x040D |Carbon Dioxide Concentration Measurement |CDOCONC |C |C |C |C |C |C | -|1043 |0x0413 |Nitrogen Dioxide Concentration Measurement |NDOCONC |C |C |C |C |C |C | -|1045 |0x0415 |Ozone Concentration Measurement |OZCONC |C |C |C |C |C |C | -|1066 |0x042A |PM2.5 Concentration Measurement |PMICONC |C |C |C |C |C |C | -|1067 |0x042B |Formaldehyde Concentration Measurement |FLDCONC |C |C |C |C |C |C | -|1068 |0x042C |PM1 Concentration Measurement |PMHCONC |C |C |C |C |C |C | -|1069 |0x042D |PM10 Concentration Measurement |PMKCONC |C |C |C |C |C |C | -|1070 |0x042E |Total Volatile Organic Compounds Concentration Measurement|TVOCCONC |C |C |C |C |C |C | -|1071 |0x042F |Radon Concentration Measurement |RNCONC |C |C |C |C |C |C | -|1072 |0x0430 |Soil Measurement |SOIL | | | | | |C | -|1105 |0x0451 |Wi-Fi Network Management |WIFINM | | |C |C |C |C | -|1106 |0x0452 |Thread Border Router Management |TBRM | | |C |C |C |C | -|1107 |0x0453 |Thread Network Directory |THNETDIR | | |C |C |C |C | -|1283 |0x0503 |Wake On LAN |WAKEONLAN |C |C |C |C |C |C | -|1284 |0x0504 |Channel |CHANNEL |C |C |C |C |C |C | -|1285 |0x0505 |Target Navigator |TGTNAV |C |C |C |C |C |C | -|1286 |0x0506 |Media Playback |MEDIAPLAYBACK |C |C |C |C |C |C | -|1287 |0x0507 |Media Input |MEDIAINPUT |C |C |C |C |C |C | -|1288 |0x0508 |Low Power |LOWPOWER |C |C |C |C |C |C | -|1289 |0x0509 |Keypad Input |KEYPADINPUT |C |C |C |C |C |C | -|1290 |0x050A |Content Launcher |CONTENTLAUNCHER|C |C |C |C |C |C | -|1291 |0x050B |Audio Output |AUDIOOUTPUT |C |C |C |C |C |C | -|1292 |0x050C |Application Launcher |APPLAUNCHER |C |C |C |C |C |C | -|1293 |0x050D |Application Basic |APBSC |C |C |C |C |C |C | -|1294 |0x050E |Account Login |ALOGIN |C |C |C |C |C |C | -|1295 |0x050F |Content Control |CONCON | |P |P |P |P |P | -|1296 |0x0510 |Content App Observer |APPOBSERVER | |C |C |C |C |C | -|1360 |0x0550 |Zone Management |ZONEMGMT | | | | | |C | -|1361 |0x0551 |Camera AV Stream Management |AVSM | | | | | |C | -|1362 |0x0552 |Camera AV Settings User Level Management |AVSUM | | | | | |C | -|1363 |0x0553 |WebRTC Transport Provider |WEBRTCP | | | | | |C | -|1364 |0x0554 |WebRTC Transport Requestor |WEBRTCR | | | | | |C | -|1365 |0x0555 |Push AV Stream Transport |PAVST | | | | | |C | -|1366 |0x0556 |Chime |CHIME | | | | | |C | -|1792 |0x0700 |Commodity Tariff |SETRF | | | | | |C | -|1872 |0x0750 |Ecosystem Information |ECOINFO | | |C |C |C |C | -|1873 |0x0751 |Commissioner Control |CCTRL | | |C |C |C |C | -|1874 |0x0752 |Joint Fabric Datastore |JFDS | | |P |P |P |P | -|1875 |0x0753 |Joint Fabric Administrator |JFPKI | | |P |P |P |P | -|2049 |0x0801 |TLS Certificate Management |TLSCERT | | | | | |C | -|2050 |0x0802 |TLS Client Management |TLSCLIENT | | | | | |C | -|2822 |0x0B06 |Meter Identification |MTRID | | | | | |C | -|2823 |0x0B07 |Commodity Metering |COMMTR | | | | | |C | +| ID (Decimal) | ID (hex) | Name | PICS Code | 1.0 | 1.1 | 1.2 | 1.3 | 1.4 | 1.4.1 | 1.4.2-mve-1 | 1.5 | 0.9-winter-2026 | +| ------------ | -------- | ---------------------------------------------------------- | --------------- | --- | --- | --- | --- | --- | ----- | ----------- | --- | --------------- | +| 3 | 0x0003 | Identify | I | C | C | C | C | C | C | C | C | C | +| 4 | 0x0004 | Groups | G | C | C | C | C | C | C | C | C | C | +| 5 | 0x0005 | Scenes | S | C | C | C | | | | | | | +| 6 | 0x0006 | On/Off | OO | C | C | C | C | C | C | C | C | C | +| 8 | 0x0008 | Level Control | LVL | C | C | C | C | C | C | C | C | C | +| 28 | 0x001C | Pulse Width Modulation | PWM | C | C | C | P | | | | | | +| 29 | 0x001D | Descriptor | DESC | C | C | C | C | C | C | C | C | C | +| 30 | 0x001E | Binding | BIND | C | C | C | C | C | C | C | C | C | +| 31 | 0x001F | Access Control | ACL | C | C | C | C | C | C | C | C | C | +| 37 | 0x0025 | Actions | ACT | C | C | C | C | C | C | C | C | C | +| 40 | 0x0028 | Basic Information | BINFO | C | C | C | C | C | C | C | C | C | +| 41 | 0x0029 | OTA Software Update Provider | OTAP | C | C | C | C | C | C | C | C | C | +| 42 | 0x002A | OTA Software Update Requestor | OTAR | C | C | C | C | C | C | C | C | C | +| 43 | 0x002B | Localization Configuration | LCFG | C | C | C | C | C | C | C | C | C | +| 44 | 0x002C | Time Format Localization | LTIME | C | C | C | C | C | C | C | C | C | +| 45 | 0x002D | Unit Localization | LUNIT | C | C | C | C | C | C | C | C | C | +| 46 | 0x002E | Power Source Configuration | PSCFG | C | C | C | C | C | C | C | C | C | +| 47 | 0x002F | Power Source | PS | C | C | C | C | C | C | C | C | C | +| 48 | 0x0030 | General Commissioning | CGEN | C | C | C | C | C | C | C | C | C | +| 49 | 0x0031 | Network Commissioning | CNET | C | C | C | C | C | C | C | C | C | +| 50 | 0x0032 | Diagnostic Logs | DLOG | C | C | C | C | C | C | C | C | C | +| 51 | 0x0033 | General Diagnostics | DGGEN | C | C | C | C | C | C | C | C | C | +| 52 | 0x0034 | Software Diagnostics | DGSW | C | C | C | C | C | C | C | C | C | +| 53 | 0x0035 | Thread Network Diagnostics | DGTHREAD | C | C | C | C | C | C | C | C | C | +| 54 | 0x0036 | Wi-Fi Network Diagnostics | DGWIFI | C | C | C | C | C | C | C | C | C | +| 55 | 0x0037 | Ethernet Network Diagnostics | DGETH | C | C | C | C | C | C | C | C | C | +| 56 | 0x0038 | Time Synchronization | TIMESYNC | C | C | C | C | C | C | C | C | C | +| 57 | 0x0039 | Bridged Device Basic Information | BRBINFO | C | C | C | C | C | C | C | C | C | +| 59 | 0x003B | Switch | SWTCH | C | C | C | C | C | C | C | C | C | +| 60 | 0x003C | Administrator Commissioning | CADMIN | C | C | C | C | C | C | C | C | C | +| 62 | 0x003E | Operational Credentials | OPCREDS | C | C | C | C | C | C | C | C | C | +| 63 | 0x003F | Group Key Management | GRPKEY | C | C | C | C | C | C | C | C | C | +| 64 | 0x0040 | Fixed Label | FLABEL | C | C | C | C | C | C | C | C | C | +| 65 | 0x0041 | User Label | ULABEL | C | C | C | C | C | C | C | C | C | +| 66 | 0x0042 | Proxy Configuration | PXCFG | C | C | C | P | P | P | | | | +| 67 | 0x0043 | Proxy Discovery | PXDSC | C | C | C | P | P | P | | | | +| 68 | 0x0044 | Valid Proxies | PXVALID | C | C | C | P | P | P | | | | +| 69 | 0x0045 | Boolean State | BOOL | C | C | C | C | C | C | C | C | C | +| 70 | 0x0046 | ICD Management | ICDM | | | C | C | C | C | C | C | C | +| 72 | 0x0048 | Oven Cavity Operational State | OVENOPSTATE | | | | C | C | C | C | C | C | +| 73 | 0x0049 | Oven Mode | OTCCM | | | | C | C | C | C | C | C | +| 74 | 0x004A | Laundry Dryer Controls | DRYERCTRL | | | | C | C | C | C | C | C | +| 80 | 0x0050 | Mode Select | MOD | C | C | C | C | C | C | C | C | C | +| 81 | 0x0051 | Laundry Washer Mode | LWM | | | C | C | C | C | C | C | C | +| 82 | 0x0052 | Refrigerator And Temperature Controlled Cabinet Mode | TCCM | | | C | C | C | C | C | C | C | +| 83 | 0x0053 | Laundry Washer Controls | WASHERCTRL | | | C | C | C | C | C | C | C | +| 84 | 0x0054 | RVC Run Mode | RVCRUNM | | | C | C | C | C | C | C | C | +| 85 | 0x0055 | RVC Clean Mode | RVCCLEANM | | | C | C | C | C | C | C | C | +| 86 | 0x0056 | Temperature Control | TCTL | | | C | C | C | C | C | C | C | +| 87 | 0x0057 | Refrigerator Alarm | REFALM | | | C | C | C | C | C | C | C | +| 89 | 0x0059 | Dishwasher Mode | DISHM | | | C | C | C | C | C | C | C | +| 91 | 0x005B | Air Quality | AIRQUAL | | | C | C | C | C | C | C | C | +| 92 | 0x005C | Smoke CO Alarm | SMOKECO | | | C | C | C | C | C | C | C | +| 93 | 0x005D | Dishwasher Alarm | DISHALM | | | C | C | C | C | C | C | C | +| 94 | 0x005E | Microwave Oven Mode | MWOM | | | | C | C | C | C | C | C | +| 95 | 0x005F | Microwave Oven Control | MWOCTRL | | | | C | C | C | C | C | C | +| 96 | 0x0060 | Operational State | OPSTATE | | | C | C | C | C | C | C | C | +| 97 | 0x0061 | RVC Operational State | RVCOPSTATE | | | C | C | C | C | C | C | C | +| 98 | 0x0062 | Scenes Management | S | | | | P | P | P | C | C | C | +| 113 | 0x0071 | HEPA Filter Monitoring | HEPAFREMON | | | C | C | C | C | C | C | C | +| 114 | 0x0072 | Activated Carbon Filter Monitoring | ACFREMON | | | C | C | C | C | C | C | C | +| 121 | 0x0079 | Water Tank Level Monitoring | REPM | | | | | C | C | C | C | C | +| 128 | 0x0080 | Boolean State Configuration | BOOLCFG | | | | C | C | C | C | C | C | +| 129 | 0x0081 | Valve Configuration and Control | VALCC | | | | C | C | C | C | C | C | +| 144 | 0x0090 | Electrical Power Measurement | EPM | | | | C | C | C | C | C | C | +| 145 | 0x0091 | Electrical Energy Measurement | EEM | | | | C | C | C | C | C | C | +| 148 | 0x0094 | Water Heater Management | EWATERHTR | | | | | C | C | C | C | C | +| 149 | 0x0095 | Commodity Price | SEPR | | | | | | | | C | C | +| 151 | 0x0097 | Messages | MESS | | | | C | C | C | C | C | C | +| 152 | 0x0098 | Device Energy Management | DEM | | | | P | C | C | C | C | C | +| 153 | 0x0099 | Energy EVSE | EEVSE | | | | C | C | C | C | C | C | +| 155 | 0x009B | Energy Preference | EPREF | | | | P | P | P | P | P | P | +| 156 | 0x009C | Power Topology | PWRTL | | | | C | C | C | C | C | C | +| 157 | 0x009D | Energy EVSE Mode | EEVSEM | | | | C | C | C | C | C | C | +| 158 | 0x009E | Water Heater Mode | WHM | | | | | C | C | C | C | C | +| 159 | 0x009F | Device Energy Management Mode | DEMM | | | | P | C | C | C | C | C | +| 160 | 0x00A0 | Electrical Grid Conditions | EGC | | | | | | | | C | C | +| 257 | 0x0101 | Door Lock | DRLK | C | C | C | C | C | C | C | C | C | +| 258 | 0x0102 | Window Covering | WNCV | C | C | C | C | C | C | C | C | C | +| 260 | 0x0104 | Closure Control | CLCTRL | | | | | | | | C | C | +| 261 | 0x0105 | Closure Dimension | CLDIM | | | | | | | | C | C | +| 336 | 0x0150 | Service Area | SEAR | | | | | C | C | C | C | C | +| 512 | 0x0200 | Pump Configuration and Control | PCC | C | C | C | C | C | C | C | C | C | +| 513 | 0x0201 | Thermostat | TSTAT | C | C | C | C | C | C | C | C | C | +| 514 | 0x0202 | Fan Control | FAN | C | C | C | C | C | C | C | C | C | +| 516 | 0x0204 | Thermostat User Interface Configuration | TSUIC | C | C | C | C | C | C | C | C | C | +| 768 | 0x0300 | Color Control | CC | C | C | C | C | C | C | C | C | C | +| 769 | 0x0301 | Ballast Configuration | BC | C | C | C | P | P | P | | | | +| 1024 | 0x0400 | Illuminance Measurement | ILL | C | C | C | C | C | C | C | C | C | +| 1026 | 0x0402 | Temperature Measurement | TMP | C | C | C | C | C | C | C | C | C | +| 1027 | 0x0403 | Pressure Measurement | PRS | C | C | C | C | C | C | C | C | C | +| 1028 | 0x0404 | Flow Measurement | FLW | C | C | C | C | C | C | C | C | C | +| 1029 | 0x0405 | Relative Humidity Measurement | RH | C | C | C | C | C | C | C | C | C | +| 1030 | 0x0406 | Occupancy Sensing | OCC | C | C | C | C | C | C | C | C | C | +| 1031 | 0x0407 | Leaf Wetness Measurement | RH | C | C | C | | | | | | | +| 1032 | 0x0408 | Soil Moisture Measurement | RH | C | C | C | | | | | | | +| 1036 | 0x040C | Carbon Monoxide Concentration Measurement | CMOCONC | | | C | C | C | C | C | C | C | +| 1037 | 0x040D | Carbon Dioxide Concentration Measurement | CDOCONC | | | C | C | C | C | C | C | C | +| 1043 | 0x0413 | Nitrogen Dioxide Concentration Measurement | NDOCONC | | | C | C | C | C | C | C | C | +| 1045 | 0x0415 | Ozone Concentration Measurement | OZCONC | | | C | C | C | C | C | C | C | +| 1066 | 0x042A | PM2.5 Concentration Measurement | PMICONC | | | C | C | C | C | C | C | C | +| 1067 | 0x042B | Formaldehyde Concentration Measurement | FLDCONC | | | C | C | C | C | C | C | C | +| 1068 | 0x042C | PM1 Concentration Measurement | PMHCONC | | | C | C | C | C | C | C | C | +| 1069 | 0x042D | PM10 Concentration Measurement | PMKCONC | | | C | C | C | C | C | C | C | +| 1070 | 0x042E | Total Volatile Organic Compounds Concentration Measurement | TVOCCONC | | | C | C | C | C | C | C | C | +| 1071 | 0x042F | Radon Concentration Measurement | RNCONC | | | C | C | C | C | C | C | C | +| 1072 | 0x0430 | Soil Measurement | SOIL | | | | | | | | C | C | +| 1105 | 0x0451 | Wi-Fi Network Management | WIFINM | | | | | C | C | C | C | C | +| 1106 | 0x0452 | Thread Border Router Management | TBRM | | | | | C | C | C | C | C | +| 1107 | 0x0453 | Thread Network Directory | THNETDIR | | | | | C | C | C | C | C | +| 1283 | 0x0503 | Wake On LAN | WAKEONLAN | C | C | C | C | C | C | C | C | C | +| 1284 | 0x0504 | Channel | CHANNEL | C | C | C | C | C | C | C | C | C | +| 1285 | 0x0505 | Target Navigator | TGTNAV | C | C | C | C | C | C | C | C | C | +| 1286 | 0x0506 | Media Playback | MEDIAPLAYBACK | C | C | C | C | C | C | C | C | C | +| 1287 | 0x0507 | Media Input | MEDIAINPUT | C | C | C | C | C | C | C | C | C | +| 1288 | 0x0508 | Low Power | LOWPOWER | C | C | C | C | C | C | C | C | C | +| 1289 | 0x0509 | Keypad Input | KEYPADINPUT | C | C | C | C | C | C | C | C | C | +| 1290 | 0x050A | Content Launcher | CONTENTLAUNCHER | C | C | C | C | C | C | C | C | C | +| 1291 | 0x050B | Audio Output | AUDIOOUTPUT | C | C | C | C | C | C | C | C | C | +| 1292 | 0x050C | Application Launcher | APPLAUNCHER | C | C | C | C | C | C | C | C | C | +| 1293 | 0x050D | Application Basic | APBSC | C | C | C | C | C | C | C | C | C | +| 1294 | 0x050E | Account Login | ALOGIN | C | C | C | C | C | C | C | C | C | +| 1295 | 0x050F | Content Control | CONCON | | | | P | P | P | P | P | P | +| 1296 | 0x0510 | Content App Observer | APPOBSERVER | | | | C | C | C | C | C | C | +| 1360 | 0x0550 | Zone Management | ZONEMGMT | | | | | | | | C | C | +| 1361 | 0x0551 | Camera AV Stream Management | AVSM | | | | | | | | C | C | +| 1362 | 0x0552 | Camera AV Settings User Level Management | AVSUM | | | | | | | | C | C | +| 1363 | 0x0553 | WebRTC Transport Provider | WEBRTCP | | | | | | | | C | C | +| 1364 | 0x0554 | WebRTC Transport Requestor | WEBRTCR | | | | | | | | C | C | +| 1365 | 0x0555 | Push AV Stream Transport | PAVST | | | | | | | | C | C | +| 1366 | 0x0556 | Chime | CHIME | | | | | | | | C | C | +| 1792 | 0x0700 | Commodity Tariff | SETRF | | | | | | | | C | C | +| 1872 | 0x0750 | Ecosystem Information | ECOINFO | | | | | C | C | C | C | C | +| 1873 | 0x0751 | Commissioner Control | CCTRL | | | | | C | C | C | C | C | +| 1874 | 0x0752 | Joint Fabric Datastore | JFDS | | | | | P | P | P | P | P | +| 1875 | 0x0753 | Joint Fabric Administrator | JFPKI | | | | | P | P | P | P | P | +| 2049 | 0x0801 | TLS Certificate Management | TLSCERT | | | | | | | | C | C | +| 2050 | 0x0802 | TLS Client Management | TLSCLIENT | | | | | | | | C | C | +| 2822 | 0x0B06 | Meter Identification | MTRID | | | | | | | | C | C | +| 2823 | 0x0B07 | Commodity Metering | COMMTR | | | | | | | | C | C | diff --git a/docs/ids_and_codes/spec_device_types.md b/docs/ids_and_codes/spec_device_types.md index 8e1247d7092..bb20a2a33dd 100644 --- a/docs/ids_and_codes/spec_device_types.md +++ b/docs/ids_and_codes/spec_device_types.md @@ -1,105 +1,103 @@ # List of currently defined spec device types -This file was **AUTOMATICALLY** generated by `python scripts/generate_spec_xml.py`. DO NOT EDIT BY HAND! +This file was **AUTOMATICALLY** generated by +`python scripts/generate_spec_xml.py`. DO NOT EDIT BY HAND! -The following markers are used in this document (matches the ID master list): -| State | Description | -|-------|--------------------------------| -| blank | Not supported in this revision | -| C | Certifiable | -| P | Provisional | +The following markers are used in this document (matches the ID master list): | +State | Description | |-------|--------------------------------| | blank | Not +supported in this revision | | C | Certifiable | | P | Provisional | -| ID (Decimal) | ID (hex) | Name |1.2|1.3|1.4|1.4.1|1.4.2-mve-1|1.5| -|--------------|----------|------------------------------|---|---|---|-----|-----------|---| -|10 |0x000A |Door Lock |C |C |C |C |C |C | -|11 |0x000B |Door Lock Controller |C |C |C |C |C |C | -|14 |0x000E |Aggregator |C |C |C |C |C |C | -|15 |0x000F |Generic Switch |C |C |C |C |C |C | -|17 |0x0011 |Power Source |C |C |C |C |C |C | -|18 |0x0012 |OTA Requestor |C |C |C |C |C |C | -|19 |0x0013 |Bridged Node |C |C |C |C |C |C | -|20 |0x0014 |OTA Provider |C |C |C |C |C |C | -|21 |0x0015 |Contact Sensor |C |C |C |C |C |C | -|22 |0x0016 |Root Node |C |C |C |C |C |C | -|23 |0x0017 |Solar Power | | |C |C |C |C | -|24 |0x0018 |Battery Storage | | |C |C |C |C | -|25 |0x0019 |Secondary Network Interface | | |C |C |C |C | -|34 |0x0022 |Speaker |C |C |C |C |C |C | -|35 |0x0023 |Casting Video Player |C |C |C |C |C |C | -|36 |0x0024 |Content App |C |C |C |C |C |C | -|39 |0x0027 |Mode Select |C |C |C |C |C |C | -|40 |0x0028 |Basic Video Player |C |C |C |C |C |C | -|41 |0x0029 |Casting Video Client |C |C |C |C |C |C | -|42 |0x002A |Video Remote Control |C |C |C |C |C |C | -|43 |0x002B |Fan |C |C |C |C |C |C | -|44 |0x002C |Air Quality Sensor |C |C |C |C |C |C | -|45 |0x002D |Air Purifier |C |C |C |C |C |C | -|64 |0x0040 |Irrigation System | | | | | |C | -|65 |0x0041 |Water Freeze Detector | |C |C |C |C |C | -|66 |0x0042 |Water Valve | |C |C |C |C |C | -|67 |0x0043 |Water Leak Detector | |C |C |C |C |C | -|68 |0x0044 |Rain Sensor | |C |C |C |C |C | -|69 |0x0045 |Soil Sensor | | | | | |C | -|112 |0x0070 |Refrigerator |C |C |C |C |C |C | -|113 |0x0071 |Temperature Controlled Cabinet|C |C |C |C |C |C | -|114 |0x0072 |Room Air Conditioner |C |C |C |C |C |C | -|115 |0x0073 |Laundry Washer |C |C |C |C |C |C | -|116 |0x0074 |Robotic Vacuum Cleaner |C |C |C |C |C |C | -|117 |0x0075 |Dishwasher |C |C |C |C |C |C | -|118 |0x0076 |Smoke CO Alarm |C |C |C |C |C |C | -|119 |0x0077 |Cook Surface | |C |C |C |C |C | -|120 |0x0078 |Cooktop | |C |C |C |C |C | -|121 |0x0079 |Microwave Oven | |C |C |C |C |C | -|122 |0x007A |Extractor Hood | |C |C |C |C |C | -|123 |0x007B |Oven | |C |C |C |C |C | -|124 |0x007C |Laundry Dryer | |C |C |C |C |C | -|144 |0x0090 |Network Infrastructure Manager| | |C |C |C |C | -|145 |0x0091 |Thread Border Router | | |C |C |C |C | -|256 |0x0100 |On/Off Light |C |C |C |C |C |C | -|257 |0x0101 |Dimmable Light |C |C |C |C |C |C | -|259 |0x0103 |On/Off Light Switch |C |C |C |C |C |C | -|260 |0x0104 |Dimmer Switch |C |C |C |C |C |C | -|261 |0x0105 |Color Dimmer Switch |C |C |C |C |C |C | -|262 |0x0106 |Light Sensor |C |C |C |C |C |C | -|263 |0x0107 |Occupancy Sensor |C |C |C |C |C |C | -|266 |0x010A |On/Off Plug-in Unit |C |C |C |C |C |C | -|267 |0x010B |Dimmable Plug-In Unit |C |C |C |C |C |C | -|268 |0x010C |Color Temperature Light |C |C |C |C |C |C | -|269 |0x010D |Extended Color Light |C |C |C |C |C |C | -|271 |0x010F |Mounted On/Off Control | | |C |C |C |C | -|272 |0x0110 |Mounted Dimmable Load Control | | |C |C |C |C | -|304 |0x0130 |Joint Fabric Administrator | | |P |P |P |P | -|320 |0x0140 |Intercom | | | | | |C | -|321 |0x0141 |Audio Doorbell | | | | | |C | -|322 |0x0142 |Camera | | | | | |C | -|323 |0x0143 |Video Doorbell | | | | | |C | -|324 |0x0144 |Floodlight Camera | | | | | |C | -|325 |0x0145 |Snapshot Camera | | | | | |C | -|326 |0x0146 |Chime | | | | | |C | -|327 |0x0147 |Camera Controller | | | | | |C | -|328 |0x0148 |Doorbell | | | | | |C | -|514 |0x0202 |Window Covering |C |C |C |C |C |C | -|515 |0x0203 |Window Covering Controller |C |C |C |C |C |C | -|560 |0x0230 |Closure | | | | | |C | -|561 |0x0231 |Closure Panel | | | | | |C | -|574 |0x023E |Closure Controller | | | | | |C | -|768 |0x0300 |Heating/Cooling Unit |C | | | | | | -|769 |0x0301 |Thermostat |C |C |C |C |C |C | -|770 |0x0302 |Temperature Sensor |C |C |C |C |C |C | -|771 |0x0303 |Pump |C |C |C |C |C |C | -|772 |0x0304 |Pump Controller |C |C |C |C |C |C | -|773 |0x0305 |Pressure Sensor |C |C |C |C |C |C | -|774 |0x0306 |Flow Sensor |C |C |C |C |C |C | -|775 |0x0307 |Humidity Sensor |C |C |C |C |C |C | -|777 |0x0309 |Heat Pump | | |C |C |C |C | -|778 |0x030A |Thermostat Controller | | | | |C |C | -|1292 |0x050C |Energy EVSE | |C |C |C |C |C | -|1293 |0x050D |Device Energy Management | |C |C |C |C |C | -|1295 |0x050F |Water Heater | | |C |C |C |C | -|1296 |0x0510 |Electrical Sensor | |C |C |C |C |C | -|1297 |0x0511 |Electrical Utility Meter | | | | | |C | -|1298 |0x0512 |Meter Reference Point | | | | | |C | -|1299 |0x0513 |Electrical Energy Tariff | | | | | |C | -|1300 |0x0514 |Electrical Meter | | | | | |C | -|2112 |0x0840 |Control Bridge |C |C |C |C |C |C | -|2128 |0x0850 |On/Off Sensor |C |C |C |C |C |C | +| ID (Decimal) | ID (hex) | Name | 1.0 | 1.1 | 1.2 | 1.3 | 1.4 | 1.4.1 | 1.4.2-mve-1 | 1.5 | 0.9-winter-2026 | +| ------------ | -------- | ------------------------------ | --- | --- | --- | --- | --- | ----- | ----------- | --- | --------------- | +| 10 | 0x000A | Door Lock | C | C | C | C | C | C | C | C | C | +| 11 | 0x000B | Door Lock Controller | C | C | C | C | C | C | C | C | C | +| 14 | 0x000E | Aggregator | C | C | C | C | C | C | C | C | C | +| 15 | 0x000F | Generic Switch | C | C | C | C | C | C | C | C | C | +| 17 | 0x0011 | Power Source | C | C | C | C | C | C | C | C | C | +| 18 | 0x0012 | OTA Requestor | C | C | C | C | C | C | C | C | C | +| 19 | 0x0013 | Bridged Node | C | C | C | C | C | C | C | C | C | +| 20 | 0x0014 | OTA Provider | C | C | C | C | C | C | C | C | C | +| 21 | 0x0015 | Contact Sensor | C | C | C | C | C | C | C | C | C | +| 22 | 0x0016 | Root Node | C | C | C | C | C | C | C | C | C | +| 23 | 0x0017 | Solar Power | | | | | C | C | C | C | C | +| 24 | 0x0018 | Battery Storage | | | | | C | C | C | C | C | +| 25 | 0x0019 | Secondary Network Interface | | | | | C | C | C | C | C | +| 34 | 0x0022 | Speaker | C | C | C | C | C | C | C | C | C | +| 35 | 0x0023 | Casting Video Player | C | C | C | C | C | C | C | C | C | +| 36 | 0x0024 | Content App | C | C | C | C | C | C | C | C | C | +| 39 | 0x0027 | Mode Select | C | C | C | C | C | C | C | C | C | +| 40 | 0x0028 | Basic Video Player | C | C | C | C | C | C | C | C | C | +| 41 | 0x0029 | Casting Video Client | C | C | C | C | C | C | C | C | C | +| 42 | 0x002A | Video Remote Control | C | C | C | C | C | C | C | C | C | +| 43 | 0x002B | Fan | C | C | C | C | C | C | C | C | C | +| 44 | 0x002C | Air Quality Sensor | | | C | C | C | C | C | C | C | +| 45 | 0x002D | Air Purifier | | | C | C | C | C | C | C | C | +| 64 | 0x0040 | Irrigation System | | | | | | | | C | C | +| 65 | 0x0041 | Water Freeze Detector | | | | C | C | C | C | C | C | +| 66 | 0x0042 | Water Valve | | | | C | C | C | C | C | C | +| 67 | 0x0043 | Water Leak Detector | | | | C | C | C | C | C | C | +| 68 | 0x0044 | Rain Sensor | | | | C | C | C | C | C | C | +| 69 | 0x0045 | Soil Sensor | | | | | | | | C | C | +| 112 | 0x0070 | Refrigerator | | | C | C | C | C | C | C | C | +| 113 | 0x0071 | Temperature Controlled Cabinet | | | C | C | C | C | C | C | C | +| 114 | 0x0072 | Room Air Conditioner | | | C | C | C | C | C | C | C | +| 115 | 0x0073 | Laundry Washer | | | C | C | C | C | C | C | C | +| 116 | 0x0074 | Robotic Vacuum Cleaner | | | C | C | C | C | C | C | C | +| 117 | 0x0075 | Dishwasher | | | C | C | C | C | C | C | C | +| 118 | 0x0076 | Smoke CO Alarm | | | C | C | C | C | C | C | C | +| 119 | 0x0077 | Cook Surface | | | | C | C | C | C | C | C | +| 120 | 0x0078 | Cooktop | | | | C | C | C | C | C | C | +| 121 | 0x0079 | Microwave Oven | | | | C | C | C | C | C | C | +| 122 | 0x007A | Extractor Hood | | | | C | C | C | C | C | C | +| 123 | 0x007B | Oven | | | | C | C | C | C | C | C | +| 124 | 0x007C | Laundry Dryer | | | | C | C | C | C | C | C | +| 144 | 0x0090 | Network Infrastructure Manager | | | | | C | C | C | C | C | +| 145 | 0x0091 | Thread Border Router | | | | | C | C | C | C | C | +| 256 | 0x0100 | On/Off Light | C | C | C | C | C | C | C | C | C | +| 257 | 0x0101 | Dimmable Light | C | C | C | C | C | C | C | C | C | +| 259 | 0x0103 | On/Off Light Switch | C | C | C | C | C | C | C | C | C | +| 260 | 0x0104 | Dimmer Switch | C | C | C | C | C | C | C | C | C | +| 261 | 0x0105 | Color Dimmer Switch | C | C | C | C | C | C | C | C | C | +| 262 | 0x0106 | Light Sensor | C | C | C | C | C | C | C | C | C | +| 263 | 0x0107 | Occupancy Sensor | C | C | C | C | C | C | C | C | C | +| 266 | 0x010A | On/Off Plug-in Unit | C | C | C | C | C | C | C | C | C | +| 267 | 0x010B | Dimmable Plug-In Unit | C | C | C | C | C | C | C | C | C | +| 268 | 0x010C | Color Temperature Light | C | C | C | C | C | C | C | C | C | +| 269 | 0x010D | Extended Color Light | C | C | C | C | C | C | C | C | C | +| 271 | 0x010F | Mounted On/Off Control | | | | | C | C | C | C | C | +| 272 | 0x0110 | Mounted Dimmable Load Control | | | | | C | C | C | C | C | +| 304 | 0x0130 | Joint Fabric Administrator | | | | | P | P | P | P | P | +| 320 | 0x0140 | Intercom | | | | | | | | C | C | +| 321 | 0x0141 | Audio Doorbell | | | | | | | | C | C | +| 322 | 0x0142 | Camera | | | | | | | | C | C | +| 323 | 0x0143 | Video Doorbell | | | | | | | | C | C | +| 324 | 0x0144 | Floodlight Camera | | | | | | | | C | C | +| 325 | 0x0145 | Snapshot Camera | | | | | | | | C | C | +| 326 | 0x0146 | Chime | | | | | | | | C | C | +| 327 | 0x0147 | Camera Controller | | | | | | | | C | C | +| 328 | 0x0148 | Doorbell | | | | | | | | C | C | +| 514 | 0x0202 | Window Covering | C | C | C | C | C | C | C | C | C | +| 515 | 0x0203 | Window Covering Controller | C | C | C | C | C | C | C | C | C | +| 560 | 0x0230 | Closure | | | | | | | | C | C | +| 561 | 0x0231 | Closure Panel | | | | | | | | C | C | +| 574 | 0x023E | Closure Controller | | | | | | | | C | C | +| 768 | 0x0300 | Heating/Cooling Unit | C | C | C | | | | | | | +| 769 | 0x0301 | Thermostat | C | C | C | C | C | C | C | C | C | +| 770 | 0x0302 | Temperature Sensor | C | C | C | C | C | C | C | C | C | +| 771 | 0x0303 | Pump | C | C | C | C | C | C | C | C | C | +| 772 | 0x0304 | Pump Controller | C | C | C | C | C | C | C | C | C | +| 773 | 0x0305 | Pressure Sensor | C | C | C | C | C | C | C | C | C | +| 774 | 0x0306 | Flow Sensor | C | C | C | C | C | C | C | C | C | +| 775 | 0x0307 | Humidity Sensor | C | C | C | C | C | C | C | C | C | +| 777 | 0x0309 | Heat Pump | | | | | C | C | C | C | C | +| 778 | 0x030A | Thermostat Controller | | | | | | | C | C | C | +| 1292 | 0x050C | Energy EVSE | | | | C | C | C | C | C | C | +| 1293 | 0x050D | Device Energy Management | | | | C | C | C | C | C | C | +| 1295 | 0x050F | Water Heater | | | | | C | C | C | C | C | +| 1296 | 0x0510 | Electrical Sensor | | | | C | C | C | C | C | C | +| 1297 | 0x0511 | Electrical Utility Meter | | | | | | | | C | C | +| 1298 | 0x0512 | Meter Reference Point | | | | | | | | C | C | +| 1299 | 0x0513 | Electrical Energy Tariff | | | | | | | | C | C | +| 1300 | 0x0514 | Electrical Meter | | | | | | | | C | C | +| 2112 | 0x0840 | Control Bridge | C | C | C | C | C | C | C | C | C | +| 2128 | 0x0850 | On/Off Sensor | C | C | C | C | C | C | C | C | C | diff --git a/docs/platforms/nxp/nxp_RTs_ota_software_update.md b/docs/platforms/nxp/nxp_RTs_ota_software_update.md index 81904232aa1..b28164c2566 100644 --- a/docs/platforms/nxp/nxp_RTs_ota_software_update.md +++ b/docs/platforms/nxp/nxp_RTs_ota_software_update.md @@ -98,7 +98,7 @@ user@ubuntu: export ARMGCC_DIR= # with ARMGCC_DIR referencing the compiler path `west build` command : ``` -user@ubuntu: west build -d mcuboot_build -b examples/ota_examples/mcuboot_opensource +user@ubuntu: west build -d mcuboot_build -b examples/ota_examples/mcuboot_opensource -DCONF_FILE=/connectedhomeip/third_party/nxp/nxp_matter_support/cmake/rt//bootloader.conf ``` > Note : For RT1170 platform, `-Dcore_id=cm7` argument should be added to the @@ -205,6 +205,13 @@ partitioning with mcuboot, please refer to the dedicated `readme.txt` located in > Auto-generated signed application image can be found under the path > `/app_SIGNED.bin`. +##### Signature Algorithm Compatibility + +Starting from MCUBoot v2.2, the default signature algorithm is EC256. Matter +images are now signed using ECDSA by default. To maintain compatibility with +older MCUBoot versions (prior to 2.2), which use RSA by default, we also provide +an RSA-signed image named `/app_SIGNED_RSA.bin`. + After flashing the bootloader, the application can be programmed to the board. The image must have the following format : @@ -235,13 +242,47 @@ To sign the image and wrap the raw binary of the application with the header and trailer, "`imgtool`" is provided in the SDK and can be found in "`/third_party/nxp/nxp_matter_support/github_sdk/sdk_next/repo/mcuxsdk/middleware/mcuboot_opensource/scripts/`". -The following commands can be run (make sure to replace the /path/to/file/binary -with the adequate files): +First, change to the scripts directory: -```sh -user@ubuntu: cd ~/Desktop//third_party/nxp/nxp_matter_support/github_sdk/sdk_next/repo/mcuxsdk/middleware/mcuboot_opensource/scripts/ +```bash +cd ~/Desktop//third_party/nxp/nxp_matter_support/github_sdk/sdk_next/repo/mcuxsdk/middleware/mcuboot_opensource/scripts/ +``` + +Then, run one of the following signing commands (make sure to replace the +/path/to/file/binary with the adequate files): -user@ubuntu: python3 imgtool.py sign --key ~/Desktop//third_party/nxp/nxp_matter_support/github_sdk/sdk_next/repo/mcuxsdk/middleware/mcuboot_opensource/boot/nxp_mcux_sdk/keys/sign-rsa2048-priv.pem --align 4 --header-size 0x1000 --pad-header --pad --confirm --slot-size 0x440000 --max-sectors 1088 --version "1.0" ~/Desktop/connectedhomeip/examples/all-clusters-app/nxp/rt/<"rt_board">/out/debug/chip-<"rt_board">-all-cluster-example.bin ~/Desktop/connectedhomeip/examples/all-clusters-app/nxp/rt/<"rt_board">/out/debug/chip-<"rt_board">-all-cluster-example_SIGNED.bin +- Signing with ECDSA (for MCUBoot version >= 2.2) + +```bash +python3 imgtool.py sign \ + --key ~/Desktop//third_party/nxp/nxp_matter_support/github_sdk/sdk_next/repo/mcuxsdk/middleware/mcuboot_opensource/boot/nxp_mcux_sdk/keys/sign-ecdsa-p256-priv.pem \ + --align 4 \ + --header-size 0x1000 \ + --pad-header \ + --pad \ + --confirm \ + --slot-size 0x440000 \ + --max-sectors 1088 \ + --version "1.0" \ + ~/Desktop/connectedhomeip/examples/all-clusters-app/nxp/rt/<"rt_board">/out/debug/chip-<"rt_board">-all-cluster-example.bin \ + ~/Desktop/connectedhomeip/examples/all-clusters-app/nxp/rt/<"rt_board">/out/debug/chip-<"rt_board">-all-cluster-example_SIGNED.bin +``` + +- Signing with RSA (for MCUBoot version < 2.2) + +```bash +python3 imgtool.py sign \ + --key ~/Desktop//third_party/nxp/nxp_matter_support/github_sdk/sdk_next/repo/mcuxsdk/middleware/mcuboot_opensource/boot/nxp_mcux_sdk/keys/sign-rsa2048-priv.pem \ + --align 4 \ + --header-size 0x1000 \ + --pad-header \ + --pad \ + --confirm \ + --slot-size 0x440000 \ + --max-sectors 1088 \ + --version "1.0" \ + ~/Desktop/connectedhomeip/examples/all-clusters-app/nxp/rt/<"rt_board">/out/debug/chip-<"rt_board">-all-cluster-example.bin \ + ~/Desktop/connectedhomeip/examples/all-clusters-app/nxp/rt/<"rt_board">/out/debug/chip-<"rt_board">-all-cluster-example_SIGNED.bin ``` Notes : @@ -253,16 +294,16 @@ Notes : adjusted accordingly. - In this example, the image is signed with the private key provided by the SDK as an example - (`/third_party/nxp/nxp_matter_support/github_sdk/sdk_next/repo/mcuxsdk/middleware/mcuboot_opensource/boot/nxp_mcux_sdk/keys/sign-rsa2048-priv.pem`), + (`/third_party/nxp/nxp_matter_support/github_sdk/sdk_next/repo/mcuxsdk/middleware/mcuboot_opensource/boot/nxp_mcux_sdk/keys/sign-ecdsa-p256-priv.pem`), MCUBoot is built with its corresponding public key which would be used to verify the integrity of the image. It is possible to generate a new pair of keys using the following commands. This procedure should be done prior to building the mcuboot application. -- To generate the private key : +- To generate the private key with ECDSA : ``` -user@ubuntu: python3 imgtool.py keygen -k priv_key.pem -t rsa-2048 +user@ubuntu: python3 imgtool.py keygen -k priv_key.pem -t ecdsa-p256 ``` - To extract the public key : @@ -272,11 +313,16 @@ user@ubuntu: python3 imgtool.py getpub -k priv_key.pem ``` - The extracted public key can then be copied to the - `/third_party/nxp/nxp_matter_support/github_sdk/sdk_next/repo/mcuxsdk/middleware/mcuboot_opensource/boot/nxp_mcux_sdk/keys/sign-rsa2048-pub.c`, - given as a value to the rsa_pub_key[] array. + `/third_party/nxp/nxp_matter_support/github_sdk/sdk_next/repo/mcuxsdk/middleware/mcuboot_opensource/boot/nxp_mcux_sdk/keys/sign-ecdsa-p256-pub.c`, + given as a value to the ecdsa_pub_key[] array. The resulting output is the signed binary of the application version "1.0". +> Note : To generate RSA keys, make sure to replace the type `ecdsa-p256` with +> `rsa-2048`, and replace `rsa_pub_key[]` in the +> `/third_party/nxp/nxp_matter_support/github_sdk/sdk_next/repo/mcuxsdk/middleware/mcuboot_opensource/boot/nxp_mcux_sdk/keys/sign-rsa2048-pub.c` +> file. + #### Flashing the signed application image JLink can be used to flash the application using the command : diff --git a/docs/platforms/nxp/nxp_examples_freertos_platforms.md b/docs/platforms/nxp/nxp_examples_freertos_platforms.md index a4bd06fc8ed..8ccec3bea61 100644 --- a/docs/platforms/nxp/nxp_examples_freertos_platforms.md +++ b/docs/platforms/nxp/nxp_examples_freertos_platforms.md @@ -6,6 +6,8 @@ - [Testing the example](#testing-the-example) - [Matter Shell](#testing-the-example-application-with-matter-cli-enabled) + + ## Introduction This guide provides step-by-step instructions for working with CHIP applications @@ -18,6 +20,8 @@ The NXP examples are based on and provide a prototype application that demonstrates device commissioning and different cluster control. + + ### Supported platforms Matter example applications are supported on the following NXP platforms : @@ -27,6 +31,10 @@ Matter example applications are supported on the following NXP platforms : | RW61x | [Matter NXP Guide for RW61x platform](./nxp_rw61x_guide.md) | | RT1170 | [Matter NXP Guide for RT1170 platform](./nxp_rt1170_guide.md) | | RT1060 | [Matter NXP Guide for RT1060 platform](./nxp_rt1060_guide.md) | +| MCXW71 | [Matter NXP Guide for MCXW71 platform](./nxp_mcxw71_guide.md) | +| MCXW72 | [Matter NXP Guide for MCXW72 platform](./nxp_mcxw72_guide.md) | + + ## Building @@ -60,7 +68,7 @@ user@ubuntu:~/Desktop/git/connectedhomeip$ scripts/checkout_submodules.py --shal - Step 2 : Activate Matter environment : -If you are setting the Matter environment for the first time, or your local +If you are setting up the Matter environment for the first time, or your local environment is out of date, run the following script : ``` @@ -97,8 +105,8 @@ export the path as follows : user@ubuntu:~/Desktop/git/connectedhomeip$ export ARMGCC_DIR=/path/to/connectedhomeip/.environment/cipd/packages/arm ``` -> Note : Steps 1 to 3 can be skipped if your environment is up to date. Steps 4 -> and 5 should be repeated in each new terminal session to ensure the +> Note : Steps 1 and 3 can be skipped if your environment is up to date. Steps +> 2, 4 and 5 should be repeated in each new terminal session to ensure the > environment is correctly configured. ### Build the application @@ -114,6 +122,8 @@ CHIP NXP examples support building with two different build systems : > Please refer to the platform [dedicated readme](#supported-platforms) to check > which build system(s) is supported by the platform. + + #### CMake build system The example application can be built with `west build` command, which can be @@ -153,29 +163,39 @@ Additional arguments that can be passed in the `west build` command line : > configuration supported, please refer to the > [dedicated readme](#supported-platforms) for the platform you are targeting. + + ##### Available project configuration files and platform compatibility -| Configuration File | Description | Supported platforms | -| ------------------------------------------ | ------------------------------------------------------ | --------------------- | -| `prj_wifi.conf` | Wi-Fi | RW61x, RT1060, RT1170 | -| `prj_wifi_fdata.conf` | Wi-Fi, factory data | RW61x, RT1060, RT1170 | -| `prj_wifi_ota_fdata.conf` | Wi-Fi, factory data, OTA | RW61x, RT1060, RT1170 | -| `prj_wifi_ota_fdata_v2.conf` | Wi-Fi, factory data, OTA, with SW v2 | RW61x, RT1060, RT1170 | -| `prj_wifi_ota.conf` | Wi-Fi, OTA | RW61x, RT1060, RT1170 | -| `prj_wifi_ota_v2.conf` | Wi-Fi, OTA, SW v2 | RW61x, RT1060, RT1170 | -| `prj_wifi_onnetwork.conf` | Wi-Fi onnetwork without BLE | RW61x, RT1060, RT1170 | -| `prj_thread_ftd.conf` | Thread FTD | RW61x, RT1060, RT1170 | -| `prj_thread_ftd_ota.conf` | Thread FTD, OTA | RW61x, RT1060, RT1170 | -| `prj_thread_ftd_ota_fdata.conf` | Thread FTD, OTA, factory data | RW61x, RT1060, RT1170 | -| `prj_thread_ftd_wifi_br_ota.conf` | Wi-Fi + Thread Border Router, OTA | RW61x, RT1060, RT1170 | -| `prj_thread_ftd_wifi_br_ota_fdata.conf` | Wi-Fi + Thread Border Router, OTA, factory data | RW61x, RT1060, RT1170 | -| `prj_thread_ftd_wifi_br_ota_fdata_v2.conf` | Wi-Fi + Thread Border Router, OTA SW v2 , factory data | RW61x, RT1060, RT1170 | -| `prj_thread_ftd_wifi_br_ota_v2.conf` | Wi-Fi + Thread Border Router, OTA with SW v2 | RW61x, RT1060, RT1170 | -| `prj_eth.conf` | Ethernet | RW61x `frdm` | -| `prj_eth_fdata.conf` | Ethernet, factory data | RW61x `frdm` | -| `prj_eth_ota.conf` | Ethernet, OTA | RW61x `frdm` | -| `prj_eth_ota_fdata.conf` | Ethernet, factory data, OTA | RW61x `frdm` | -| `prj_eth_ota_fdata_v2.conf` | Ethernet, factory data, OTA, SW v2 | RW61x `frdm` | +| Configuration File | Description | Supported platforms | +| ------------------------------------------ | ------------------------------------------------------ | ------------------------------------- | +| `prj_wifi.conf` | Wi-Fi | RW61x, RT1060, RT1170 | +| `prj_wifi_fdata.conf` | Wi-Fi, factory data | RW61x, RT1060, RT1170 | +| `prj_wifi_ota_fdata.conf` | Wi-Fi, factory data, OTA | RW61x, RT1060, RT1170 | +| `prj_wifi_ota_fdata_v2.conf` | Wi-Fi, factory data, OTA, with SW v2 | RW61x, RT1060, RT1170 | +| `prj_wifi_ota.conf` | Wi-Fi, OTA | RW61x, RT1060, RT1170 | +| `prj_wifi_ota_v2.conf` | Wi-Fi, OTA, SW v2 | RW61x, RT1060, RT1170 | +| `prj_wifi_onnetwork.conf` | Wi-Fi onnetwork without BLE | RW61x, RT1060, RT1170 | +| `prj_thread_ftd.conf` | Thread FTD | RW61x, RT1060, RT1170, MCXW71, MCXW72 | +| `prj_thread_ftd_fdata.conf` | Thread FTD, factory data | RW61x, RT1060, RT1170, MCXW71, MCXW72 | +| `prj_thread_ftd_ota.conf` | Thread FTD, OTA | RW61x, RT1060, RT1170, MCXW71, MCXW72 | +| `prj_thread_ftd_ota_fdata.conf` | Thread FTD, OTA, factory data | RW61x, RT1060, RT1170, MCXW71, MCXW72 | +| `prj_thread_ftd_wifi_br_ota.conf` | Wi-Fi + Thread Border Router, OTA | RW61x, RT1060, RT1170 | +| `prj_thread_ftd_wifi_br_ota_fdata.conf` | Wi-Fi + Thread Border Router, OTA, factory data | RW61x, RT1060, RT1170 | +| `prj_thread_ftd_wifi_br_ota_fdata_v2.conf` | Wi-Fi + Thread Border Router, OTA SW v2 , factory data | RW61x, RT1060, RT1170 | +| `prj_thread_ftd_wifi_br_ota_v2.conf` | Wi-Fi + Thread Border Router, OTA with SW v2 | RW61x, RT1060, RT1170 | +| `prj_thread_mtd.conf` | Thread MTD | MCXW71, MCXW72 | +| `prj_thread_mtd_fdata.conf` | Thread MTD, factory data | MCXW71, MCXW72 | +| `prj_thread_mtd_low_power.conf` | Thread MTD operating in low power mode | MCXW71, MCXW72 | +| `prj_thread_mtd_low_power_lit.conf` | Thread MTD, low power ICD LIT | MCXW71, MCXW72 | +| `prj_thread_mtd_fdata_low_power.conf` | Thread MTD, factory data, low power | MCXW71, MCXW72 | +| `prj_thread_mtd_ota_low_power.conf` | Thread MTD, OTA, low power | MCXW71, MCXW72 | +| `prj_thread_mtd_ota_fdata.conf` | Thread MTD, OTA, factory data | MCXW71, MCXW72 | +| `prj_eth.conf` | Ethernet | RW61x `frdm` | +| `prj_eth_fdata.conf` | Ethernet, factory data | RW61x `frdm` | +| `prj_eth_ota.conf` | Ethernet, OTA | RW61x `frdm` | +| `prj_eth_ota_fdata.conf` | Ethernet, factory data, OTA | RW61x `frdm` | +| `prj_eth_ota_fdata_v2.conf` | Ethernet, factory data, OTA, SW v2 | RW61x `frdm` | The build output can be found under the `build_dir` specified in the `west build` command, the binary can be found under the following name : @@ -244,12 +264,16 @@ _gn gen_ command when building an application. > For more information about platform-specific GN options, please refer to the > platform [dedicated readme](#supported-platforms). + + ## Flashing and debugging For flashing and debugging the example application, follow detailed instructions -form the [dedicated readme](#supported-platforms) to the platform you are +from the [dedicated readme](#supported-platforms) to the platform you are targeting. + + ## Testing the example CHIP Tool is a Matter controller which can be used to commission a Matter device @@ -314,7 +338,7 @@ The Matter CLI can be enabled with the NXP CHIP application. For more information about the Matter CLI default commands, you can refer to the dedicated [ReadMe](../../../examples/shell/README.md). -The NXP application supports additional commands : +The NXP applications support additional commands : ``` > help diff --git a/docs/platforms/nxp/nxp_manufacturing_flow.md b/docs/platforms/nxp/nxp_manufacturing_flow.md index 03ea47712d2..8ed295fe412 100644 --- a/docs/platforms/nxp/nxp_manufacturing_flow.md +++ b/docs/platforms/nxp/nxp_manufacturing_flow.md @@ -140,12 +140,13 @@ Here is the interpretation of the **optional** parameters: ## 3. Write provisioning data -| platform | tool | command | details | -| -------- | --------------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------- | -| `mcxw71` | `JLink` | `loadfile factory_data.bin 0xFE080` | NA | -| `rw61x` | `JLink` | `loadfile factory_data.bin 0xBFFF000` | Here, `0xBFFF000` is the value of symbol `__FACTORY_DATA_START` from the corresponding `.map` file | -| `rt1060` | `MCUXpresso Flash Tool GUI` | NA | The address is given by the `__FACTORY_DATA_START` symbol in the `.map` file | -| `rt1170` | `MCUXpresso Flash Tool GUI` | NA | The address is given by the `__FACTORY_DATA_START` symbol in the `.map` file | +| platform | tool | command | details | +| -------- | --------------------------- | ----------------------------------------- | -------------------------------------------------------------------------------------------------- | +| `mcxw71` | `JLink` | `loadfile factory_data.bin 0xFE080` | NA | +| `mcxw72` | `blhost` | `write-memory 0x2002680 factory_data.bin` | Factory data is written in `IFR0`, sector 1 at a predefined offset. The address is expanded here. | +| `rw61x` | `JLink` | `loadfile factory_data.bin 0xBFFF000` | Here, `0xBFFF000` is the value of symbol `__FACTORY_DATA_START` from the corresponding `.map` file | +| `rt1060` | `MCUXpresso Flash Tool GUI` | NA | The address is given by the `__FACTORY_DATA_START` symbol in the `.map` file | +| `rt1170` | `MCUXpresso Flash Tool GUI` | NA | The address is given by the `__FACTORY_DATA_START` symbol in the `.map` file | ## 4. Build app and usage diff --git a/docs/platforms/nxp/nxp_mcxw71_guide.md b/docs/platforms/nxp/nxp_mcxw71_guide.md new file mode 100644 index 00000000000..094af7cf00c --- /dev/null +++ b/docs/platforms/nxp/nxp_mcxw71_guide.md @@ -0,0 +1,201 @@ +# Matter NXP MCXW71 Applications Guide + +- [Introduction](#introduction) +- [Building](#building) +- [Manufacturing Data](#manufacturing-data) +- [Flashing and debugging](#flashing-and-debugging) +- [Testing the example](#testing-the-example) +- [OTA Software Update](#ota-software-update) + +
+ + + +## Introduction + +The Matter MCXW71 example applications provide a working demonstration of the +FRDM-MCXW71 board integration, built using the Project CHIP codebase and the NXP +MCUX SDK. + +### Supported configurations + +The examples support: + +- Matter over Openthread + +### Supported build systems + +MCXW71 platform supports only one build system to generate the application : + +- `CMake` + + + +## Building + +Make sure to follow shared build instructions from +[CHIP NXP Examples Guide for FreeRTOS platforms](./nxp_examples_freertos_platforms.md) +to set-up your environment. + +> In the following steps, the "lighting-app" is used as an example. + +The examples support configuration and build using the CMake build system. You +can find more information in +[CMake Build System](./nxp_examples_freertos_platforms.md#cmake-build-system) +section which explains how to further configure your application build. + +In the `west build` command, the `board` option should be replaced with +`frdmmcxw71`. The build option +`-DCONFIG_MCUX_COMPONENT_middleware.freertos-kernel.config=n` must be used in +the build command line for the MCXW71 platform. + +Example of build command to build the Lighting app with Matter-over-Thread (FTD +device type) configuration on MCXW71 platform : + +``` +user@ubuntu:~/Desktop/git/connectedhomeip$ west build -d bin/lighting-app/ftd -b frdmmcxw71 examples/lighting-app/nxp -DCONF_FILE_NAME=prj_thread_ftd.conf -DCONFIG_MCUX_COMPONENT_middleware.freertos-kernel.config=n +``` + +Note that the MCXW71 example supports various configurations that can be +provided to the `CONF_FILE_NAME` variable, you can refer to the +[table of available project configuration files and platform compatibility](./nxp_examples_freertos_platforms.md#build-config-files) +to check all the supported configurations. + + + +## Manufacturing data + +See +[Guide for writing manufacturing data on NXP devices](./nxp_manufacturing_flow.md). + + + +## Flashing and debugging + +### Flashing the NBU + +Normally the `NBU` image should be written/updated only when migrating to a new +NXP SDK or to a new Matter release altogether. The procedure below can be used +to upload/refresh the board's NBU firmware. + +1. Install the Bootloader Host Application (`blhost`) from the + [MCU Bootloader for NXP Microcontrollers downloads page](https://www.nxp.com/design/design-center/software/development-software/mcuxpresso-software-and-tools-/mcu-bootloader-for-nxp-microcontrollers:MCUBOOT). + +2. The NBU image is available in your Matter source code tree in + +`third_party/nxp/nxp_matter_support/github_sdk/sdk_next/repo/mcuxsdk/middleware/wireless/ieee-802.15.4/bin/k32w1_mcxw71/k32w1_mcxw71_nbu_ble_15_4_dyn_matter.sb3` + +3. Initialize the board in `ISP` (In-System Programming) mode, which allows the + SoC to accept commands to erase/write/update internal flash memories via the + serial port. In order to do that disconnect the board from your PC and hold + down the SW3 button while reconnecting it back. When you release the SW3 + button the board should be operating in ISP mode. + +4. Erase the host and NBU flash memories using the `blhost` tool + + ``` + blhost -p flash-erase-all + ``` + +5. Use the same `blhost` tool to write the NBU image on the board: + + ``` + blhost -p -- receive-sb-file k32w1_mcxw71_nbu_ble_15_4_dyn_matter.sb3 + ``` + +6. Return the board to normal operating mode by disconnecting and then + reconnecting it back to your PC. + +### Flashing the example application + +We recommend using `JLink Commander` from Segger to flash the example +application. It can be downloaded and installed from +https://www.segger.com/downloads/jlink. Once installed, JLink Commander can be +run to flash the application using the following steps : + +``` +$ JLink +``` + +``` +J-Link > connect +Device> ? # you will be presented with a dialog -> select `MCXW716` +Please specify target interface: +J) JTAG (Default) +S) SWD +T) cJTAG +TIF> S +Specify target interface speed [kHz]. : 4000 kHz +Speed> # +``` + +Program the application executable : + +``` +J-Link > loadfile (.elf format) +``` + + + +## Testing the example + +To test the example, please make sure to check the `Testing the example` section +from the common readme +[CHIP NXP Examples Guide for FreeRTOS platforms](./nxp_examples_freertos_platforms.md#testing-the-example). + +### UART Ports + +Testing the example with the CLI enabled will require connecting to both UART0 +and UART1 serial ports. For applications where CLI is _not_ available, +connecting to the default UART1 is enough. + +| Interface | Role | +| --------------- | --------------------------------------------------------------------- | +| UART0 | Used for logs only when `matter-cli` is enabled | +| UART1 (default) | Used either as `matter-cli` or for logs when `matter-cli` is disabled | + +You need a `USB-UART` bridge to make use of the UART0 interface. The pin +configuration is the following: + +- `J5` `pin 3` - UART0 RX +- `J5` `pin 4` - UART0 TX +- `J5` `pin 8` - GND + +### Device UI + +The device state feedback is provided through the on-board LEDs: + +| Widget | Effect | Description | +| ------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------- | +| LED2 | short flash on (50ms on/950ms off) | The device is in an unprovisioned (unpaired) state and is waiting for a commissioner to connect. | +| LED2 | rapid even flashing (100ms period) | The device is in an unprovisioned state and a commissioner is connected via BLE. | +| LED2 | short flash off (950ms on/50ms off) | The device is fully provisioned, but does not yet have full network (Thread) or service connectivity. | +| LED2 | solid on | The device is fully provisioned and has full network and service connectivity. | +| RGB LED | on | The `StateValue` attribute of the `BooleanState` cluster is `true` (simulating detection). | +| RGB LED | off | The `StateValue` attribute of the `BooleanState` cluster is `false` (simulating no detection). | + +NOTE: `LED2` will be disabled when OTA is used. On `FRDM-MCXW71` board, `PTB0` +is wired to both `LED2` and `CS` (Chip Select) of the External Flash Memory. +Since the OTA image is stored in external memory, `LED2` operations will affect +OTA operation by corrupting packages and OTA will not work. + +The user can control the device using the on-board buttons. The actions are +summarized below: + +| Button | Action | State | Output | +| ------ | ------------ | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| SW2 | short press | not commissioned | Enable/disable BLE advertising | +| SW2 | short press | commissioned + device is LIT | Enable Active Mode | +| SW2 | long press | any | Initiate a factory reset (can be cancelled by pressing the button again within the factory reset timeout limit - 6 seconds by default) | +| SW2 | double press | commissioned + device is LIT + supports DSLS | Enable / Disable SIT Mode | +| SW4 | short press | any | Toggle attribute `StateValue` value | +| SW4 | long press | any | Clean soft reset of the device (takes into account proper Matter shutdown procedure) | + + + +## OTA Software Update + +Over-The-Air software updates are supported with the MCXW71 examples. The +process to follow in order to perform a software update is described in the +dedicated guide +['Matter Over-The-Air Software Update with NXP MCXW example applications'](./nxp_mcxw_ota_guide.md). diff --git a/docs/platforms/nxp/nxp_mcxw72_guide.md b/docs/platforms/nxp/nxp_mcxw72_guide.md new file mode 100644 index 00000000000..ebac798e98f --- /dev/null +++ b/docs/platforms/nxp/nxp_mcxw72_guide.md @@ -0,0 +1,218 @@ +# Matter NXP MCXW72 Applications Guide + +- [Introduction](#introduction) +- [Building](#building) +- [Manufacturing Data](#manufacturing-data) +- [Flashing and debugging](#flashing-and-debugging) +- [Testing the example](#testing-the-example) +- [OTA Software Update](#ota-software-update) + +
+ + + +## Introduction + +The Matter MCXW72 example applications provide a working demonstration of the +MCXW72 board integration, built using the Project CHIP codebase and the NXP MCUX +SDK. + +### Supported configurations + +The examples support: + +- Matter over Openthread + +### Supported build systems + +MCXW72 platform supports two different build systems to generate the application +: + +- `GN` (_contact-sensor_ application only) +- `CMake` + + + +## Building + +Make sure to follow shared build instructions from +[CHIP NXP Examples Guide for FreeRTOS platforms](./nxp_examples_freertos_platforms.md#set-up-the-build-environment) +to set-up your environment. + +> In the following steps, the "lighting-app" is used as an example. + +### CMake Build System + +The examples support configuration and build using the CMake build system. You +can find more information in +[CMake Build System](./nxp_examples_freertos_platforms.md#cmake-build-system) +section which explains how to further configure your application build. + +In the `west build` command, the `board` option should be replaced with +`frdmmcxw72`. The build option +`-DCONFIG_MCUX_COMPONENT_middleware.freertos-kernel.config=n` must be used in +the build command line for the MCXW72 platform. Also, the `core_id` should be +set to `cm33_core0`. + +Example of build command to build the Lighting app with Matter-over-Thread (FTD +device type) configuration on MCXW72 platform : + +``` +user@ubuntu:~/Desktop/git/connectedhomeip$ west build -d bin/lighting-app/ftd -b frdmmcxw72 examples/lighting-app/nxp -Dcore_id=cm33_core0 -DCONF_FILE_NAME=prj_thread_ftd.conf -DCONFIG_MCUX_COMPONENT_middleware.freertos-kernel.config=n +``` + +Note that the MCXW72 examples support various configurations that can be +provided to the `CONF_FILE_NAME` variable, you can refer to the +[table of available project configuration files and platform compatibility](./nxp_examples_freertos_platforms.md#build-config-files) +to check all the supported configurations. + +### GN Build System + +#### Building with Matter over Thread configuration on MCXW72 + +- Build Matter-over-Thread configuration with BLE commissioning. + +``` +user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/mcxw72$ gn gen out/debug +user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/mcxw72$ ninja -C out/debug +``` + +#### General information + +The resulting application can be found in out/debug/chip-mcxw72-contact-example. + +Additional GN options can be added when building the application. You can check +[Common GN options to FreeRTOS platforms](./nxp_examples_freertos_platforms.md#general-information) +for the full list. + + + +## Manufacturing data + +See +[Guide for writing manufacturing data on NXP devices](./nxp_manufacturing_flow.md) + + + +## Flashing and debugging + +### Flashing the NBU firmware + +Normally the `NBU` image should be written/updated only when migrating to a new +NXP SDK or to a new Matter release altogether. The procedure below can be used +to upload/refresh the board's NBU firmware. + +1. Install the Bootloader Host Application (`blhost`) from the + [MCU Bootloader for NXP Microcontrollers downloads page](https://www.nxp.com/design/design-center/software/development-software/mcuxpresso-software-and-tools-/mcu-bootloader-for-nxp-microcontrollers:MCUBOOT). + +2. The NBU image is available in your Matter source code tree in + +`third_party/nxp/nxp_matter_support/github_sdk/sdk_next/repo/mcuxsdk/middleware/wireless/ieee-802.15.4/bin/mcxw72/mcxw72_nbu_ble_full_15_4_dyn.bin` + +3. Initialize the board in `ISP` (In-System Programming) mode, which allows the + SoC to accept commands to erase/write/update internal flash memories via the + serial port. In order to do that disconnect the board from your PC and hold + down the SW3 button while reconnecting it back. When you release the SW3 + button the board should be operating in ISP mode. + +4. Erase the host and NBU flash memories using the `blhost` tool + + ``` + blhost -p flash-erase-all 0 + blhost -p flash-erase-all 1 + ``` + +5. Use the same `blhost` tool to write the NBU image on the board: + + ``` + blhost -p write-memory 0x48800000 mcxw72_nbu_ble_full_15_4_dyn.bin + ``` + +6. Return the board to normal operating mode by disconnecting and then + reconnecting it back to your PC. + +### Flashing the example application + +We recommend using `JLink` from Segger to flash the example application. It can +be downloaded and installed from https://www.segger.com/downloads/jlink. Once +installed, JLink can be run to flash the application using the following steps : + +``` +$ JLink +``` + +``` +J-Link > connect +Device> ? # you will be presented with a dialog -> select `MCXW727C_M33_0` +Please specify target interface: +J) JTAG (Default) +S) SWD +T) cJTAG +TIF> S +Specify target interface speed [kHz]. : 4000 kHz +Speed> # +``` + +Program the application executable : + +``` +J-Link > loadfile (.elf or .srec format) +``` + + + +## Testing the example + +To test the example, please make sure to check the `Testing the example` section +from the common readme +[CHIP NXP Examples Guide for FreeRTOS platforms](./nxp_examples_freertos_platforms.md#testing-the-example). + +### UART Ports + +Testing the example with the CLI enabled will require connecting to both UART0 +and UART1 serial ports. For applications where CLI is _not_ available, +connecting to the default UART1 is enough. + +| Interface | Role | +| --------------- | --------------------------------------------------------------------- | +| UART0 | Used for logs only when `matter-cli` is enabled | +| UART1 (default) | Used either as `matter-cli` or for logs when `matter-cli` is disabled | + +You need a `USB-UART` bridge to make use of the UART0 interface. The pin +configuration is the following: + +- `J5` `pin 3` - UART0 RX +- `J5` `pin 4` - UART0 TX +- `J5` `pin 8` - GND + +### Device UI + +The device state feedback is provided through the on-board LEDs: + +| Widget | Effect | Description | +| ------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------- | +| LED2 | short flash on (50ms on/950ms off) | The device is in an unprovisioned (unpaired) state and is waiting for a commissioner to connect. | +| LED2 | rapid even flashing (100ms period) | The device is in an unprovisioned state and a commissioner is connected via BLE. | +| LED2 | short flash off (950ms on/50ms off) | The device is fully provisioned, but does not yet have full network (Thread) or service connectivity. | +| LED2 | solid on | The device is fully provisioned and has full network and service connectivity. | +| RGB LED | on | The `StateValue` attribute of the `BooleanState` cluster is `true` (simulating detection). | +| RGB LED | off | The `StateValue` attribute of the `BooleanState` cluster is `false` (simulating no detection). | + +The user can control the device using the on-board buttons. The actions are +summarized below: + +| Button | Action | State | Output | +| ------ | ----------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| SW2 | short press | not commissioned | Enable/disable BLE advertising | +| SW2 | long press | any | Initiate a factory reset (can be cancelled by pressing the button again within the factory reset timeout limit - 6 seconds by default) | +| SW4 | short press | any | Toggle attribute `StateValue` value | +| SW4 | long press | any | Clean soft reset of the device (takes into account proper Matter shutdown procedure) | + + + +## OTA Software Update + +Over-The-Air software updates are supported with the MCXW72 examples. The +process to follow in order to perform a software update is described in the +dedicated guide +['Matter Over-The-Air Software Update with NXP MCXW example applications'](./nxp_mcxw_ota_guide.md). diff --git a/docs/platforms/nxp/nxp_mcxw71_ota_guide.md b/docs/platforms/nxp/nxp_mcxw_ota_guide.md similarity index 99% rename from docs/platforms/nxp/nxp_mcxw71_ota_guide.md rename to docs/platforms/nxp/nxp_mcxw_ota_guide.md index 8a32e928edd..f76cd64143a 100644 --- a/docs/platforms/nxp/nxp_mcxw71_ota_guide.md +++ b/docs/platforms/nxp/nxp_mcxw_ota_guide.md @@ -1,4 +1,4 @@ -# NXP `MCXW71` OTA guide +# NXP MCXW OTA guide ### Convert `srec` into `sb3` file diff --git a/docs/platforms/nxp/nxp_rt1060_guide.md b/docs/platforms/nxp/nxp_rt1060_guide.md index be2f7376bb3..5453cd5f729 100644 --- a/docs/platforms/nxp/nxp_rt1060_guide.md +++ b/docs/platforms/nxp/nxp_rt1060_guide.md @@ -13,14 +13,6 @@ - [Hardware requirements RT1060 + 88W8801 + K32W0x1DK6](#hardware-requirements-rt1060--88w8801--k32w0x1dk6) - [Building](#building) - [CMake Build System](#cmake-build-system) - - [GN Build System](#gn-build-system) - - [Building with Matter over Wifi configuration on RT1060 + transceiver](#building-with-matter-over-wifi-configuration-on-rt1060--transceiver) - - [Build with Matter over Thread configuration on RT1060 + transceiver](#build-with-matter-over-thread-configuration-on-rt1060--transceiver) - - [Build with Matter over Thread configuration on RT1060 + K32W0](#build-with-matter-over-thread-configuration-on-rt1060--k32w0) - - [Build with Matter over Thread configuration on RT1060-EVK-C + IW612](#build-with-matter-over-thread-configuration-on-rt1060-evk-c--iw612) - - [Build with Matter over Wi-Fi + OpenThread Border Router configuration on RT1060-EVK-C + IW612](#build-with-matter-over-wi-fi--openthread-border-router-configuration-on-rt1060-evk-c--iw612) - - [Build with Matter over Wi-Fi + OpenThread Border Router configuration on RT1060 + 88W8801 + K32W0x1DK6](#build-with-matter-over-wi-fi--openthread-border-router-configuration-on-rt1060--88w8801--k32w0x1dk6) - - [General Information](#general-information) - [Manufacturing data](#manufacturing-data) - [Flashing and debugging](#flashing-and-debugging) - [Testing the example](#testing-the-example) @@ -289,166 +281,6 @@ automatically by the host build in > [How to customize the CMake build](./nxp_examples_freertos_platforms.md#how-to-customize-the-cmake-build) > section. -### GN Build System - -#### Building with Matter over Wifi configuration on RT1060 + transceiver - -- Build the Wi-fi configuration for **MIMXRT1060-EVK-B board + IW416 - transceiver** (with BLE for commissioning). - -``` -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ gn gen --args="chip_enable_wifi=true iw416_transceiver=true" out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ ninja -C out/debug -``` - -- Build the Wi-fi configuration for **MIMXRT1060-EVK-B board + 88W8801 - transceiver** with Matter-over-Wifi configuration and only onnetwork - commissioning (without BLE, the WiFi network credentials are provided at - build-time which will enable the device to join the Wi-Fi AP at startup): - -``` -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ export ssid_name= && export ssid_password= && gn gen --args="chip_enable_wifi=true w8801_transceiver=true chip_config_network_layer_ble=false wifi_auto_connect_at_boot=true wifi_auto_connect_at_boot_ssid=\"${ssid_name}\" wifi_auto_connect_at_boot_password=\"${ssid_password}\"" out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ ninja -C out/debug -``` - -- Build the Wi-fi configuration for **MIMXRT1060-EVK-C board + IW612 - transceiver** (with BLE for commissioning). - -``` -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ gn gen --args="chip_enable_wifi=true iwx12_transceiver=true evkname=\"evkcmimxrt1060\" " out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ ninja -C out/debug -``` - -- Build the Wi-fi configuration for **MIMXRT1060-EVK-C board + IW612 - transceiver** with Matter-over-Wifi configuration and only onnetwork - commissioning (without BLE, the WiFi network credentials are provided at - build-time which will enable the device to join the Wi-Fi AP at startup): - -``` -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ export ssid_name= && export ssid_password= && gn gen --args="chip_enable_wifi=true iwx12_transceiver=true evkname=\"evkcmimxrt1060\" chip_config_network_layer_ble=false wifi_auto_connect_at_boot=true wifi_auto_connect_at_boot_ssid=\"${ssid_name}\" wifi_auto_connect_at_boot_password=\"${ssid_password}\"" out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ ninja -C out/debug -``` - -#### Build with Matter over Thread configuration on RT1060 + transceiver - -##### Build with Matter over Thread configuration on RT1060 + K32W0 - -For this configuration a K32W0 RCP image is required and must support in a -single image the openthread RCP configuration and the BLE HCI BB configuration. -Messages between the host and the K32W0 transceiver are transferred on a single -UART with flow control support. For that the HDLC-Lite framing protocol is used -to transfer spinel and hci frames. In addition, hci and spinel frames can be -distinguished by using the Spinel convention which is line compatible with -BT/BLE HCI. - -Before building the Matter host application, it is required to generate the -K32W0 image supporting features as described above. To build this binary the -target `ot_rcp_ble_hci_bb_single_uart_fc` should be built by following the -[Readme.md][ot_rcp_ble_hci_bb_k32w0_readme]. After a successful build, a `".h"` -file will be generated and would contain the K32W0 RCP binary. As described in -the [Readme.md][ot_rcp_ble_hci_bb_k32w0_readme], the application binaries will -be generated in -`ot_nxp/build_k32w061/ot_rcp_ble_hci_bb_single_uart_fc/bin/ot-rcp-ble-hci-bb-k32w061.elf.bin.h`. - -The generate K32W0 transceiver binary `".h"` file path must be indicated to the -host Matter application build. In fact the Matter host application is in charge -of storing the K32W0 firmware in its flash to be able to use the -`The Over The Wire (OTW) protocol (over UART)` to download (at host startup) the -k32w0 transceiver image from the host to the K32W0 internal flash. For more -information on the k32w0 `OTW` protocol, user can consult the doxygen header of -the file located in -`/third_party/nxp/nxp_matter_support/github_sdk/sdk_next/repo/middleware/wireless/framework/OTW/k32w0_transceiver/fwk_otw.c`. - -Here is a summary of the k32w0 _gn gen_ arguments that are mandatory or -optional: - -- Mandatory: `k32w0_transceiver=true` -- Mandatory: `hci_spinel_single_uart=true` -- Optional: - `k32w0_transceiver_bin_path=\"/home/ot-nxp/build_k32w061/ot_rcp_ble_hci_bb_single_uart_fc/bin/ot-rcp-ble-hci-bb-k32w061.elf.bin.h\"` - This argument is optional, by default, if not set, the binary file located - in - "\${chip_root}/third_party/openthread/ot_nxp/build_k32w061/ot_rcp_ble_hci_bb_single_uart_fc/bin/ot-rcp-ble-hci-bb-k32w061.elf.bin.h" - will be used. If the K32W061 transceiver binary is saved at another location - an absolute path of its location should be given. -- Optional: `otw_logs_enabled=true` This argument is optional, by default - being set to false. If set to true, RT logging will print the `OTW` logs. - -[ot_rcp_ble_hci_bb_k32w0_readme]: - https://github.com/NXP/ot-nxp/blob/v1.0.0.2-tag-nxp/examples/hybrid/ot_rcp_ble_hci_bb/k32w061/README.md#building-the-examples - -Below is presented an example of _gn gen_ argument that could be used to -generate the host matter application with a k32w0 transceiver. - -``` -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ gn gen --args="chip_enable_openthread=true k32w0_transceiver=true k32w0_transceiver_bin_path=\"/home/ot-nxp/build_k32w061/ot_rcp_ble_hci_bb_single_uart_fc/bin/ot-rcp-ble-hci-bb-k32w061.elf.bin.h\" hci_spinel_single_uart=true chip_inet_config_enable_ipv4=false chip_config_network_layer_ble=true" out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ ninja -C out/debug -``` - -##### Build with Matter over Thread configuration on RT1060-EVK-C + IW612 - -Build the OpenThread configuration for MIMXRT1060-EVK-C board + IW612 -transceiver (with BLE for commissioning). - -``` -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ gn gen --args="chip_enable_openthread=true iwx12_transceiver=true evkname=\"evkcmimxrt1060\" chip_inet_config_enable_ipv4=false chip_config_network_layer_ble=true" " out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ ninja -C out/debug -``` - -##### Build with Matter over Wi-Fi + OpenThread Border Router configuration on RT1060-EVK-C + IW612 - -This configuration supports the Thread Border Router management cluster to -provision the Thread credentials. Enabling the Matter CLI in order to control -the Thread network on the Border Router is optional but recommended for other -features like the Thread credential sharing. - -Note that the Thread Border Router management cluster is only supported on the -thermostat application for now. - -- Build Matter with Border Router configuration with ble-wifi commissioning: - -``` -user@ubuntu:~/Desktop/git/connectedhomeip/examples/thermostat/nxp/rt/rt1060$ gn gen --args="chip_enable_openthread=true iwx12_transceiver=true evkname=\"evkcmimxrt1060\" chip_enable_wifi=true chip_inet_config_enable_ipv4=false chip_config_network_layer_ble=true chip_enable_secondary_nwk_if=true chip_device_config_thread_network_endpoint_id=2" " out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/thermostat/nxp/rt/rt1060$ ninja -C out/debug -``` - -##### Build with Matter over Wi-Fi + OpenThread Border Router configuration on RT1060 + 88W8801 + K32W0x1DK6 - -This configuration supports the Thread Border Router management cluster to -provision the Thread credentials. Enabling the Matter CLI in order to control -the Thread network on the Border Router is optional but recommended for other -features like the Thread credential sharing. - -Note that the Thread Border Router management cluster is only supported on the -thermostat application for now. - -- Build Matter with Border Router configuration with ble-wifi commissioning: - -``` -user@ubuntu:~/Desktop/git/connectedhomeip/examples/thermostat/nxp/rt/rt1060$ gn gen --args="chip_enable_wifi=true w8801_transceiver=true nxp_enable_matter_cli=true chip_config_network_layer_ble=true chip_enable_openthread=true k32w0_transceiver=true chip_enable_secondary_nwk_if=true chip_device_config_thread_network_endpoint_id=2 k32w0_transceiver_bin_path=\"/path/to/ot-rcp/ot-rcp-ble-hci-bb-k32w061.elf.bin.h\" hci_spinel_single_uart=true " out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/thermostat/nxp/rt/rt1060$ ninja -C out/debug -``` - -- Build Matter with Border Router configuration with onnetwork commissioning: - -``` -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ export ssid_name= && export ssid_password= && gn gen --args="chip_enable_wifi=true w8801_transceiver=true chip_enable_secondary_nwk_if=true chip_device_config_thread_network_endpoint_id=2 nxp_enable_matter_cli=true chip_config_network_layer_ble=false wifi_auto_connect_at_boot=true wifi_auto_connect_at_boot_ssid=\"${ssid_name}\" wifi_auto_connect_at_boot_password=\"${ssid_password}\" chip_enable_openthread=true k32w0_transceiver=true k32w0_transceiver_bin_path=\"/path/to/ot-rcp/ot-rcp-ble-hci-bb-k32w061.elf.bin.h\"" out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ ninja -C out/debug -``` - -#### General Information - -The resulting output file can be found in -out/debug/chip-rt1060-all-cluster-example. - -Additional GN options can be added when building the application. You can check -[Common GN options to FreeRTOS platforms](./nxp_examples_freertos_platforms.md#general-information) -for the full list. Below is the list of RT1060 specific GN options : - -- By default, the MIMXRT1060-EVK-B will be chosen by the application. To - switch to an MIMXRT1060-EVK, the argument `evkname=\"evkmimxrt1060\"` must - be added to the _gn gen_ command. - ## Manufacturing data diff --git a/docs/platforms/nxp/nxp_rt1170_guide.md b/docs/platforms/nxp/nxp_rt1170_guide.md index 4475228f316..9ae480aa3fd 100644 --- a/docs/platforms/nxp/nxp_rt1170_guide.md +++ b/docs/platforms/nxp/nxp_rt1170_guide.md @@ -11,10 +11,6 @@ - [Board settings (Spinel over SPI, I2C, BLE over UART)](#board-settings-spinel-over-spi-i2c-ble-over-uart) - [Building](#building) - [CMake Build System](#cmake-build-system) - - [GN Build System](#gn-build-system) - - [Building with Matter over Wifi configuration on RT1170 + IW612](#building-with-matter-over-wifi-configuration-on-rt1170--iw612) - - [Building with Matter over Thread configuration on RT1170 + IW612](#building-with-matter-over-thread-configuration-on-rt1170--iw612) - - [Building with Matter over Wifi + OpenThread Border Router configuration on RT1170 + IW612](#building-with-matter-over-wifi--openthread-border-router-configuration-on-rt1170--iw612) - [General information](#general-information) - [Manufacturing data](#manufacturing-data) - [Flashing and debugging](#flashing-and-debugging) @@ -56,7 +52,6 @@ over Thread on RT1170 : RT1170 platform supports two different build systems to generate the application : -- `GN` - `CMake` ### Hardware requirements for RT1170 + IW612 @@ -183,55 +178,6 @@ to check all the supported configurations. > [How to customize the CMake build](./nxp_examples_freertos_platforms.md#how-to-customize-the-cmake-build) > section. -### GN Build System - -#### Building with Matter over Wifi configuration on RT1170 + IW612 - -- Build the Wi-fi configuration for MIMXRT1170 board + IW612 transceiver (with - BLE for commissioning). - -``` -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1170$ gn gen --args="chip_enable_wifi=true iwx12_transceiver=true chip_config_network_layer_ble=true chip_enable_ble=true " out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1170$ ninja -C out/debug -``` - -#### Building with Matter over Thread configuration on RT1170 + IW612 - -- Build the Openthread configuration for MIMXRT1170 board + IW612 transceiver - (with BLE for commissioning). - -``` -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-cluster/nxp/rt/rt1170$ gn gen --args="chip_enable_openthread=true iwx12_transceiver=true chip_inet_config_enable_ipv4=false chip_config_network_layer_ble=true" out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-cluster/nxp/rt/rt1170/$ ninja -C out/debug -``` - -#### Building with Matter over Wifi + OpenThread Border Router configuration on RT1170 + IW612 - -This configuration supports the Thread Border Router management cluster to -provision the Thread credentials. Enabling the Matter CLI in order to control -the Thread network on the Border Router is optional but recommended for other -features like the Thread credential sharing. - -Note that the Thread Border Router management cluster is only supported on the -thermostat application for now. - -- Build Matter with Border Router configuration with BLE commissioning - (ble-wifi) : - -``` -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt11170$ gn gen --args="chip_enable_wifi=true iwx12_transceiver=true chip_config_network_layer_ble=true chip_enable_ble=true chip_enable_openthread=true nxp_enable_matter_cli=true" out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1170$ ninja -C out/debug -``` - -### General information - -The resulting output file can be found in -out/debug/chip-rt1170-all-cluster-example. - -Additional GN options can be added when building the application. You can check -[Common GN options to FreeRTOS platforms](./nxp_examples_freertos_platforms.md#general-information) -for the full list. - ## Manufacturing data See diff --git a/docs/testing/python.md b/docs/testing/python.md index 08694dede6d..97648971b81 100644 --- a/docs/testing/python.md +++ b/docs/testing/python.md @@ -502,6 +502,40 @@ Fabric admin for default controller: second_ctrl = fa.new_fabric_admin.NewController(nodeId=node_id) ``` +Reboot the DUT during testing: + +```python +# Simple reboot - device state persists +await self.request_device_reboot() + +# Factory reset - clears device state (removes KVS) +await self.request_device_factory_reset() +``` + +```shell +# Example Command w/ run_python_test.py test runner: +scripts/tests/run_python_test.py --factory-reset --app out/linux-x64-all-clusters/chip-all-clusters-app --app-args "--discriminator 1234 --KVS kvs1" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS src/app/tests/suites/certification/ci-pics-values --endpoint 1" --script src/python_testing/TC_ACL_2_10.py --app-ready-pattern "APP STATUS: Starting event loop" +``` + +The `request_device_reboot()` and `request_device_factory_reset()` methods work +differently depending on the environment. When the test is started with +`run_python_test.py` as it is in the CI, need to make sure to import +MatterBaseTest and have your test module inherit from it to make this +functionality accessible during your test, the device is automatically rebooted +and possibly factory reset during the test depending on test implementation +using the restart_flag_file. When the test is started by some other means (e.g., +during certification testing), you'll be prompted to manually reboot or factory +reset the device using the device-specific mechanism. + +If reboot utilized automatically expires existing controller sessions to device +to force reconnection once device is back up and stable or if factory reset +utilized the device will automatically re-enter commissioning mode to allow new +commissioning once the device is back up and stable. + +See +[TC-ACL-2.10](https://github.com/project-chip/connectedhomeip/blob/master/src/python_testing/TC_ACL_2_10.py) +for an example testing ACL persistence across reboots. + ## Automating manual steps Some test plans have manual steps that require the tester to manually change the diff --git a/examples/air-purifier-app/air-purifier-common/air-purifier-app.matter b/examples/air-purifier-app/air-purifier-common/air-purifier-app.matter index fee76953212..58d18375289 100644 --- a/examples/air-purifier-app/air-purifier-common/air-purifier-app.matter +++ b/examples/air-purifier-app/air-purifier-common/air-purifier-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/air-purifier-app/air-purifier-common/src/air-purifier-manager.cpp b/examples/air-purifier-app/air-purifier-common/src/air-purifier-manager.cpp index 7bf2de05b52..f46ad19a527 100644 --- a/examples/air-purifier-app/air-purifier-common/src/air-purifier-manager.cpp +++ b/examples/air-purifier-app/air-purifier-common/src/air-purifier-manager.cpp @@ -27,8 +27,8 @@ void AirPurifierManager::Init() { FanControl::SetDefaultDelegate(mEndpointId, this); - activatedCarbonFilterInstance.Init(); - hepaFilterInstance.Init(); + TEMPORARY_RETURN_IGNORED activatedCarbonFilterInstance.Init(); + TEMPORARY_RETURN_IGNORED hepaFilterInstance.Init(); mAirQualitySensorManager.Init(); mTemperatureSensorManager.Init(); mHumiditySensorManager.Init(); diff --git a/examples/air-purifier-app/air-purifier-common/src/air-quality-sensor-manager.cpp b/examples/air-purifier-app/air-purifier-common/src/air-quality-sensor-manager.cpp index d6c3155c250..913e7a1d089 100644 --- a/examples/air-purifier-app/air-purifier-common/src/air-quality-sensor-manager.cpp +++ b/examples/air-purifier-app/air-purifier-common/src/air-quality-sensor-manager.cpp @@ -33,126 +33,128 @@ void AirQualitySensorManager::Init() */ // Air Quality - airQualityInstance.Init(); + TEMPORARY_RETURN_IGNORED airQualityInstance.Init(); airQualityInstance.UpdateAirQuality(AirQualityEnum::kGood); // CO2 - carbonDioxideConcentrationMeasurementInstance.Init(); - carbonDioxideConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - carbonDioxideConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - carbonDioxideConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); - carbonDioxideConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - carbonDioxideConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - carbonDioxideConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - carbonDioxideConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - carbonDioxideConcentrationMeasurementInstance.SetUncertainty(0.0f); - carbonDioxideConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED carbonDioxideConcentrationMeasurementInstance.Init(); + TEMPORARY_RETURN_IGNORED carbonDioxideConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED carbonDioxideConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED carbonDioxideConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); + TEMPORARY_RETURN_IGNORED carbonDioxideConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED carbonDioxideConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED carbonDioxideConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED carbonDioxideConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED carbonDioxideConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED carbonDioxideConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); // CO - carbonMonoxideConcentrationMeasurementInstance.Init(); - carbonMonoxideConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - carbonMonoxideConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - carbonMonoxideConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); - carbonMonoxideConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - carbonMonoxideConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - carbonMonoxideConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - carbonMonoxideConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - carbonMonoxideConcentrationMeasurementInstance.SetUncertainty(0.0f); - carbonMonoxideConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED carbonMonoxideConcentrationMeasurementInstance.Init(); + TEMPORARY_RETURN_IGNORED carbonMonoxideConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED carbonMonoxideConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED carbonMonoxideConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); + TEMPORARY_RETURN_IGNORED carbonMonoxideConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED carbonMonoxideConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED carbonMonoxideConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED carbonMonoxideConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED carbonMonoxideConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED carbonMonoxideConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); // NO2 - nitrogenDioxideConcentrationMeasurementInstance.Init(); - nitrogenDioxideConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - nitrogenDioxideConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - nitrogenDioxideConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); - nitrogenDioxideConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - nitrogenDioxideConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - nitrogenDioxideConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - nitrogenDioxideConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - nitrogenDioxideConcentrationMeasurementInstance.SetUncertainty(0.0f); - nitrogenDioxideConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED nitrogenDioxideConcentrationMeasurementInstance.Init(); + TEMPORARY_RETURN_IGNORED nitrogenDioxideConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED nitrogenDioxideConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED nitrogenDioxideConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); + TEMPORARY_RETURN_IGNORED nitrogenDioxideConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED nitrogenDioxideConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED nitrogenDioxideConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED nitrogenDioxideConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED nitrogenDioxideConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED nitrogenDioxideConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); // PM1 - pm1ConcentrationMeasurementInstance.Init(); - pm1ConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - pm1ConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - pm1ConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); - pm1ConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - pm1ConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - pm1ConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - pm1ConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - pm1ConcentrationMeasurementInstance.SetUncertainty(0.0f); - pm1ConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED pm1ConcentrationMeasurementInstance.Init(); + TEMPORARY_RETURN_IGNORED pm1ConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED pm1ConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED pm1ConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); + TEMPORARY_RETURN_IGNORED pm1ConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED pm1ConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED pm1ConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED pm1ConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED pm1ConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED pm1ConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); // PM10 - pm10ConcentrationMeasurementInstance.Init(); - pm10ConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - pm10ConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - pm10ConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); - pm10ConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - pm10ConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - pm10ConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - pm10ConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - pm10ConcentrationMeasurementInstance.SetUncertainty(0.0f); - pm10ConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED pm10ConcentrationMeasurementInstance.Init(); + TEMPORARY_RETURN_IGNORED pm10ConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED pm10ConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED pm10ConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); + TEMPORARY_RETURN_IGNORED pm10ConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED pm10ConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED pm10ConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED pm10ConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED pm10ConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED pm10ConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); // PM2.5 - pm25ConcentrationMeasurementInstance.Init(); - pm25ConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - pm25ConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - pm25ConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); - pm25ConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - pm25ConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - pm25ConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - pm25ConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - pm25ConcentrationMeasurementInstance.SetUncertainty(0.0f); - pm25ConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED pm25ConcentrationMeasurementInstance.Init(); + TEMPORARY_RETURN_IGNORED pm25ConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED pm25ConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED pm25ConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); + TEMPORARY_RETURN_IGNORED pm25ConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED pm25ConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED pm25ConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED pm25ConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED pm25ConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED pm25ConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); // Radon - radonConcentrationMeasurementInstance.Init(); - radonConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - radonConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - radonConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); - radonConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - radonConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - radonConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - radonConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - radonConcentrationMeasurementInstance.SetUncertainty(0.0f); - radonConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED radonConcentrationMeasurementInstance.Init(); + TEMPORARY_RETURN_IGNORED radonConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED radonConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED radonConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); + TEMPORARY_RETURN_IGNORED radonConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED radonConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED radonConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED radonConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED radonConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED radonConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); // TVOC - totalVolatileOrganicCompoundsConcentrationMeasurementInstance.Init(); - totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); - totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetUncertainty(0.0f); - totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED totalVolatileOrganicCompoundsConcentrationMeasurementInstance.Init(); + TEMPORARY_RETURN_IGNORED totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetMaxMeasuredValue( + MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); + TEMPORARY_RETURN_IGNORED totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetAverageMeasuredValue( + MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED totalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); // Ozone - ozoneConcentrationMeasurementInstance.Init(); - ozoneConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - ozoneConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - ozoneConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); - ozoneConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - ozoneConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - ozoneConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - ozoneConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - ozoneConcentrationMeasurementInstance.SetUncertainty(0.0f); - ozoneConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED ozoneConcentrationMeasurementInstance.Init(); + TEMPORARY_RETURN_IGNORED ozoneConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED ozoneConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED ozoneConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); + TEMPORARY_RETURN_IGNORED ozoneConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED ozoneConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED ozoneConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED ozoneConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED ozoneConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED ozoneConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); // Formaldehyde - formaldehydeConcentrationMeasurementInstance.Init(); - formaldehydeConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - formaldehydeConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - formaldehydeConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); - formaldehydeConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - formaldehydeConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - formaldehydeConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - formaldehydeConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - formaldehydeConcentrationMeasurementInstance.SetUncertainty(0.0f); - formaldehydeConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED formaldehydeConcentrationMeasurementInstance.Init(); + TEMPORARY_RETURN_IGNORED formaldehydeConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED formaldehydeConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED formaldehydeConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); + TEMPORARY_RETURN_IGNORED formaldehydeConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED formaldehydeConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED formaldehydeConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED formaldehydeConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED formaldehydeConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED formaldehydeConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); } diff --git a/examples/air-purifier-app/air-purifier-common/src/filter-delegates.cpp b/examples/air-purifier-app/air-purifier-common/src/filter-delegates.cpp index 74091ab778b..eb5d4d573d0 100644 --- a/examples/air-purifier-app/air-purifier-common/src/filter-delegates.cpp +++ b/examples/air-purifier-app/air-purifier-common/src/filter-delegates.cpp @@ -80,23 +80,23 @@ CHIP_ERROR ImmutableReplacementProductListManager::Next(ReplacementProductStruct { case 0: { item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kUpc); - item.SetProductIdentifierValue(CharSpan::fromCharString("111112222233")); + TEMPORARY_RETURN_IGNORED item.SetProductIdentifierValue(CharSpan::fromCharString("111112222233")); break; case 1: item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kGtin8); - item.SetProductIdentifierValue(CharSpan::fromCharString("gtin8xxx")); + TEMPORARY_RETURN_IGNORED item.SetProductIdentifierValue(CharSpan::fromCharString("gtin8xxx")); break; case 2: item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kEan); - item.SetProductIdentifierValue(CharSpan::fromCharString("4444455555666")); + TEMPORARY_RETURN_IGNORED item.SetProductIdentifierValue(CharSpan::fromCharString("4444455555666")); break; case 3: item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kGtin14); - item.SetProductIdentifierValue(CharSpan::fromCharString("gtin14xxxxxxxx")); + TEMPORARY_RETURN_IGNORED item.SetProductIdentifierValue(CharSpan::fromCharString("gtin14xxxxxxxx")); break; case 4: item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kOem); - item.SetProductIdentifierValue(CharSpan::fromCharString("oem20xxxxxxxxxxxxxxx")); + TEMPORARY_RETURN_IGNORED item.SetProductIdentifierValue(CharSpan::fromCharString("oem20xxxxxxxxxxxxxxx")); break; default: return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; diff --git a/examples/air-purifier-app/ameba/main/chipinterface.cpp b/examples/air-purifier-app/ameba/main/chipinterface.cpp index 69019d16fcd..a6406b32c56 100755 --- a/examples/air-purifier-app/ameba/main/chipinterface.cpp +++ b/examples/air-purifier-app/ameba/main/chipinterface.cpp @@ -144,9 +144,9 @@ static void InitServer(intptr_t context) static AmebaObserver sAmebaObserver; initParams.appDelegate = &sAmebaObserver; + chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); - chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); NetWorkCommissioningInstInit(); diff --git a/examples/air-purifier-app/linux/main.cpp b/examples/air-purifier-app/linux/main.cpp index 0335ebcaac3..eb2accf6966 100644 --- a/examples/air-purifier-app/linux/main.cpp +++ b/examples/air-purifier-app/linux/main.cpp @@ -50,10 +50,10 @@ void ApplicationInit() EndpointId(TEMPERATURE_SENSOR_ENDPOINT), EndpointId(RELATIVE_HUMIDITY_SENSOR_ENDPOINT), EndpointId(THERMOSTAT_ENDPOINT)); - SetParentEndpointForEndpoint(AIR_QUALITY_SENSOR_ENDPOINT, AIR_PURIFIER_ENDPOINT); - SetParentEndpointForEndpoint(TEMPERATURE_SENSOR_ENDPOINT, AIR_PURIFIER_ENDPOINT); - SetParentEndpointForEndpoint(RELATIVE_HUMIDITY_SENSOR_ENDPOINT, AIR_PURIFIER_ENDPOINT); - SetParentEndpointForEndpoint(THERMOSTAT_ENDPOINT, AIR_PURIFIER_ENDPOINT); + SuccessOrDie(SetParentEndpointForEndpoint(AIR_QUALITY_SENSOR_ENDPOINT, AIR_PURIFIER_ENDPOINT)); + SuccessOrDie(SetParentEndpointForEndpoint(TEMPERATURE_SENSOR_ENDPOINT, AIR_PURIFIER_ENDPOINT)); + SuccessOrDie(SetParentEndpointForEndpoint(RELATIVE_HUMIDITY_SENSOR_ENDPOINT, AIR_PURIFIER_ENDPOINT)); + SuccessOrDie(SetParentEndpointForEndpoint(THERMOSTAT_ENDPOINT, AIR_PURIFIER_ENDPOINT)); } void ApplicationShutdown() diff --git a/examples/air-quality-sensor-app/air-quality-sensor-common/air-quality-sensor-app.matter b/examples/air-quality-sensor-app/air-quality-sensor-common/air-quality-sensor-app.matter index 1d4eea2ca03..524df27362f 100644 --- a/examples/air-quality-sensor-app/air-quality-sensor-common/air-quality-sensor-app.matter +++ b/examples/air-quality-sensor-app/air-quality-sensor-common/air-quality-sensor-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/air-quality-sensor-app/air-quality-sensor-common/icd-lit-air-quality-sensor-app.matter b/examples/air-quality-sensor-app/air-quality-sensor-common/icd-lit-air-quality-sensor-app.matter index adbd4c5347e..2a3812d9061 100644 --- a/examples/air-quality-sensor-app/air-quality-sensor-common/icd-lit-air-quality-sensor-app.matter +++ b/examples/air-quality-sensor-app/air-quality-sensor-common/icd-lit-air-quality-sensor-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/all-clusters-app/all-clusters-common/BUILD.gn b/examples/all-clusters-app/all-clusters-common/BUILD.gn index fe7b6006343..757b5df3bac 100644 --- a/examples/all-clusters-app/all-clusters-common/BUILD.gn +++ b/examples/all-clusters-app/all-clusters-common/BUILD.gn @@ -21,6 +21,7 @@ chip_data_model("all-clusters-common") { "${chip_root}/src/app/clusters/bindings:binding-manager", "${chip_root}/src/app/clusters/tls-certificate-management-server", "${chip_root}/src/app/clusters/tls-certificate-management-server:certificate-table", + "${chip_root}/src/app/clusters/tls-client-management-server", "${chip_root}/src/crypto", ] zap_file = "all-clusters-app.zap" diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter index 0aeb0b12ed2..41191eac6a1 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } @@ -6293,573 +6295,19 @@ cluster LowPower = 1288 { command Sleep(): DefaultSuccess = 0; } -/** The Camera AV Stream Management cluster is used to allow clients to manage, control, and configure various audio, video, and snapshot streams on a camera. */ -cluster CameraAvStreamManagement = 1361 { - revision 1; - - enum AudioCodecEnum : enum8 { - kOPUS = 0 [spec_name = "OPUS"]; - kAACLC = 1 [spec_name = "AAC-LC"]; - } - - enum ImageCodecEnum : enum8 { - kJPEG = 0 [spec_name = "JPEG"]; - } - - enum TriStateAutoEnum : enum8 { - kOff = 0; - kOn = 1; - kAuto = 2; - } - - enum TwoWayTalkSupportTypeEnum : enum8 { - kNotSupported = 0; - kHalfDuplex = 1; - kFullDuplex = 2; - } - - enum VideoCodecEnum : enum8 { - kH264 = 0; - kHEVC = 1 [spec_name = "HEVC"]; - kVVC = 2 [spec_name = "VVC"]; - kAV1 = 3 [spec_name = "AV1"]; - } - - bitmap Feature : bitmap32 { - kAudio = 0x1; - kVideo = 0x2; - kSnapshot = 0x4; - kPrivacy = 0x8; - kSpeaker = 0x10; - kImageControl = 0x20; - kWatermark = 0x40; - kOnScreenDisplay = 0x80; - kLocalStorage = 0x100; - kHighDynamicRange = 0x200; - kNightVision = 0x400; - } - - struct VideoResolutionStruct { - int16u width = 0; - int16u height = 1; - } - - struct VideoStreamStruct { - int16u videoStreamID = 0; - StreamUsageEnum streamUsage = 1; - VideoCodecEnum videoCodec = 2; - int16u minFrameRate = 3; - int16u maxFrameRate = 4; - VideoResolutionStruct minResolution = 5; - VideoResolutionStruct maxResolution = 6; - int32u minBitRate = 7; - int32u maxBitRate = 8; - int16u keyFrameInterval = 9; - optional boolean watermarkEnabled = 10; - optional boolean OSDEnabled = 11; - int8u referenceCount = 12; - } - - struct SnapshotStreamStruct { - int16u snapshotStreamID = 0; - ImageCodecEnum imageCodec = 1; - int16u frameRate = 2; - VideoResolutionStruct minResolution = 3; - VideoResolutionStruct maxResolution = 4; - int8u quality = 5; - int8u referenceCount = 6; - boolean encodedPixels = 7; - boolean hardwareEncoder = 8; - optional boolean watermarkEnabled = 9; - optional boolean OSDEnabled = 10; - } - - struct SnapshotCapabilitiesStruct { - VideoResolutionStruct resolution = 0; - int16u maxFrameRate = 1; - ImageCodecEnum imageCodec = 2; - boolean requiresEncodedPixels = 3; - optional boolean requiresHardwareEncoder = 4; - } - - struct RateDistortionTradeOffPointsStruct { - VideoCodecEnum codec = 0; - VideoResolutionStruct resolution = 1; - int32u minBitRate = 2; - } - - struct AudioCapabilitiesStruct { - int8u maxNumberOfChannels = 0; - AudioCodecEnum supportedCodecs[] = 1; - int32u supportedSampleRates[] = 2; - int8u supportedBitDepths[] = 3; - } - - struct AudioStreamStruct { - int16u audioStreamID = 0; - StreamUsageEnum streamUsage = 1; - AudioCodecEnum audioCodec = 2; - int8u channelCount = 3; - int32u sampleRate = 4; - int32u bitRate = 5; - int8u bitDepth = 6; - int8u referenceCount = 7; - } - - struct VideoSensorParamsStruct { - int16u sensorWidth = 0; - int16u sensorHeight = 1; - int16u maxFPS = 2; - optional int16u maxHDRFPS = 3; - } - - readonly attribute optional int8u maxConcurrentEncoders = 0; - readonly attribute optional int32u maxEncodedPixelRate = 1; - readonly attribute optional VideoSensorParamsStruct videoSensorParams = 2; - readonly attribute optional boolean nightVisionUsesInfrared = 3; - readonly attribute optional VideoResolutionStruct minViewportResolution = 4; - readonly attribute optional RateDistortionTradeOffPointsStruct rateDistortionTradeOffPoints[] = 5; - readonly attribute int32u maxContentBufferSize = 6; - readonly attribute optional AudioCapabilitiesStruct microphoneCapabilities = 7; - readonly attribute optional AudioCapabilitiesStruct speakerCapabilities = 8; - readonly attribute optional TwoWayTalkSupportTypeEnum twoWayTalkSupport = 9; - readonly attribute optional SnapshotCapabilitiesStruct snapshotCapabilities[] = 10; - readonly attribute int32u maxNetworkBandwidth = 11; - readonly attribute optional int16u currentFrameRate = 12; - attribute access(read: manage, write: manage) optional boolean HDRModeEnabled = 13; - readonly attribute StreamUsageEnum supportedStreamUsages[] = 14; - readonly attribute optional VideoStreamStruct allocatedVideoStreams[] = 15; - readonly attribute optional AudioStreamStruct allocatedAudioStreams[] = 16; - readonly attribute optional SnapshotStreamStruct allocatedSnapshotStreams[] = 17; - readonly attribute StreamUsageEnum streamUsagePriorities[] = 18; - attribute optional boolean softRecordingPrivacyModeEnabled = 19; - attribute optional boolean softLivestreamPrivacyModeEnabled = 20; - readonly attribute optional boolean hardPrivacyModeOn = 21; - attribute access(read: manage, write: manage) optional TriStateAutoEnum nightVision = 22; - attribute access(read: manage, write: manage) optional TriStateAutoEnum nightVisionIllum = 23; - attribute access(read: manage, write: manage) optional ViewportStruct viewport = 24; - attribute access(read: manage, write: manage) optional boolean speakerMuted = 25; - attribute access(read: manage, write: manage) optional int8u speakerVolumeLevel = 26; - readonly attribute access(read: manage) optional int8u speakerMaxLevel = 27; - readonly attribute access(read: manage) optional int8u speakerMinLevel = 28; - attribute access(read: manage, write: manage) optional boolean microphoneMuted = 29; - attribute access(read: manage, write: manage) optional int8u microphoneVolumeLevel = 30; - readonly attribute access(read: manage) optional int8u microphoneMaxLevel = 31; - readonly attribute access(read: manage) optional int8u microphoneMinLevel = 32; - attribute access(read: manage, write: manage) optional boolean microphoneAGCEnabled = 33; - attribute access(read: manage, write: manage) optional int16u imageRotation = 34; - attribute access(read: manage, write: manage) optional boolean imageFlipHorizontal = 35; - attribute access(read: manage, write: manage) optional boolean imageFlipVertical = 36; - attribute access(read: manage, write: manage) optional boolean localVideoRecordingEnabled = 37; - attribute access(read: manage, write: manage) optional boolean localSnapshotRecordingEnabled = 38; - attribute access(read: manage, write: manage) optional boolean statusLightEnabled = 39; - attribute access(read: manage, write: manage) optional ThreeLevelAutoEnum statusLightBrightness = 40; - readonly attribute command_id generatedCommandList[] = 65528; - readonly attribute command_id acceptedCommandList[] = 65529; - readonly attribute attrib_id attributeList[] = 65531; - readonly attribute bitmap32 featureMap = 65532; - readonly attribute int16u clusterRevision = 65533; - - request struct AudioStreamAllocateRequest { - StreamUsageEnum streamUsage = 0; - AudioCodecEnum audioCodec = 1; - int8u channelCount = 2; - int32u sampleRate = 3; - int32u bitRate = 4; - int8u bitDepth = 5; - } - - response struct AudioStreamAllocateResponse = 1 { - int16u audioStreamID = 0; - } - - request struct AudioStreamDeallocateRequest { - int16u audioStreamID = 0; - } - - request struct VideoStreamAllocateRequest { - StreamUsageEnum streamUsage = 0; - VideoCodecEnum videoCodec = 1; - int16u minFrameRate = 2; - int16u maxFrameRate = 3; - VideoResolutionStruct minResolution = 4; - VideoResolutionStruct maxResolution = 5; - int32u minBitRate = 6; - int32u maxBitRate = 7; - int16u keyFrameInterval = 8; - optional boolean watermarkEnabled = 9; - optional boolean OSDEnabled = 10; - } - - response struct VideoStreamAllocateResponse = 4 { - int16u videoStreamID = 0; - } - - request struct VideoStreamModifyRequest { - int16u videoStreamID = 0; - optional boolean watermarkEnabled = 1; - optional boolean OSDEnabled = 2; - } - - request struct VideoStreamDeallocateRequest { - int16u videoStreamID = 0; - } - - request struct SnapshotStreamAllocateRequest { - ImageCodecEnum imageCodec = 0; - int16u maxFrameRate = 1; - VideoResolutionStruct minResolution = 2; - VideoResolutionStruct maxResolution = 3; - int8u quality = 4; - optional boolean watermarkEnabled = 5; - optional boolean OSDEnabled = 6; - } - - response struct SnapshotStreamAllocateResponse = 8 { - int16u snapshotStreamID = 0; - } - - request struct SnapshotStreamModifyRequest { - int16u snapshotStreamID = 0; - optional boolean watermarkEnabled = 1; - optional boolean OSDEnabled = 2; - } - - request struct SnapshotStreamDeallocateRequest { - int16u snapshotStreamID = 0; - } - - request struct SetStreamPrioritiesRequest { - StreamUsageEnum streamPriorities[] = 0; - } - - request struct CaptureSnapshotRequest { - nullable int16u snapshotStreamID = 0; - VideoResolutionStruct requestedResolution = 1; - } - - response struct CaptureSnapshotResponse = 13 { - octet_string data = 0; - ImageCodecEnum imageCodec = 1; - VideoResolutionStruct resolution = 2; - } - - /** This command SHALL allocate an audio stream on the camera and return an allocated audio stream identifier. */ - command access(invoke: manage) AudioStreamAllocate(AudioStreamAllocateRequest): AudioStreamAllocateResponse = 0; - /** This command SHALL deallocate an audio stream on the camera, corresponding to the given audio stream identifier. */ - command access(invoke: manage) AudioStreamDeallocate(AudioStreamDeallocateRequest): DefaultSuccess = 2; - /** This command SHALL allocate a video stream on the camera and return an allocated video stream identifier. */ - command access(invoke: manage) VideoStreamAllocate(VideoStreamAllocateRequest): VideoStreamAllocateResponse = 3; - /** This command SHALL be used to modify a stream specified by the VideoStreamID. */ - command access(invoke: manage) VideoStreamModify(VideoStreamModifyRequest): DefaultSuccess = 5; - /** This command SHALL deallocate a video stream on the camera, corresponding to the given video stream identifier. */ - command access(invoke: manage) VideoStreamDeallocate(VideoStreamDeallocateRequest): DefaultSuccess = 6; - /** This command SHALL allocate a snapshot stream on the device and return an allocated snapshot stream identifier. */ - command access(invoke: manage) SnapshotStreamAllocate(SnapshotStreamAllocateRequest): SnapshotStreamAllocateResponse = 7; - /** This command SHALL be used to modify a stream specified by the VideoStreamID. */ - command access(invoke: manage) SnapshotStreamModify(SnapshotStreamModifyRequest): DefaultSuccess = 9; - /** This command SHALL deallocate an snapshot stream on the camera, corresponding to the given snapshot stream identifier. */ - command access(invoke: manage) SnapshotStreamDeallocate(SnapshotStreamDeallocateRequest): DefaultSuccess = 10; - /** This command SHALL set the relative priorities of the various stream usages on the camera. */ - command access(invoke: administer) SetStreamPriorities(SetStreamPrioritiesRequest): DefaultSuccess = 11; - /** This command SHALL return a Snapshot from the camera. */ - command CaptureSnapshot(CaptureSnapshotRequest): CaptureSnapshotResponse = 12; -} - -/** This cluster provides an interface into controls associated with the operation of a device that provides pan, tilt, and zoom functions, either mechanically, or against a digital image. */ -cluster CameraAvSettingsUserLevelManagement = 1362 { - revision 1; - - enum PhysicalMovementEnum : enum8 { - kIdle = 0; - kMoving = 1; - } - - bitmap Feature : bitmap32 { - kDigitalPTZ = 0x1; - kMechanicalPan = 0x2; - kMechanicalTilt = 0x4; - kMechanicalZoom = 0x8; - kMechanicalPresets = 0x10; - } - - struct MPTZStruct { - optional int16s pan = 0; - optional int16s tilt = 1; - optional int8u zoom = 2; - } - - struct MPTZPresetStruct { - int8u presetID = 0; - char_string<32> name = 1; - MPTZStruct settings = 2; - } - - struct DPTZStruct { - int16u videoStreamID = 0; - ViewportStruct viewport = 1; - } - - readonly attribute optional MPTZStruct MPTZPosition = 0; - readonly attribute optional int8u maxPresets = 1; - readonly attribute optional MPTZPresetStruct MPTZPresets[] = 2; - readonly attribute optional DPTZStruct DPTZStreams[] = 3; - readonly attribute optional int8u zoomMax = 4; - readonly attribute optional int16s tiltMin = 5; - readonly attribute optional int16s tiltMax = 6; - readonly attribute optional int16s panMin = 7; - readonly attribute optional int16s panMax = 8; - readonly attribute optional PhysicalMovementEnum movementState = 9; - readonly attribute command_id generatedCommandList[] = 65528; - readonly attribute command_id acceptedCommandList[] = 65529; - readonly attribute attrib_id attributeList[] = 65531; - readonly attribute bitmap32 featureMap = 65532; - readonly attribute int16u clusterRevision = 65533; - - request struct MPTZSetPositionRequest { - optional int16s pan = 0; - optional int16s tilt = 1; - optional int8u zoom = 2; - } - - request struct MPTZRelativeMoveRequest { - optional int16s panDelta = 0; - optional int16s tiltDelta = 1; - optional int8s zoomDelta = 2; - } - - request struct MPTZMoveToPresetRequest { - int8u presetID = 0; - } - - request struct MPTZSavePresetRequest { - optional int8u presetID = 0; - char_string<32> name = 1; - } - - request struct MPTZRemovePresetRequest { - int8u presetID = 0; - } - - request struct DPTZSetViewportRequest { - int16u videoStreamID = 0; - ViewportStruct viewport = 1; - } - - request struct DPTZRelativeMoveRequest { - int16u videoStreamID = 0; - optional int16s deltaX = 1; - optional int16s deltaY = 2; - optional int8s zoomDelta = 3; - } - - /** This command SHALL move the camera to the provided values for pan, tilt, and zoom in the mechanical PTZ. */ - command MPTZSetPosition(MPTZSetPositionRequest): DefaultSuccess = 0; - /** This command SHALL move the camera by the delta values relative to the currently defined position. */ - command MPTZRelativeMove(MPTZRelativeMoveRequest): DefaultSuccess = 1; - /** This command SHALL move the camera to the positions specified by the Preset passed. */ - command MPTZMoveToPreset(MPTZMoveToPresetRequest): DefaultSuccess = 2; - /** This command allows creating a new preset or updating the values of an existing one. */ - command MPTZSavePreset(MPTZSavePresetRequest): DefaultSuccess = 3; - /** This command SHALL remove a preset entry from the PresetMptzTable. */ - command MPTZRemovePreset(MPTZRemovePresetRequest): DefaultSuccess = 4; - /** This command allows for setting the digital viewport for a specific Video Stream. */ - command DPTZSetViewport(DPTZSetViewportRequest): DefaultSuccess = 5; - /** This command SHALL change the per stream viewport by the amount specified in a relative fashion. */ - command DPTZRelativeMove(DPTZRelativeMoveRequest): DefaultSuccess = 6; -} - -/** This cluster implements the upload of Audio and Video streams from the Push AV Stream Transport Cluster using suitable push-based transports. */ -cluster PushAvStreamTransport = 1365 { - revision 1; - - enum CMAFInterfaceEnum : enum8 { - kInterface1 = 0; - kInterface2DASH = 1; - kInterface2HLS = 2; - } - - enum ContainerFormatEnum : enum8 { - kCMAF = 0 [spec_name = "CMAF"]; - } - - enum IngestMethodsEnum : enum8 { - kCMAFIngest = 0; - } - - enum StatusCodeEnum : enum8 { - kInvalidTLSEndpoint = 2; - kInvalidStream = 3; - kInvalidURL = 4; - kInvalidZone = 5; - kInvalidCombination = 6; - kInvalidTriggerType = 7; - kInvalidTransportStatus = 8; - kInvalidOptions = 9; - kInvalidStreamUsage = 10; - kInvalidTime = 11; - } - - enum TransportStatusEnum : enum8 { - kActive = 0; - kInactive = 1; - } - - enum TransportTriggerTypeEnum : enum8 { - kCommand = 0; - kMotion = 1; - kContinuous = 2; - } - - enum TriggerActivationReasonEnum : enum8 { - kUserInitiated = 0; - kAutomation = 1; - kEmergency = 2; - } - - bitmap Feature : bitmap32 { - kPerZoneSensitivity = 0x1; - kMetadata = 0x2; - } - - struct TransportMotionTriggerTimeControlStruct { - int16u initialDuration = 0; - int16u augmentationDuration = 1; - elapsed_s maxDuration = 2; - int16u blindDuration = 3; - } - - struct TransportZoneOptionsStruct { - nullable int16u zone = 0; - optional int8u sensitivity = 1; - } - - struct TransportTriggerOptionsStruct { - TransportTriggerTypeEnum triggerType = 0; - optional nullable TransportZoneOptionsStruct motionZones[] = 1; - optional nullable int8u motionSensitivity = 2; - optional TransportMotionTriggerTimeControlStruct motionTimeControl = 3; - optional int16u maxPreRollLen = 4; - } - - struct CMAFContainerOptionsStruct { - CMAFInterfaceEnum CMAFInterface = 0; - int16u segmentDuration = 1; - int16u chunkDuration = 2; - int8u sessionGroup = 3; - char_string<16> trackName = 4; - optional octet_string<16> CENCKey = 5; - optional octet_string<16> CENCKeyID = 6; - optional boolean metadataEnabled = 7; - } - - struct ContainerOptionsStruct { - ContainerFormatEnum containerType = 0; - optional CMAFContainerOptionsStruct CMAFContainerOptions = 1; - } - - struct TransportOptionsStruct { - StreamUsageEnum streamUsage = 0; - optional nullable int16u videoStreamID = 1; - optional nullable int16u audioStreamID = 2; - int16u TLSEndpointID = 3; - long_char_string<2000> url = 4; - TransportTriggerOptionsStruct triggerOptions = 5; - IngestMethodsEnum ingestMethod = 6; - ContainerOptionsStruct containerOptions = 7; - optional epoch_s expiryTime = 8; - } - - fabric_scoped struct TransportConfigurationStruct { - int16u connectionID = 0; - TransportStatusEnum transportStatus = 1; - optional TransportOptionsStruct transportOptions = 2; - fabric_idx fabricIndex = 254; - } - - struct SupportedFormatStruct { - ContainerFormatEnum containerFormat = 0; - IngestMethodsEnum ingestMethod = 1; - } - - info event PushTransportBegin = 0 { - int16u connectionID = 0; - TransportTriggerTypeEnum triggerType = 1; - optional TriggerActivationReasonEnum activationReason = 2; - } - - info event PushTransportEnd = 1 { - int16u connectionID = 0; - } - - readonly attribute SupportedFormatStruct supportedFormats[] = 0; - readonly attribute TransportConfigurationStruct currentConnections[] = 1; - readonly attribute command_id generatedCommandList[] = 65528; - readonly attribute command_id acceptedCommandList[] = 65529; - readonly attribute attrib_id attributeList[] = 65531; - readonly attribute bitmap32 featureMap = 65532; - readonly attribute int16u clusterRevision = 65533; - - request struct AllocatePushTransportRequest { - TransportOptionsStruct transportOptions = 0; - } - - response struct AllocatePushTransportResponse = 1 { - TransportConfigurationStruct transportConfiguration = 0; - } - - request struct DeallocatePushTransportRequest { - int16u connectionID = 0; - } - - request struct ModifyPushTransportRequest { - int16u connectionID = 0; - TransportOptionsStruct transportOptions = 1; - } - - request struct SetTransportStatusRequest { - nullable int16u connectionID = 0; - TransportStatusEnum transportStatus = 1; - } - - request struct ManuallyTriggerTransportRequest { - int16u connectionID = 0; - TriggerActivationReasonEnum activationReason = 1; - optional TransportMotionTriggerTimeControlStruct timeControl = 2; - optional long_octet_string<256> userDefined = 3; - } - - request struct FindTransportRequest { - nullable int16u connectionID = 0; - } - - response struct FindTransportResponse = 7 { - TransportConfigurationStruct transportConfigurations[] = 0; - } - - /** This command SHALL allocate a transport and return a PushTransportConnectionID. */ - fabric command access(invoke: manage) AllocatePushTransport(AllocatePushTransportRequest): AllocatePushTransportResponse = 0; - /** This command SHALL be generated to request the Node deallocates the specified transport. */ - fabric command access(invoke: manage) DeallocatePushTransport(DeallocatePushTransportRequest): DefaultSuccess = 2; - /** This command is used to request the Node modifies the configuration of the specified push transport. */ - fabric command access(invoke: manage) ModifyPushTransport(ModifyPushTransportRequest): DefaultSuccess = 3; - /** This command SHALL be generated to request the Node modifies the Transport Status of a specified transport or all transports. */ - fabric command access(invoke: manage) SetTransportStatus(SetTransportStatusRequest): DefaultSuccess = 4; - /** This command SHALL be generated to request the Node to manually start the specified push transport. */ - fabric command ManuallyTriggerTransport(ManuallyTriggerTransportRequest): DefaultSuccess = 5; - /** This command SHALL return the Transport Configuration for the specified push transport or all allocated transports for the fabric if null. */ - fabric command FindTransport(FindTransportRequest): FindTransportResponse = 6; -} - /** This cluster provides facilities to configure and play Chime sounds, such as those used in a doorbell. */ cluster Chime = 1366 { - revision 1; + revision 2; struct ChimeSoundStruct { int8u chimeID = 0; char_string<48> name = 1; } + info event ChimeStartedPlaying = 0 { + int8u chimeID = 0; + } + readonly attribute ChimeSoundStruct installedChimeSounds[] = 0; attribute int8u selectedChime = 1; attribute boolean enabled = 2; @@ -6869,7 +6317,12 @@ cluster Chime = 1366 { readonly attribute bitmap32 featureMap = 65532; readonly attribute int16u clusterRevision = 65533; - command PlayChimeSound(): DefaultSuccess = 0; + request struct PlayChimeSoundRequest { + optional int8u chimeID = 0; + } + + /** This command will play the currently selected chime or the chime passed in. */ + command PlayChimeSound(PlayChimeSoundRequest): DefaultSuccess = 0; } /** This Cluster is used to manage TLS Client Certificates and to provision @@ -8604,7 +8057,7 @@ endpoint 1 { ram attribute defaultSensitivityLevel default = 2; ram attribute alarmsActive; ram attribute alarmsSuppressed; - persist attribute alarmsEnabled; + ram attribute alarmsEnabled; ram attribute alarmsSupported default = 0x03; ram attribute sensorFault default = 0; callback attribute generatedCommandList; @@ -9154,109 +8607,6 @@ endpoint 1 { handle command Sleep; } - server cluster CameraAvStreamManagement { - callback attribute maxConcurrentEncoders; - callback attribute maxEncodedPixelRate; - callback attribute videoSensorParams; - callback attribute nightVisionUsesInfrared; - callback attribute minViewportResolution; - callback attribute rateDistortionTradeOffPoints; - callback attribute maxContentBufferSize; - callback attribute microphoneCapabilities; - callback attribute speakerCapabilities; - callback attribute twoWayTalkSupport; - callback attribute snapshotCapabilities; - callback attribute maxNetworkBandwidth; - callback attribute currentFrameRate; - callback attribute HDRModeEnabled; - callback attribute supportedStreamUsages; - callback attribute allocatedVideoStreams; - callback attribute allocatedAudioStreams; - callback attribute allocatedSnapshotStreams; - callback attribute streamUsagePriorities; - callback attribute softRecordingPrivacyModeEnabled; - callback attribute softLivestreamPrivacyModeEnabled; - callback attribute hardPrivacyModeOn; - callback attribute nightVision; - callback attribute nightVisionIllum; - callback attribute viewport; - callback attribute speakerMuted; - callback attribute speakerVolumeLevel; - callback attribute speakerMaxLevel; - callback attribute speakerMinLevel; - callback attribute microphoneMuted; - callback attribute microphoneVolumeLevel; - callback attribute microphoneMaxLevel; - callback attribute microphoneMinLevel; - callback attribute microphoneAGCEnabled; - callback attribute imageRotation; - callback attribute imageFlipHorizontal; - callback attribute imageFlipVertical; - callback attribute localVideoRecordingEnabled; - callback attribute localSnapshotRecordingEnabled; - callback attribute statusLightEnabled; - callback attribute statusLightBrightness; - callback attribute generatedCommandList; - callback attribute acceptedCommandList; - callback attribute attributeList; - callback attribute featureMap; - ram attribute clusterRevision default = 1; - - handle command SnapshotStreamAllocate; - handle command SnapshotStreamAllocateResponse; - handle command SnapshotStreamDeallocate; - handle command SetStreamPriorities; - handle command CaptureSnapshot; - handle command CaptureSnapshotResponse; - } - - server cluster CameraAvSettingsUserLevelManagement { - callback attribute MPTZPosition; - ram attribute maxPresets default = 5; - callback attribute MPTZPresets; - callback attribute DPTZStreams; - ram attribute zoomMax default = 100; - ram attribute tiltMin default = -90; - ram attribute tiltMax default = 90; - ram attribute panMin default = -180; - ram attribute panMax default = 180; - ram attribute movementState; - callback attribute generatedCommandList; - callback attribute acceptedCommandList; - callback attribute attributeList; - ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; - - handle command MPTZSetPosition; - handle command MPTZRelativeMove; - handle command MPTZMoveToPreset; - handle command MPTZSavePreset; - handle command MPTZRemovePreset; - handle command DPTZSetViewport; - handle command DPTZRelativeMove; - } - - server cluster PushAvStreamTransport { - emits event PushTransportBegin; - emits event PushTransportEnd; - callback attribute supportedFormats; - callback attribute currentConnections; - callback attribute generatedCommandList; - callback attribute acceptedCommandList; - callback attribute attributeList; - ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; - - handle command AllocatePushTransport; - handle command AllocatePushTransportResponse; - handle command DeallocatePushTransport; - handle command ModifyPushTransport; - handle command SetTransportStatus; - handle command ManuallyTriggerTransport; - handle command FindTransport; - handle command FindTransportResponse; - } - server cluster Chime { callback attribute installedChimeSounds; callback attribute selectedChime; diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap index 79096ff35aa..578c34942b2 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap @@ -11579,7 +11579,7 @@ "side": "server", "type": "AlarmModeBitmap", "included": 1, - "storageOption": "NVM", + "storageOption": "RAM", "singleton": 0, "bounded": 0, "defaultValue": "", @@ -18870,70 +18870,29 @@ ] }, { - "name": "Camera AV Stream Management", - "code": 1361, + "name": "Chime", + "code": 1366, "mfgCode": null, - "define": "CAMERA_AV_STREAM_MANAGEMENT_CLUSTER", + "define": "CHIME_CLUSTER", "side": "server", "enabled": 1, - "apiMaturity": "provisional", "commands": [ { - "name": "SnapshotStreamAllocate", - "code": 7, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "SnapshotStreamAllocateResponse", - "code": 8, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "SnapshotStreamDeallocate", - "code": 10, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "SetStreamPriorities", - "code": 11, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "CaptureSnapshot", - "code": 12, + "name": "PlayChimeSound", + "code": 0, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 - }, - { - "name": "CaptureSnapshotResponse", - "code": 13, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 } ], "attributes": [ { - "name": "MaxConcurrentEncoders", + "name": "InstalledChimeSounds", "code": 0, "mfgCode": null, "side": "server", - "type": "int8u", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -18945,11 +18904,11 @@ "reportableChange": 0 }, { - "name": "MaxEncodedPixelRate", + "name": "SelectedChime", "code": 1, "mfgCode": null, "side": "server", - "type": "int32u", + "type": "int8u", "included": 1, "storageOption": "External", "singleton": 0, @@ -18961,11 +18920,11 @@ "reportableChange": 0 }, { - "name": "VideoSensorParams", + "name": "Enabled", "code": 2, "mfgCode": null, "side": "server", - "type": "VideoSensorParamsStruct", + "type": "boolean", "included": 1, "storageOption": "External", "singleton": 0, @@ -18977,11 +18936,11 @@ "reportableChange": 0 }, { - "name": "NightVisionUsesInfrared", - "code": 3, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", - "type": "boolean", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -18993,11 +18952,11 @@ "reportableChange": 0 }, { - "name": "MinViewportResolution", - "code": 4, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", - "type": "VideoResolutionStruct", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -19009,8 +18968,8 @@ "reportableChange": 0 }, { - "name": "RateDistortionTradeOffPoints", - "code": 5, + "name": "AttributeList", + "code": 65531, "mfgCode": null, "side": "server", "type": "array", @@ -19025,43 +18984,175 @@ "reportableChange": 0 }, { - "name": "MaxContentBufferSize", - "code": 6, + "name": "FeatureMap", + "code": 65532, "mfgCode": null, "side": "server", - "type": "int32u", + "type": "bitmap32", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "MicrophoneCapabilities", - "code": 7, + "name": "ClusterRevision", + "code": 65533, "mfgCode": null, "side": "server", - "type": "AudioCapabilitiesStruct", + "type": "int16u", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "1", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 + } + ] + }, + { + "name": "TLS Certificate Management", + "code": 2049, + "mfgCode": null, + "define": "TLS_CERTIFICATE_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ProvisionRootCertificate", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ProvisionRootCertificateResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "FindRootCertificate", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "FindRootCertificateResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "LookupRootCertificate", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "LookupRootCertificateResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "RemoveRootCertificate", + "code": 6, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ClientCSR", + "code": 7, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 }, { - "name": "SpeakerCapabilities", + "name": "ClientCSRResponse", "code": 8, "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ProvisionClientCertificate", + "code": 9, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "FindClientCertificate", + "code": 10, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "FindClientCertificateResponse", + "code": 11, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "LookupClientCertificate", + "code": 12, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "LookupClientCertificateResponse", + "code": 13, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "RemoveClientCertificate", + "code": 14, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "MaxRootCertificates", + "code": 0, + "mfgCode": null, "side": "server", - "type": "AudioCapabilitiesStruct", + "type": "int8u", "included": 1, "storageOption": "External", "singleton": 0, @@ -19073,11 +19164,11 @@ "reportableChange": 0 }, { - "name": "TwoWayTalkSupport", - "code": 9, + "name": "ProvisionedRootCertificates", + "code": 1, "mfgCode": null, "side": "server", - "type": "TwoWayTalkSupportTypeEnum", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -19089,11 +19180,11 @@ "reportableChange": 0 }, { - "name": "SnapshotCapabilities", - "code": 10, + "name": "MaxClientCertificates", + "code": 2, "mfgCode": null, "side": "server", - "type": "array", + "type": "int8u", "included": 1, "storageOption": "External", "singleton": 0, @@ -19105,11 +19196,11 @@ "reportableChange": 0 }, { - "name": "MaxNetworkBandwidth", - "code": 11, + "name": "ProvisionedClientCertificates", + "code": 3, "mfgCode": null, "side": "server", - "type": "int32u", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -19121,11 +19212,11 @@ "reportableChange": 0 }, { - "name": "CurrentFrameRate", - "code": 12, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", - "type": "int16u", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -19137,11 +19228,11 @@ "reportableChange": 0 }, { - "name": "HDRModeEnabled", - "code": 13, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", - "type": "boolean", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -19153,8 +19244,8 @@ "reportableChange": 0 }, { - "name": "SupportedStreamUsages", - "code": 14, + "name": "AttributeList", + "code": 65531, "mfgCode": null, "side": "server", "type": "array", @@ -19169,1431 +19260,27 @@ "reportableChange": 0 }, { - "name": "AllocatedVideoStreams", - "code": 15, + "name": "FeatureMap", + "code": 65532, "mfgCode": null, "side": "server", - "type": "array", + "type": "bitmap32", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "AllocatedAudioStreams", - "code": 16, + "name": "ClusterRevision", + "code": 65533, "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": "AllocatedSnapshotStreams", - "code": 17, - "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": "StreamUsagePriorities", - "code": 18, - "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": "SoftRecordingPrivacyModeEnabled", - "code": 19, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "SoftLivestreamPrivacyModeEnabled", - "code": 20, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "HardPrivacyModeOn", - "code": 21, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "NightVision", - "code": 22, - "mfgCode": null, - "side": "server", - "type": "TriStateAutoEnum", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "NightVisionIllum", - "code": 23, - "mfgCode": null, - "side": "server", - "type": "TriStateAutoEnum", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "Viewport", - "code": 24, - "mfgCode": null, - "side": "server", - "type": "ViewportStruct", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "SpeakerMuted", - "code": 25, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "SpeakerVolumeLevel", - "code": 26, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "SpeakerMaxLevel", - "code": 27, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "SpeakerMinLevel", - "code": 28, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MicrophoneMuted", - "code": 29, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MicrophoneVolumeLevel", - "code": 30, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MicrophoneMaxLevel", - "code": 31, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MicrophoneMinLevel", - "code": 32, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MicrophoneAGCEnabled", - "code": 33, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ImageRotation", - "code": 34, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ImageFlipHorizontal", - "code": 35, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ImageFlipVertical", - "code": 36, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "LocalVideoRecordingEnabled", - "code": 37, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "LocalSnapshotRecordingEnabled", - "code": 38, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "StatusLightEnabled", - "code": 39, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "StatusLightBrightness", - "code": 40, - "mfgCode": null, - "side": "server", - "type": "ThreeLevelAutoEnum", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "GeneratedCommandList", - "code": 65528, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AcceptedCommandList", - "code": 65529, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AttributeList", - "code": 65531, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "FeatureMap", - "code": 65532, - "mfgCode": null, - "side": "server", - "type": "bitmap32", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ClusterRevision", - "code": 65533, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "1", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - } - ] - }, - { - "name": "Camera AV Settings User Level Management", - "code": 1362, - "mfgCode": null, - "define": "CAMERA_AV_SETTINGS_USER_LEVEL_MANAGEMENT_CLUSTER", - "side": "server", - "enabled": 1, - "apiMaturity": "provisional", - "commands": [ - { - "name": "MPTZSetPosition", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "MPTZRelativeMove", - "code": 1, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "MPTZMoveToPreset", - "code": 2, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "MPTZSavePreset", - "code": 3, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "MPTZRemovePreset", - "code": 4, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "DPTZSetViewport", - "code": 5, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "DPTZRelativeMove", - "code": 6, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "MPTZPosition", - "code": 0, - "mfgCode": null, - "side": "server", - "type": "MPTZStruct", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MaxPresets", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "5", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MPTZPresets", - "code": 2, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "DPTZStreams", - "code": 3, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ZoomMax", - "code": 4, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "100", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "TiltMin", - "code": 5, - "mfgCode": null, - "side": "server", - "type": "int16s", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "-90", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "TiltMax", - "code": 6, - "mfgCode": null, - "side": "server", - "type": "int16s", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "90", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "PanMin", - "code": 7, - "mfgCode": null, - "side": "server", - "type": "int16s", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "-180", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "PanMax", - "code": 8, - "mfgCode": null, - "side": "server", - "type": "int16s", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "180", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MovementState", - "code": 9, - "mfgCode": null, - "side": "server", - "type": "PhysicalMovementEnum", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "GeneratedCommandList", - "code": 65528, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AcceptedCommandList", - "code": 65529, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AttributeList", - "code": 65531, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "FeatureMap", - "code": 65532, - "mfgCode": null, - "side": "server", - "type": "bitmap32", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ClusterRevision", - "code": 65533, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "1", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - } - ] - }, - { - "name": "Push AV Stream Transport", - "code": 1365, - "mfgCode": null, - "define": "PUSH_AV_STREAM_TRANSPORT_CLUSTER", - "side": "server", - "enabled": 1, - "apiMaturity": "provisional", - "commands": [ - { - "name": "AllocatePushTransport", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "AllocatePushTransportResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "DeallocatePushTransport", - "code": 2, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "ModifyPushTransport", - "code": 3, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "SetTransportStatus", - "code": 4, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "ManuallyTriggerTransport", - "code": 5, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "FindTransport", - "code": 6, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "FindTransportResponse", - "code": 7, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "SupportedFormats", - "code": 0, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "CurrentConnections", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "GeneratedCommandList", - "code": 65528, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AcceptedCommandList", - "code": 65529, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AttributeList", - "code": 65531, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "FeatureMap", - "code": 65532, - "mfgCode": null, - "side": "server", - "type": "bitmap32", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ClusterRevision", - "code": 65533, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "1", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - } - ], - "events": [ - { - "name": "PushTransportBegin", - "code": 0, - "mfgCode": null, - "side": "server", - "included": 1 - }, - { - "name": "PushTransportEnd", - "code": 1, - "mfgCode": null, - "side": "server", - "included": 1 - } - ] - }, - { - "name": "Chime", - "code": 1366, - "mfgCode": null, - "define": "CHIME_CLUSTER", - "side": "server", - "enabled": 1, - "apiMaturity": "provisional", - "commands": [ - { - "name": "PlayChimeSound", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "InstalledChimeSounds", - "code": 0, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "SelectedChime", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "Enabled", - "code": 2, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "GeneratedCommandList", - "code": 65528, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AcceptedCommandList", - "code": 65529, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AttributeList", - "code": 65531, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "FeatureMap", - "code": 65532, - "mfgCode": null, - "side": "server", - "type": "bitmap32", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ClusterRevision", - "code": 65533, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "1", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - } - ] - }, - { - "name": "TLS Certificate Management", - "code": 2049, - "mfgCode": null, - "define": "TLS_CERTIFICATE_MANAGEMENT_CLUSTER", - "side": "server", - "enabled": 1, - "apiMaturity": "provisional", - "commands": [ - { - "name": "ProvisionRootCertificate", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "ProvisionRootCertificateResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "FindRootCertificate", - "code": 2, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "FindRootCertificateResponse", - "code": 3, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "LookupRootCertificate", - "code": 4, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "LookupRootCertificateResponse", - "code": 5, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "RemoveRootCertificate", - "code": 6, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "ClientCSR", - "code": 7, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "ClientCSRResponse", - "code": 8, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "ProvisionClientCertificate", - "code": 9, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "FindClientCertificate", - "code": 10, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "FindClientCertificateResponse", - "code": 11, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "LookupClientCertificate", - "code": 12, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "LookupClientCertificateResponse", - "code": 13, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "RemoveClientCertificate", - "code": 14, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "MaxRootCertificates", - "code": 0, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ProvisionedRootCertificates", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MaxClientCertificates", - "code": 2, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ProvisionedClientCertificates", - "code": 3, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "GeneratedCommandList", - "code": 65528, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AcceptedCommandList", - "code": 65529, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AttributeList", - "code": 65531, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "FeatureMap", - "code": 65532, - "mfgCode": null, - "side": "server", - "type": "bitmap32", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ClusterRevision", - "code": 65533, - "mfgCode": null, - "side": "server", - "type": "int16u", + "type": "int16u", "included": 1, "storageOption": "External", "singleton": 0, @@ -20613,7 +19300,6 @@ "define": "TLS_CLIENT_MANAGEMENT_CLUSTER", "side": "server", "enabled": 1, - "apiMaturity": "provisional", "commands": [ { "name": "ProvisionEndpoint", diff --git a/examples/all-clusters-app/all-clusters-common/include/camera-av-settings-user-level-management-instance.h b/examples/all-clusters-app/all-clusters-common/include/camera-av-settings-user-level-management-instance.h deleted file mode 100644 index 848f623f8b4..00000000000 --- a/examples/all-clusters-app/all-clusters-common/include/camera-av-settings-user-level-management-instance.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * - * Copyright (c) 2025 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 - -namespace chip { -namespace app { -namespace Clusters { -namespace CameraAvSettingsUserLevelManagement { - -class AVSettingsUserLevelManagementDelegate : public Delegate -{ -public: - AVSettingsUserLevelManagementDelegate() = default; - ~AVSettingsUserLevelManagementDelegate() = default; - - void ShutdownApp() override; - - bool CanChangeMPTZ() override; - - CHIP_ERROR LoadMPTZPresets(std::vector & mptzPresetHelpers) override; - CHIP_ERROR LoadDPTZStreams(std::vector & dptzStreams) override; - CHIP_ERROR PersistentAttributesLoadedCallback() override; - - virtual void VideoStreamAllocated(uint16_t aStreamID) override; - virtual void VideoStreamDeallocated(uint16_t aStreamID) override; - virtual void DefaultViewportUpdated(Globals::Structs::ViewportStruct::Type aViewport) override; - - // To be invoked by the Camera App once a physical PTZ action has been completed. This is expected to be a discrete period of - // time after a request is made for PTZ via the HAL. This results in the request command receiving an appropriate status - // response. - void OnPhysicalMoveCompleted(Protocols::InteractionModel::Status status); - - void CancelActiveTimers(); - - /** - * delegate command handlers - */ - Protocols::InteractionModel::Status MPTZSetPosition(Optional aPan, Optional aTilt, Optional aZoom, - PhysicalPTZCallback * callback) override; - Protocols::InteractionModel::Status MPTZRelativeMove(Optional aPan, Optional aTilt, Optional aZoom, - PhysicalPTZCallback * callback) override; - Protocols::InteractionModel::Status MPTZMoveToPreset(uint8_t aPreset, Optional aPan, Optional aTilt, - Optional aZoom, PhysicalPTZCallback * callback) override; - Protocols::InteractionModel::Status MPTZSavePreset(uint8_t aPreset) override; - Protocols::InteractionModel::Status MPTZRemovePreset(uint8_t aPreset) override; - Protocols::InteractionModel::Status DPTZSetViewport(uint16_t aVideoStreamID, - Globals::Structs::ViewportStruct::Type aViewport) override; - Protocols::InteractionModel::Status DPTZRelativeMove(uint16_t aVideoStreamID, Optional aDeltaX, - Optional aDeltaY, Optional aZoomDelta, - Globals::Structs::ViewportStruct::Type & aViewport) override; - -private: - PhysicalPTZCallback * mCallback = nullptr; -}; - -void Shutdown(); - -} // namespace CameraAvSettingsUserLevelManagement -} // namespace Clusters -} // namespace app -} // namespace chip diff --git a/examples/all-clusters-app/all-clusters-common/include/camera-av-stream-delegate-impl.h b/examples/all-clusters-app/all-clusters-common/include/camera-av-stream-delegate-impl.h deleted file mode 100644 index 651275da5d6..00000000000 --- a/examples/all-clusters-app/all-clusters-common/include/camera-av-stream-delegate-impl.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * - * Copyright (c) 2025 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include -#include - -namespace chip { -namespace app { -namespace Clusters { -namespace CameraAvStreamManagement { - -constexpr uint8_t kMaxVideoStreams = 10; // Maximum number of pre-allocated streams -constexpr uint16_t kInvalidStreamID = 65500; - -struct VideoStream -{ - uint16_t id; // Stream ID - bool isAllocated; // Flag to indicate if the stream is allocated - VideoCodecEnum codec; // Codec information (e.g., "H.264", "HEVC") - uint16_t frameRate; // frame rate -}; - -struct AudioStream -{ - uint16_t id; // Stream ID - bool isAllocated; // Flag to indicate if the stream is allocated - AudioCodecEnum codec; // Codec information (e.g., "OPUS", "AACLC") - uint8_t channelCount; // channel count -}; - -struct SnapshotStream -{ - uint16_t id; // Stream ID - bool isAllocated; // Flag to indicate if the stream is allocated - ImageCodecEnum codec; // Codec information (e.g., "JPEG") - uint8_t quality; // Quality -}; - -/** - * The application delegate to define the options & implement commands. - */ -class CameraAVStreamManager : public CameraAVStreamMgmtDelegate -{ -public: - Protocols::InteractionModel::Status VideoStreamAllocate(const VideoStreamStruct & allocateArgs, - uint16_t & outStreamID) override; - - Protocols::InteractionModel::Status VideoStreamModify(const uint16_t streamID, const chip::Optional waterMarkEnabled, - const chip::Optional osdEnabled) override; - - Protocols::InteractionModel::Status VideoStreamDeallocate(const uint16_t streamID) override; - - Protocols::InteractionModel::Status AudioStreamAllocate(const AudioStreamStruct & allocateArgs, - uint16_t & outStreamID) override; - - Protocols::InteractionModel::Status AudioStreamDeallocate(const uint16_t streamID) override; - - Protocols::InteractionModel::Status SnapshotStreamAllocate(const SnapshotStreamAllocateArgs & allocateArgs, - uint16_t & outStreamID) override; - - Protocols::InteractionModel::Status SnapshotStreamModify(const uint16_t streamID, const chip::Optional waterMarkEnabled, - const chip::Optional osdEnabled) override; - - Protocols::InteractionModel::Status SnapshotStreamDeallocate(const uint16_t streamID) override; - - void OnVideoStreamAllocated(const VideoStreamStruct & allocatedStream, StreamAllocationAction action) override; - - void OnStreamUsagePrioritiesChanged() override; - - void OnAttributeChanged(AttributeId attributeId) override; - - Protocols::InteractionModel::Status CaptureSnapshot(const DataModel::Nullable streamID, - const VideoResolutionStruct & resolution, - ImageSnapshot & outImageSnapshot) override; - - CHIP_ERROR PersistentAttributesLoadedCallback() override; - - CHIP_ERROR OnTransportAcquireAudioVideoStreams(uint16_t audioStreamID, uint16_t videoStreamID) override; - - CHIP_ERROR OnTransportReleaseAudioVideoStreams(uint16_t audioStreamID, uint16_t videoStreamID) override; - - const std::vector & GetAllocatedVideoStreams() const override; - - const std::vector & GetAllocatedAudioStreams() const override; - - void GetBandwidthForStreams(const Optional> & videoStreamId, - const Optional> & audioStreamId, uint32_t & outBandwidthbps); - void Init(); - - CameraAVStreamManager() = default; - ~CameraAVStreamManager() = default; - - // static inline CameraAVStreamManager & GetInstance() { return sCameraAVStreamMgrInstance; } - -private: - std::vector videoStreams; // Vector to hold available video streams - std::vector audioStreams; // Vector to hold available audio streams - std::vector snapshotStreams; // Vector to hold available snapshot streams - std::vector videoStreamStructs; // Vector to hold allocated video streams - std::vector audioStreamStructs; // Vector to hold allocated audio streams - void InitializeAvailableVideoStreams(); - void InitializeAvailableAudioStreams(); - void InitializeAvailableSnapshotStreams(); -}; - -} // namespace CameraAvStreamManagement -} // namespace Clusters -} // namespace app -} // namespace chip diff --git a/examples/all-clusters-app/all-clusters-common/include/chime-instance.h b/examples/all-clusters-app/all-clusters-common/include/chime-instance.h index 5a4bc5e71f1..e3204fab184 100644 --- a/examples/all-clusters-app/all-clusters-common/include/chime-instance.h +++ b/examples/all-clusters-app/all-clusters-common/include/chime-instance.h @@ -39,7 +39,7 @@ class ChimeCommandDelegate : public ChimeDelegate CHIP_ERROR GetChimeIDByIndex(uint8_t chimeIndex, uint8_t & chimeID); - Protocols::InteractionModel::Status PlayChimeSound(); + Protocols::InteractionModel::Status PlayChimeSound(uint8_t chimeID); ChimeCommandDelegate() = default; ~ChimeCommandDelegate() = default; diff --git a/examples/all-clusters-app/all-clusters-common/include/push-av-stream-transport-delegate-impl.h b/examples/all-clusters-app/all-clusters-common/include/push-av-stream-transport-delegate-impl.h deleted file mode 100644 index c6ee97de503..00000000000 --- a/examples/all-clusters-app/all-clusters-common/include/push-av-stream-transport-delegate-impl.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * - * Copyright (c) 2025 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include -#include - -namespace chip { -namespace app { -namespace Clusters { -namespace PushAvStreamTransport { - -struct PushAvStream -{ - uint16_t id; - TransportOptionsStruct transportOptions; - TransportStatusEnum transportStatus; - PushAvStreamTransportStatusEnum connectionStatus; -}; - -/** - * The application delegate to define the options & implement commands. - */ -class PushAvStreamTransportManager : public PushAvStreamTransportDelegate -{ -public: - Protocols::InteractionModel::Status AllocatePushTransport(const TransportOptionsStruct & transportOptions, - const uint16_t connectionID, - FabricIndex accessingFabricIndex) override; - - Protocols::InteractionModel::Status DeallocatePushTransport(const uint16_t connectionID) override; - - Protocols::InteractionModel::Status ModifyPushTransport(const uint16_t connectionID, - const TransportOptionsStorage transportOptions) override; - - Protocols::InteractionModel::Status SetTransportStatus(const std::vector connectionIDList, - TransportStatusEnum transportStatus) override; - - Protocols::InteractionModel::Status ManuallyTriggerTransport( - const uint16_t connectionID, TriggerActivationReasonEnum activationReason, - const Optional & timeControl) override; - - Protocols::InteractionModel::Status - ValidateBandwidthLimit(StreamUsageEnum streamUsage, const Optional> & videoStreamId, - const Optional> & audioStreamId) override; - - Protocols::InteractionModel::Status SelectVideoStream(StreamUsageEnum streamUsage, uint16_t & videoStreamId) override; - - bool ValidateStreamUsage(StreamUsageEnum streamUsage) override; - - bool ValidateSegmentDuration(uint16_t segmentDuration, const Optional> & videoStreamId) override; - - Protocols::InteractionModel::Status SelectAudioStream(StreamUsageEnum streamUsage, uint16_t & audioStreamId) override; - - Protocols::InteractionModel::Status SetVideoStream(uint16_t videoStreamId) override; - - Protocols::InteractionModel::Status SetAudioStream(uint16_t audioStreamId) override; - - Protocols::InteractionModel::Status ValidateZoneId(uint16_t zoneId) override; - - bool ValidateMotionZoneListSize(size_t zoneListSize) override; - - PushAvStreamTransportStatusEnum GetTransportBusyStatus(const uint16_t connectionID) override; - - void OnAttributeChanged(AttributeId attributeId) override; - - CHIP_ERROR LoadCurrentConnections(std::vector & currentConnections) override; - - CHIP_ERROR PersistentAttributesLoadedCallback() override; - - void SetTLSCerts(Tls::CertificateTable::BufferedClientCert & clientCertEntry, - Tls::CertificateTable::BufferedRootCert & rootCertEntry) override - { - // Handle TLS certificates if needed for implementation - } - - CHIP_ERROR IsHardPrivacyModeActive(bool & isActive) override; - - CHIP_ERROR IsSoftRecordingPrivacyModeActive(bool & isActive) override; - - CHIP_ERROR IsSoftLivestreamPrivacyModeActive(bool & isActive) override; - - void SetPushAvStreamTransportServer(PushAvStreamTransportServer * serverLogic) override - { - // Store pointer to server logic if needed for implementation - } - - void Init(); - PushAvStreamTransportManager() = default; - ~PushAvStreamTransportManager() = default; - -private: - std::vector pushavStreams; -}; - -} // namespace PushAvStreamTransport -} // namespace Clusters -} // namespace app -} // namespace chip diff --git a/examples/all-clusters-app/all-clusters-common/include/tls-certificate-management-instance.h b/examples/all-clusters-app/all-clusters-common/include/tls-certificate-management-instance.h index 526a1b493e9..1692522722e 100644 --- a/examples/all-clusters-app/all-clusters-common/include/tls-certificate-management-instance.h +++ b/examples/all-clusters-app/all-clusters-common/include/tls-certificate-management-instance.h @@ -18,7 +18,7 @@ #pragma once -#include +#include namespace chip { namespace app { @@ -27,7 +27,7 @@ namespace Clusters { /** * The application delegate to define the options & implement commands. */ -class TlsCertificateManagementCommandDelegate : public TlsCertificateManagementDelegate +class TlsCertificateManagementCommandDelegate : public TLSCertificateManagementDelegate { static TlsCertificateManagementCommandDelegate instance; Tls::CertificateTable & mCertificateTable; @@ -75,6 +75,12 @@ class TlsCertificateManagementCommandDelegate : public TlsCertificateManagementD static inline TlsCertificateManagementCommandDelegate & GetInstance() { return instance; } }; +/** + * Initialize the TLS Certificate Management cluster with application-specific delegate and certificate table. + * MUST be called before server initialization (e.g. in ApplicationInit()). + */ +void InitializeTlsCertificateManagement(); + } // namespace Clusters } // namespace app } // namespace chip diff --git a/examples/all-clusters-app/all-clusters-common/include/tls-client-management-instance.h b/examples/all-clusters-app/all-clusters-common/include/tls-client-management-instance.h index c62b3fbe86d..f1c56394e57 100644 --- a/examples/all-clusters-app/all-clusters-common/include/tls-client-management-instance.h +++ b/examples/all-clusters-app/all-clusters-common/include/tls-client-management-instance.h @@ -18,9 +18,8 @@ #pragma once -#include +#include #include -#include #include namespace chip { @@ -48,10 +47,10 @@ struct TlsEndpointId bool operator==(const TlsEndpointId & other) const { return (mEndpointId == other.mEndpointId); } }; -class EndpointTable : public app::Storage::FabricTableImpl +class EndpointTable : public app::Storage::FabricTableImpl { public: - using Super = app::Storage::FabricTableImpl; + using Super = app::Storage::FabricTableImpl; EndpointTable() : Super(kMaxProvisionedEndpoints, UINT16_MAX) {} ~EndpointTable() { Finish(); }; @@ -60,7 +59,7 @@ class EndpointTable : public app::Storage::FabricTableImpl airQualityFeatures(Feature::kModerate, Feature::kFair, Feature::kVeryPoor, Feature::kExtremelyPoor); gAirQualityCluster = new Instance(1, airQualityFeatures); - gAirQualityCluster->Init(); + TEMPORARY_RETURN_IGNORED gAirQualityCluster->Init(); } void emberAfAirQualityClusterShutdownCallback(chip::EndpointId endpointId) diff --git a/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp b/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp index 761b96c69cd..c5050ade7cf 100644 --- a/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp @@ -94,14 +94,16 @@ static void BoundDeviceChangedHandler(const Binding::TableEntry & binding, chip: if (sSwitchOnOffState) { Clusters::OnOff::Commands::On::Type onCommand; - Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), - binding.remote, onCommand, onSuccess, onFailure); + TEMPORARY_RETURN_IGNORED Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), + peer_device->GetSecureSession().Value(), binding.remote, + onCommand, onSuccess, onFailure); } else { Clusters::OnOff::Commands::Off::Type offCommand; - Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), - binding.remote, offCommand, onSuccess, onFailure); + TEMPORARY_RETURN_IGNORED Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), + peer_device->GetSecureSession().Value(), binding.remote, + offCommand, onSuccess, onFailure); } } } @@ -114,7 +116,7 @@ static void BoundDeviceContextReleaseHandler(void * context) static void InitBindingHandlerInternal(intptr_t arg) { auto & server = chip::Server::GetInstance(); - Binding::Manager::GetInstance().Init( + TEMPORARY_RETURN_IGNORED Binding::Manager::GetInstance().Init( { &server.GetFabricTable(), server.GetCASESessionManager(), &server.GetPersistentStorage() }); Binding::Manager::GetInstance().RegisterBoundDeviceChangedHandler(BoundDeviceChangedHandler); Binding::Manager::GetInstance().RegisterBoundDeviceContextReleaseHandler(BoundDeviceContextReleaseHandler); @@ -126,7 +128,7 @@ CHIP_ERROR InitBindingHandlers() // so it requires the Server instance to be correctly initialized. Post the init function to // the event queue so that everything is ready when initialization is conducted. // TODO: Fix initialization order issue in Matter server. - chip::DeviceLayer::PlatformMgr().ScheduleWork(InitBindingHandlerInternal); + TEMPORARY_RETURN_IGNORED chip::DeviceLayer::PlatformMgr().ScheduleWork(InitBindingHandlerInternal); #if defined(ENABLE_CHIP_SHELL) RegisterSwitchCommands(); #endif diff --git a/examples/all-clusters-app/all-clusters-common/src/boolcfg-stub.cpp b/examples/all-clusters-app/all-clusters-common/src/boolcfg-stub.cpp index fe2ec905068..c95dc63d5cd 100644 --- a/examples/all-clusters-app/all-clusters-common/src/boolcfg-stub.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/boolcfg-stub.cpp @@ -32,12 +32,12 @@ bool HandleBooleanStateConfigurationTestEventTrigger(uint64_t eventTrigger) { case BooleanStateConfigurationTrigger::kSensorTrigger: ChipLogProgress(Support, "[BooleanStateConfiguration-Test-Event] => Trigger sensor"); - SetAllEnabledAlarmsActive(1); + TEMPORARY_RETURN_IGNORED SetAllEnabledAlarmsActive(1); break; case BooleanStateConfigurationTrigger::kSensorUntrigger: ChipLogProgress(Support, "[BooleanStateConfiguration-Test-Event] => Untrigger sensor"); - ClearAllAlarms(1); + TEMPORARY_RETURN_IGNORED ClearAllAlarms(1); break; default: diff --git a/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp b/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp index 64647b8080d..fe6a620d6ef 100644 --- a/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp @@ -146,7 +146,7 @@ void emberAfActionsClusterInitCallback(EndpointId endpoint) sActionsDelegateImpl = std::make_unique(); sActionsServer = std::make_unique(endpoint, *sActionsDelegateImpl.get()); - sActionsServer->Init(); + TEMPORARY_RETURN_IGNORED sActionsServer->Init(); } void emberAfActionsClusterShutdownCallback(EndpointId endpoint) diff --git a/examples/all-clusters-app/all-clusters-common/src/camera-av-settings-user-level-management-stub.cpp b/examples/all-clusters-app/all-clusters-common/src/camera-av-settings-user-level-management-stub.cpp deleted file mode 100644 index d770551998a..00000000000 --- a/examples/all-clusters-app/all-clusters-common/src/camera-av-settings-user-level-management-stub.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* - * - * Copyright (c) 2025 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -using namespace chip; -using namespace chip::app; -using namespace chip::app::Clusters; -using namespace chip::app::Clusters::CameraAvSettingsUserLevelManagement; - -using chip::Protocols::InteractionModel::Status; - -std::unique_ptr gDelegate; -std::unique_ptr gAVSettingsUserLevelManagementCluster; -static constexpr EndpointId kEndpointId = 1; - -static void onTimerExpiry(System::Layer * systemLayer, void * data); - -void Shutdown() -{ - if (gAVSettingsUserLevelManagementCluster != nullptr) - { - gDelegate->CancelActiveTimers(); - gDelegate = nullptr; - gAVSettingsUserLevelManagementCluster = nullptr; - } -} - -bool AVSettingsUserLevelManagementDelegate::CanChangeMPTZ() -{ - // The server needs to verify that the camera is in a state whereby changing the MPTZ is possible. - // Device specific logic will be required. - return true; -} - -void AVSettingsUserLevelManagementDelegate::VideoStreamAllocated(uint16_t aStreamID) -{ - // The app needs to invoke this whenever the AV Stream Manager allocates a video stream; this informs the server of the - // id that is now subject to DPTZ, and the default viewport of the device - Globals::Structs::ViewportStruct::Type viewport = { 0, 0, 1920, 1080 }; - this->GetServer()->AddMoveCapableVideoStream(aStreamID, viewport); -} - -void AVSettingsUserLevelManagementDelegate::VideoStreamDeallocated(uint16_t aStreamID) -{ - // The app needs to invoke this whenever the AV Stream Manager deallocates a video stream; this informs the server of the - // deallocated id that is now not subject to DPTZ - this->GetServer()->RemoveMoveCapableVideoStream(aStreamID); -} - -void AVSettingsUserLevelManagementDelegate::DefaultViewportUpdated(Globals::Structs::ViewportStruct::Type aViewport) -{ - // The app needs to invoke this whenever the AV Stream Manager updates the device level default Viewport. This informs - // the server of the new viewport that shall be appled to all known streams. - this->GetServer()->UpdateMoveCapableVideoStreams(aViewport); -} - -Status AVSettingsUserLevelManagementDelegate::MPTZSetPosition(Optional aPan, Optional aTilt, - Optional aZoom, PhysicalPTZCallback * callback) -{ - // The Cluster implementation has validated that the Feature Flags are set and the values themselves are in range. Do any needed - // hardware interactions to actually set the camera to the new values of PTZ. Once the hardware has confirmed movements, invoke - // the callback. The server itself will persist the new values. - // - mCallback = callback; - DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(2), onTimerExpiry, this); - - return Status::Success; -} - -Status AVSettingsUserLevelManagementDelegate::MPTZRelativeMove(Optional aPan, Optional aTilt, - Optional aZoom, PhysicalPTZCallback * callback) -{ - // The Cluster implementation has validated that the Feature Flags are set and the values themselves are in range. Do any needed - // hardware interactions to actually set the camera to the new values of PTZ. Once the hardware has confirmed movements, invoke - // the callback. The server itself will persist the new values. - // - mCallback = callback; - DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(2), onTimerExpiry, this); - - return Status::Success; -} - -Status AVSettingsUserLevelManagementDelegate::MPTZMoveToPreset(uint8_t aPreset, Optional aPan, Optional aTilt, - Optional aZoom, PhysicalPTZCallback * callback) -{ - // The Cluster implementation has validated the preset is valid, and provided the MPTZ values associated with that preset. - // Do any needed hardware interactions to actually set the camera to the new values of PTZ. Once the hardware has confirmed - // movements, invoke the callback. The server itself will persist the new values. - // - mCallback = callback; - DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(2), onTimerExpiry, this); - - return Status::Success; -} - -Status AVSettingsUserLevelManagementDelegate::MPTZSavePreset(uint8_t aPreset) -{ - // The Cluster implementation has validated that there is space, and provided the new preset id. - // The application needs to confirm that the current MPTZ values can be save in a new preset. - // - return Status::Success; -} - -Status AVSettingsUserLevelManagementDelegate::MPTZRemovePreset(uint8_t aPreset) -{ - // The Cluster implementation has validated that there is a saved preset associated with the provided id. - // The application needs to confirm that this action is acceptable given the current state of the device. - // - return Status::Success; -} - -Status AVSettingsUserLevelManagementDelegate::DPTZSetViewport(uint16_t aVideoStreamID, - Globals::Structs::ViewportStruct::Type aViewport) -{ - // The Cluster implementation has ensured that the videoStreamID represents a valid stream. - // The application needs to interact with its instance of AVStreamManagement to access the stream, validate the viewport - // and set the new vieport value. - // - return Status::Success; -} - -Status AVSettingsUserLevelManagementDelegate::DPTZRelativeMove(uint16_t aVideoStreamID, Optional aDeltaX, - Optional aDeltaY, Optional aZoomDelta, - Globals::Structs::ViewportStruct::Type & aViewport) -{ - // The Cluster implementation has ensured that the videoStreamID represents a valid stream. - // The application needs to interact with its instance of AVStreamManagement to access the stream, validate - // new dimensions after application of the deltas, and set the new values for the viewport based on the pixel movement - // requested - // The passed in viewport is empty, and needs to be populated by the delegate with the value of the viewport after - // applying all deltas within the constraints of the sensor. - // - aViewport = { 0, 0, 1920, 1080 }; - return Status::Success; -} - -CHIP_ERROR AVSettingsUserLevelManagementDelegate::LoadMPTZPresets(std::vector & mptzPresetHelpers) -{ - mptzPresetHelpers.clear(); - return CHIP_NO_ERROR; -} - -CHIP_ERROR AVSettingsUserLevelManagementDelegate::LoadDPTZStreams(std::vector & dptzStreams) -{ - dptzStreams.clear(); - return CHIP_NO_ERROR; -} - -CHIP_ERROR AVSettingsUserLevelManagementDelegate::PersistentAttributesLoadedCallback() -{ - return CHIP_NO_ERROR; -} - -// Timer expiration to mimic PTZ physical movememt -// -static void onTimerExpiry(System::Layer * systemLayer, void * data) -{ - AVSettingsUserLevelManagementDelegate * delegate = reinterpret_cast(data); - - // All timers are cancelled on delegate shutdown, hence if this is invoked the delegate is alive - delegate->OnPhysicalMoveCompleted(Protocols::InteractionModel::Status::Success); -} - -void AVSettingsUserLevelManagementDelegate::ShutdownApp() -{ - CancelActiveTimers(); -} - -void AVSettingsUserLevelManagementDelegate::CancelActiveTimers() -{ - // Cancel the PTZ mimic timer if it is active - DeviceLayer::SystemLayer().CancelTimer(onTimerExpiry, this); -} - -// To be invoked by the camera once a physical PTZ action has completed. The callback method is realized by our cluster server, -// make sure that is still alive before trying to invoke methods thereon. -// -void AVSettingsUserLevelManagementDelegate::OnPhysicalMoveCompleted(Protocols::InteractionModel::Status status) -{ - if (GetServer() != nullptr) - { - if (mCallback != nullptr) - { - mCallback->OnPhysicalMovementComplete(status); - } - } -} - -void emberAfCameraAvSettingsUserLevelManagementClusterInitCallback(chip::EndpointId aEndpointId) -{ - VerifyOrDie(aEndpointId == 1); // this cluster is only enabled for endpoint 1. - VerifyOrDie(!gDelegate && !gAVSettingsUserLevelManagementCluster); - const int16_t appPanMin = -90; - const int16_t appPanMax = 90; - const int16_t appTiltMin = -45; - const int16_t appTiltMax = 45; - const uint8_t appZoomMax = 75; - const uint8_t appMaxPresets = 5; - - gDelegate = std::make_unique(); - BitFlags avsumFeatures( - CameraAvSettingsUserLevelManagement::Feature::kDigitalPTZ, CameraAvSettingsUserLevelManagement::Feature::kMechanicalPan, - CameraAvSettingsUserLevelManagement::Feature::kMechanicalTilt, - CameraAvSettingsUserLevelManagement::Feature::kMechanicalZoom, - CameraAvSettingsUserLevelManagement::Feature::kMechanicalPresets); - BitFlags avsumAttrs( - CameraAvSettingsUserLevelManagement::OptionalAttributes::kMptzPosition, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kMaxPresets, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kMptzPresets, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kDptzStreams, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kZoomMax, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kTiltMin, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kTiltMax, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kPanMin, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kPanMax, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kMovementState); - - gAVSettingsUserLevelManagementCluster = std::make_unique( - kEndpointId, *gDelegate.get(), avsumFeatures, avsumAttrs, appMaxPresets); - gAVSettingsUserLevelManagementCluster->Init(); - - // Set app specific limits to pan, tilt, zoom - gAVSettingsUserLevelManagementCluster->SetPanMin(appPanMin); - gAVSettingsUserLevelManagementCluster->SetPanMax(appPanMax); - gAVSettingsUserLevelManagementCluster->SetTiltMin(appTiltMin); - gAVSettingsUserLevelManagementCluster->SetTiltMax(appTiltMax); - gAVSettingsUserLevelManagementCluster->SetZoomMax(appZoomMax); -} diff --git a/examples/all-clusters-app/all-clusters-common/src/camera-av-stream-delegate-impl.cpp b/examples/all-clusters-app/all-clusters-common/src/camera-av-stream-delegate-impl.cpp deleted file mode 100644 index dd67a6809b1..00000000000 --- a/examples/all-clusters-app/all-clusters-common/src/camera-av-stream-delegate-impl.cpp +++ /dev/null @@ -1,400 +0,0 @@ -/* - * - * Copyright (c) 2025 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 -#include - -#define SNAPSHOT_FILE_PATH "./capture_snapshot_test.jpg" -#define SNAPSHOT_FILE_RES_WIDTH (168) -#define SNAPSHOT_FILE_RES_HEIGHT (112) - -using namespace chip; -using namespace chip::app; -using namespace chip::app::DataModel; -using namespace chip::app::Clusters; -using namespace chip::app::Clusters::Globals; -using namespace chip::app::Clusters::CameraAvStreamManagement; -using chip::Protocols::InteractionModel::Status; - -// Global pointer to overall Camera AVStream Manager implementing the Cluster delegate. -std::unique_ptr sCameraAVStreamMgrInstance; - -// Global pointer to Camera AVStream Mgmt Server SDK cluster; -std::unique_ptr sCameraAVStreamMgmtClusterServerInstance; - -Protocols::InteractionModel::Status CameraAVStreamManager::VideoStreamAllocate(const VideoStreamStruct & allocateArgs, - uint16_t & outStreamID) -{ - outStreamID = kInvalidStreamID; - bool foundAvailableStream = false; - - for (VideoStream & stream : videoStreams) - { - if (!stream.isAllocated) - { - foundAvailableStream = true; - - if (stream.codec == allocateArgs.videoCodec) - { - stream.isAllocated = true; - outStreamID = stream.id; - return Status::Success; - } - } - } - - if (!foundAvailableStream) - { - return Status::ResourceExhausted; - } - - return Status::Failure; -} - -Protocols::InteractionModel::Status CameraAVStreamManager::VideoStreamModify(const uint16_t streamID, - const Optional waterMarkEnabled, - const Optional osdEnabled) -{ - for (VideoStream & stream : videoStreams) - { - if (stream.id == streamID && stream.isAllocated) - { - ChipLogError(Zcl, "Modified video stream with ID: %d", streamID); - return Status::Success; - } - } - - ChipLogError(Zcl, "Allocated video stream with ID: %d not found", streamID); - return Status::NotFound; -} - -Protocols::InteractionModel::Status CameraAVStreamManager::VideoStreamDeallocate(const uint16_t streamID) -{ - for (VideoStream & stream : videoStreams) - { - if (stream.id == streamID && stream.isAllocated) - { - stream.isAllocated = false; - break; - } - } - - return Status::Success; -} - -Protocols::InteractionModel::Status CameraAVStreamManager::AudioStreamAllocate(const AudioStreamStruct & allocateArgs, - uint16_t & outStreamID) -{ - outStreamID = kInvalidStreamID; - - bool foundAvailableStream = false; - - for (AudioStream & stream : audioStreams) - { - if (!stream.isAllocated) - { - foundAvailableStream = true; - - if (stream.codec == allocateArgs.audioCodec) - { - stream.isAllocated = true; - outStreamID = stream.id; - return Status::Success; - } - } - } - - if (!foundAvailableStream) - { - return Status::ResourceExhausted; - } - - return Status::Failure; -} - -Protocols::InteractionModel::Status CameraAVStreamManager::AudioStreamDeallocate(const uint16_t streamID) -{ - for (AudioStream & stream : audioStreams) - { - if (stream.id == streamID && stream.isAllocated) - { - stream.isAllocated = false; - break; - } - } - - return Status::Success; -} - -Protocols::InteractionModel::Status CameraAVStreamManager::SnapshotStreamAllocate(const SnapshotStreamAllocateArgs & allocateArgs, - uint16_t & outStreamID) -{ - outStreamID = kInvalidStreamID; - - bool foundAvailableStream = false; - - for (SnapshotStream & stream : snapshotStreams) - { - if (!stream.isAllocated) - { - foundAvailableStream = true; - - if (stream.codec == allocateArgs.imageCodec) - { - stream.isAllocated = true; - outStreamID = stream.id; - return Status::Success; - } - } - } - - if (!foundAvailableStream) - { - return Status::ResourceExhausted; - } - - return Status::Failure; -} - -Protocols::InteractionModel::Status CameraAVStreamManager::SnapshotStreamModify(const uint16_t streamID, - const Optional waterMarkEnabled, - const Optional osdEnabled) -{ - for (SnapshotStream & stream : snapshotStreams) - { - if (stream.id == streamID && stream.isAllocated) - { - ChipLogError(Zcl, "Modified snapshot stream with ID: %d", streamID); - return Status::Success; - } - } - - ChipLogError(Zcl, "Allocated snapshot stream with ID: %d not found", streamID); - return Status::NotFound; -} - -Protocols::InteractionModel::Status CameraAVStreamManager::SnapshotStreamDeallocate(const uint16_t streamID) -{ - for (SnapshotStream & stream : snapshotStreams) - { - if (stream.id == streamID && stream.isAllocated) - { - stream.isAllocated = false; - break; - } - } - - return Status::Success; -} - -void CameraAVStreamManager::OnVideoStreamAllocated(const VideoStreamStruct & allocatedStream, StreamAllocationAction action) -{ - ChipLogProgress(Zcl, "Video stream has been allocated"); -} - -void CameraAVStreamManager::OnStreamUsagePrioritiesChanged() -{ - ChipLogProgress(Zcl, "Stream usage priorities changed"); -} - -void CameraAVStreamManager::OnAttributeChanged(AttributeId attributeId) -{ - ChipLogProgress(Zcl, "Attribute changed for AttributeId = " ChipLogFormatMEI, ChipLogValueMEI(attributeId)); -} - -Protocols::InteractionModel::Status CameraAVStreamManager::CaptureSnapshot(const Nullable streamID, - const VideoResolutionStruct & resolution, - ImageSnapshot & outImageSnapshot) -{ - std::ifstream file(SNAPSHOT_FILE_PATH, std::ios::binary | std::ios::ate); - if (!file.is_open()) - { - ChipLogError(Zcl, "Error opening snapshot image file: "); - return Status::Failure; - } - - std::streamsize size = file.tellg(); - file.seekg(0, std::ios::beg); - - // Ensure space for image snapshot data in outImageSnapshot - outImageSnapshot.data.resize(static_cast(size)); - - if (!file.read(reinterpret_cast(outImageSnapshot.data.data()), size)) - { - ChipLogError(Zcl, "Error reading image file: "); - file.close(); - return Status::Failure; - } - - file.close(); - - outImageSnapshot.imageRes.width = SNAPSHOT_FILE_RES_WIDTH; - outImageSnapshot.imageRes.height = SNAPSHOT_FILE_RES_HEIGHT; - outImageSnapshot.imageCodec = ImageCodecEnum::kJpeg; - - return Status::Success; -} - -CHIP_ERROR -CameraAVStreamManager::PersistentAttributesLoadedCallback() -{ - ChipLogDetail(Zcl, "Persistent attributes loaded"); - - return CHIP_NO_ERROR; -} - -CHIP_ERROR -CameraAVStreamManager::OnTransportAcquireAudioVideoStreams(uint16_t audioStreamID, uint16_t videoStreamID) -{ - ChipLogDetail(Zcl, "Transport acquired audio/video streams"); - - return CHIP_NO_ERROR; -} - -CHIP_ERROR -CameraAVStreamManager::OnTransportReleaseAudioVideoStreams(uint16_t audioStreamID, uint16_t videoStreamID) -{ - ChipLogDetail(Zcl, "Transport released audio/video streams"); - - return CHIP_NO_ERROR; -} - -const std::vector & CameraAVStreamManager::GetAllocatedVideoStreams() const -{ - return videoStreamStructs; -} - -const std::vector & CameraAVStreamManager::GetAllocatedAudioStreams() const -{ - return audioStreamStructs; -} - -void CameraAVStreamManager::GetBandwidthForStreams(const Optional> & videoStreamId, - const Optional> & audioStreamId, - uint32_t & outBandwidthbps) -{ - ChipLogDetail(Zcl, "Get bandwidth for streams called"); -} - -void CameraAVStreamManager::InitializeAvailableVideoStreams() -{ - // Example initialization with different codecs - // id, isAllocated, codec, fps - videoStreams.push_back({ 0, false, VideoCodecEnum::kH264, 24 }); - videoStreams.push_back({ 1, false, VideoCodecEnum::kH264, 30 }); - videoStreams.push_back({ 2, false, VideoCodecEnum::kHevc, 30 }); - videoStreams.push_back({ 3, false, VideoCodecEnum::kHevc, 60 }); -} - -void CameraAVStreamManager::InitializeAvailableAudioStreams() -{ - // Example initialization with different codecs - // id, isAllocated, codec, channelCount - audioStreams.push_back({ 0, false, AudioCodecEnum::kOpus, 2 }); - audioStreams.push_back({ 1, false, AudioCodecEnum::kOpus, 2 }); - audioStreams.push_back({ 2, false, AudioCodecEnum::kAacLc, 1 }); - audioStreams.push_back({ 3, false, AudioCodecEnum::kAacLc, 2 }); -} - -void CameraAVStreamManager::InitializeAvailableSnapshotStreams() -{ - // Example initialization with different codecs - // id, isAllocated, codec, quality - snapshotStreams.push_back({ 0, false, ImageCodecEnum::kJpeg, 80 }); - snapshotStreams.push_back({ 1, false, ImageCodecEnum::kJpeg, 90 }); - snapshotStreams.push_back({ 2, false, ImageCodecEnum::kJpeg, 90 }); - snapshotStreams.push_back({ 3, false, ImageCodecEnum::kJpeg, 80 }); -} - -void CameraAVStreamManager::Init() -{ - InitializeAvailableVideoStreams(); - - InitializeAvailableAudioStreams(); - - InitializeAvailableSnapshotStreams(); -} - -void emberAfCameraAvStreamManagementClusterInitCallback(EndpointId endpoint) -{ - VerifyOrReturn(endpoint == 1, // this cluster is only enabled for endpoint 1. - ChipLogError(Zcl, "AV Stream Mgmt cluster delegate is not implemented for endpoint with id %d.", endpoint)); - - VerifyOrReturn(!sCameraAVStreamMgrInstance && !sCameraAVStreamMgmtClusterServerInstance); - - sCameraAVStreamMgrInstance = std::make_unique(); - sCameraAVStreamMgrInstance->Init(); - - BitFlags features; - features.Set(Feature::kSnapshot); - features.Set(Feature::kVideo); - features.Set(Feature::kNightVision); - features.Set(Feature::kImageControl); - features.Set(Feature::kAudio); - features.Set(Feature::kPrivacy); - features.Set(Feature::kSpeaker); - features.Set(Feature::kLocalStorage); - features.Set(Feature::kWatermark); - features.Set(Feature::kOnScreenDisplay); - features.Set(Feature::kHighDynamicRange); - - // Pure optional attributes that aren't covered by a feature flag, or are attested by the server given feature flag settings - BitFlags optionalAttrs; - optionalAttrs.Set(OptionalAttribute::kHardPrivacyModeOn); - optionalAttrs.Set(OptionalAttribute::kNightVisionIllum); - optionalAttrs.Set(OptionalAttribute::kMicrophoneAGCEnabled); - optionalAttrs.Set(OptionalAttribute::kStatusLightEnabled); - optionalAttrs.Set(OptionalAttribute::kStatusLightBrightness); - optionalAttrs.Set(OptionalAttribute::kImageFlipVertical); - optionalAttrs.Set(OptionalAttribute::kImageFlipHorizontal); - optionalAttrs.Set(OptionalAttribute::kImageRotation); - - uint32_t maxConcurrentVideoEncoders = 1; - uint32_t maxEncodedPixelRate = 10000; - VideoSensorParamsStruct sensorParams = { 4608, 2592, 120, Optional(30) }; // Typical numbers for Pi camera. - bool nightVisionUsesInfrared = false; - VideoResolutionStruct minViewport = { 854, 480 }; // Assuming 480p resolution. - std::vector rateDistortionTradeOffPoints = {}; - uint32_t maxContentBufferSize = 1024; - AudioCapabilitiesStruct micCapabilities{}; - AudioCapabilitiesStruct spkrCapabilities{}; - TwoWayTalkSupportTypeEnum twowayTalkSupport = TwoWayTalkSupportTypeEnum::kNotSupported; - std::vector snapshotCapabilities = {}; - uint32_t maxNetworkBandwidth = 64 * 1000 * 1000; // 64 Mbps - std::vector supportedStreamUsages = { StreamUsageEnum::kLiveView, StreamUsageEnum::kRecording }; - std::vector streamUsagePriorities = { StreamUsageEnum::kLiveView, StreamUsageEnum::kRecording }; - - sCameraAVStreamMgmtClusterServerInstance = std::make_unique( - *sCameraAVStreamMgrInstance.get(), endpoint, features, optionalAttrs, maxConcurrentVideoEncoders, maxEncodedPixelRate, - sensorParams, nightVisionUsesInfrared, minViewport, rateDistortionTradeOffPoints, maxContentBufferSize, micCapabilities, - spkrCapabilities, twowayTalkSupport, snapshotCapabilities, maxNetworkBandwidth, supportedStreamUsages, - streamUsagePriorities); - sCameraAVStreamMgmtClusterServerInstance->Init(); -} - -void emberAfCameraAvStreamManagementClusterShutdownCallback(EndpointId endpoint) -{ - sCameraAVStreamMgmtClusterServerInstance = nullptr; - sCameraAVStreamMgrInstance = nullptr; -} diff --git a/examples/all-clusters-app/all-clusters-common/src/chime-instance.cpp b/examples/all-clusters-app/all-clusters-common/src/chime-instance.cpp index 24586f91b93..ca692bc636f 100644 --- a/examples/all-clusters-app/all-clusters-common/src/chime-instance.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/chime-instance.cpp @@ -58,7 +58,7 @@ CHIP_ERROR ChimeCommandDelegate::GetChimeIDByIndex(uint8_t chimeIndex, uint8_t & return CHIP_NO_ERROR; } -Status ChimeCommandDelegate::PlayChimeSound() +Status ChimeCommandDelegate::PlayChimeSound(uint8_t chimeID) { return Status::Success; } @@ -67,7 +67,7 @@ static ChimeServer gChimeClusterServerInstance = ChimeServer(EndpointId(1), Chim void emberAfChimeClusterInitCallback(EndpointId endpoint) { - gChimeClusterServerInstance.Init(); + TEMPORARY_RETURN_IGNORED gChimeClusterServerInstance.Init(); } void emberAfChimeClusterShutdownCallback(EndpointId endpoint) {} diff --git a/examples/all-clusters-app/all-clusters-common/src/concentration-measurement-instances.cpp b/examples/all-clusters-app/all-clusters-common/src/concentration-measurement-instances.cpp index 3fa642bd8fa..f56b47a2c40 100644 --- a/examples/all-clusters-app/all-clusters-common/src/concentration-measurement-instances.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/concentration-measurement-instances.cpp @@ -68,152 +68,155 @@ static Instance gFormaldehydeConcentrationMeasurementInstance = void emberAfCarbonDioxideConcentrationMeasurementClusterInitCallback(EndpointId endpoint) { - gCarbonDioxideConcentrationMeasurementInstance.Init(); - - gCarbonDioxideConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - gCarbonDioxideConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - gCarbonDioxideConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); - gCarbonDioxideConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - gCarbonDioxideConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - gCarbonDioxideConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - gCarbonDioxideConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - gCarbonDioxideConcentrationMeasurementInstance.SetUncertainty(0.0f); - gCarbonDioxideConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED gCarbonDioxideConcentrationMeasurementInstance.Init(); + + TEMPORARY_RETURN_IGNORED gCarbonDioxideConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED gCarbonDioxideConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED gCarbonDioxideConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(2.0f)); + TEMPORARY_RETURN_IGNORED gCarbonDioxideConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gCarbonDioxideConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gCarbonDioxideConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gCarbonDioxideConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gCarbonDioxideConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED gCarbonDioxideConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); } void emberAfCarbonMonoxideConcentrationMeasurementClusterInitCallback(EndpointId endpoint) { - gCarbonMonoxideConcentrationMeasurementInstance.Init(); - - gCarbonMonoxideConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - gCarbonMonoxideConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - gCarbonMonoxideConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); - gCarbonMonoxideConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - gCarbonMonoxideConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - gCarbonMonoxideConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - gCarbonMonoxideConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - gCarbonMonoxideConcentrationMeasurementInstance.SetUncertainty(0.0f); - gCarbonMonoxideConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED gCarbonMonoxideConcentrationMeasurementInstance.Init(); + + TEMPORARY_RETURN_IGNORED gCarbonMonoxideConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED gCarbonMonoxideConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED gCarbonMonoxideConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gCarbonMonoxideConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gCarbonMonoxideConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gCarbonMonoxideConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gCarbonMonoxideConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gCarbonMonoxideConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED gCarbonMonoxideConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); } void emberAfNitrogenDioxideConcentrationMeasurementClusterInitCallback(EndpointId endpoint) { - gNitrogenDioxideConcentrationMeasurementInstance.Init(); - - gNitrogenDioxideConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - gNitrogenDioxideConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - gNitrogenDioxideConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); - gNitrogenDioxideConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - gNitrogenDioxideConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - gNitrogenDioxideConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - gNitrogenDioxideConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - gNitrogenDioxideConcentrationMeasurementInstance.SetUncertainty(0.0f); - gNitrogenDioxideConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED gNitrogenDioxideConcentrationMeasurementInstance.Init(); + + TEMPORARY_RETURN_IGNORED gNitrogenDioxideConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED gNitrogenDioxideConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED gNitrogenDioxideConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gNitrogenDioxideConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gNitrogenDioxideConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gNitrogenDioxideConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gNitrogenDioxideConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gNitrogenDioxideConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED gNitrogenDioxideConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); } void emberAfPm1ConcentrationMeasurementClusterInitCallback(EndpointId endpoint) { - gPm1ConcentrationMeasurementInstance.Init(); - - gPm1ConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - gPm1ConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - gPm1ConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); - gPm1ConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - gPm1ConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - gPm1ConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - gPm1ConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - gPm1ConcentrationMeasurementInstance.SetUncertainty(0.0f); - gPm1ConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED gPm1ConcentrationMeasurementInstance.Init(); + + TEMPORARY_RETURN_IGNORED gPm1ConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED gPm1ConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED gPm1ConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gPm1ConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gPm1ConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gPm1ConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gPm1ConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gPm1ConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED gPm1ConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); } void emberAfPm10ConcentrationMeasurementClusterInitCallback(EndpointId endpoint) { - gPm10ConcentrationMeasurementInstance.Init(); - - gPm10ConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - gPm10ConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - gPm10ConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); - gPm10ConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - gPm10ConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - gPm10ConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - gPm10ConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - gPm10ConcentrationMeasurementInstance.SetUncertainty(0.0f); - gPm10ConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED gPm10ConcentrationMeasurementInstance.Init(); + + TEMPORARY_RETURN_IGNORED gPm10ConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED gPm10ConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED gPm10ConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gPm10ConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gPm10ConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gPm10ConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gPm10ConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gPm10ConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED gPm10ConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); } void emberAfPm25ConcentrationMeasurementClusterInitCallback(EndpointId endpoint) { - gPm25ConcentrationMeasurementInstance.Init(); - - gPm25ConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - gPm25ConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - gPm25ConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); - gPm25ConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - gPm25ConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - gPm25ConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - gPm25ConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - gPm25ConcentrationMeasurementInstance.SetUncertainty(0.0f); - gPm25ConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED gPm25ConcentrationMeasurementInstance.Init(); + + TEMPORARY_RETURN_IGNORED gPm25ConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED gPm25ConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED gPm25ConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gPm25ConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gPm25ConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gPm25ConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gPm25ConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gPm25ConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED gPm25ConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); } void emberAfRadonConcentrationMeasurementClusterInitCallback(EndpointId endpoint) { - gRadonConcentrationMeasurementInstance.Init(); - - gRadonConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - gRadonConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - gRadonConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); - gRadonConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - gRadonConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - gRadonConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - gRadonConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - gRadonConcentrationMeasurementInstance.SetUncertainty(0.0f); - gRadonConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED gRadonConcentrationMeasurementInstance.Init(); + + TEMPORARY_RETURN_IGNORED gRadonConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED gRadonConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED gRadonConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gRadonConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gRadonConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gRadonConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gRadonConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gRadonConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED gRadonConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); } void emberAfTotalVolatileOrganicCompoundsConcentrationMeasurementClusterInitCallback(EndpointId endpoint) { - gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.Init(); - - gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); - gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetUncertainty(0.0f); - gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.Init(); + + TEMPORARY_RETURN_IGNORED gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetMaxMeasuredValue( + MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetPeakMeasuredValue( + MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetAverageMeasuredValue( + MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED gTotalVolatileOrganicCompoundsConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); } void emberAfOzoneConcentrationMeasurementClusterInitCallback(EndpointId endpoint) { - gOzoneConcentrationMeasurementInstance.Init(); - - gOzoneConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - gOzoneConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - gOzoneConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); - gOzoneConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - gOzoneConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - gOzoneConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - gOzoneConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - gOzoneConcentrationMeasurementInstance.SetUncertainty(0.0f); - gOzoneConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED gOzoneConcentrationMeasurementInstance.Init(); + + TEMPORARY_RETURN_IGNORED gOzoneConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED gOzoneConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED gOzoneConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gOzoneConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gOzoneConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gOzoneConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gOzoneConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gOzoneConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED gOzoneConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); } void emberAfFormaldehydeConcentrationMeasurementClusterInitCallback(EndpointId endpoint) { - gFormaldehydeConcentrationMeasurementInstance.Init(); - - gFormaldehydeConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); - gFormaldehydeConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); - gFormaldehydeConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); - gFormaldehydeConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); - gFormaldehydeConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); - gFormaldehydeConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); - gFormaldehydeConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); - gFormaldehydeConcentrationMeasurementInstance.SetUncertainty(0.0f); - gFormaldehydeConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); + TEMPORARY_RETURN_IGNORED gFormaldehydeConcentrationMeasurementInstance.Init(); + + TEMPORARY_RETURN_IGNORED gFormaldehydeConcentrationMeasurementInstance.SetMinMeasuredValue(MakeNullable(0.0f)); + TEMPORARY_RETURN_IGNORED gFormaldehydeConcentrationMeasurementInstance.SetMaxMeasuredValue(MakeNullable(1000.0f)); + TEMPORARY_RETURN_IGNORED gFormaldehydeConcentrationMeasurementInstance.SetMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gFormaldehydeConcentrationMeasurementInstance.SetPeakMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gFormaldehydeConcentrationMeasurementInstance.SetPeakMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gFormaldehydeConcentrationMeasurementInstance.SetAverageMeasuredValue(MakeNullable(1.0f)); + TEMPORARY_RETURN_IGNORED gFormaldehydeConcentrationMeasurementInstance.SetAverageMeasuredValueWindow(320); + TEMPORARY_RETURN_IGNORED gFormaldehydeConcentrationMeasurementInstance.SetUncertainty(0.0f); + TEMPORARY_RETURN_IGNORED gFormaldehydeConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow); } void emberAfCarbonDioxideConcentrationMeasurementClusterShutdownCallback(EndpointId endpoint) {} diff --git a/examples/all-clusters-app/all-clusters-common/src/dishwasher-mode.cpp b/examples/all-clusters-app/all-clusters-common/src/dishwasher-mode.cpp index 1435435bd7e..8015aaeb24e 100644 --- a/examples/all-clusters-app/all-clusters-common/src/dishwasher-mode.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/dishwasher-mode.cpp @@ -101,7 +101,7 @@ void emberAfDishwasherModeClusterInitCallback(chip::EndpointId endpointId) VerifyOrDie(gDishwasherModeDelegate == nullptr && gDishwasherModeInstance == nullptr); gDishwasherModeDelegate = new DishwasherMode::DishwasherModeDelegate; gDishwasherModeInstance = new ModeBase::Instance(gDishwasherModeDelegate, 0x1, DishwasherMode::Id, 0); - gDishwasherModeInstance->Init(); + TEMPORARY_RETURN_IGNORED gDishwasherModeInstance->Init(); } void emberAfDishwasherModeClusterShutdownCallback(chip::EndpointId endpointId) diff --git a/examples/all-clusters-app/all-clusters-common/src/energy-preference-delegate.cpp b/examples/all-clusters-app/all-clusters-common/src/energy-preference-delegate.cpp index cfdaac5c4d9..a5b3e30ca1f 100644 --- a/examples/all-clusters-app/all-clusters-common/src/energy-preference-delegate.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/energy-preference-delegate.cpp @@ -88,7 +88,7 @@ EPrefDelegate::GetEnergyBalanceAtIndex(chip::EndpointId aEndpoint, size_t aIndex aOutStep = gsEnergyBalances[aIndex].step; if (gsEnergyBalances[aIndex].label.HasValue()) { - chip::CopyCharSpanToMutableCharSpan(gsEnergyBalances[aIndex].label.Value(), aOutLabel.Value()); + TEMPORARY_RETURN_IGNORED chip::CopyCharSpanToMutableCharSpan(gsEnergyBalances[aIndex].label.Value(), aOutLabel.Value()); } else { @@ -122,7 +122,7 @@ EPrefDelegate::GetLowPowerModeSensitivityAtIndex(chip::EndpointId aEndpoint, siz aOutStep = gsPowerBalances[aIndex].step; if (gsPowerBalances[aIndex].label.HasValue()) { - chip::CopyCharSpanToMutableCharSpan(gsPowerBalances[aIndex].label.Value(), aOutLabel.Value()); + TEMPORARY_RETURN_IGNORED chip::CopyCharSpanToMutableCharSpan(gsPowerBalances[aIndex].label.Value(), aOutLabel.Value()); } else { diff --git a/examples/all-clusters-app/all-clusters-common/src/laundry-washer-mode.cpp b/examples/all-clusters-app/all-clusters-common/src/laundry-washer-mode.cpp index b170be3646a..59de89f9902 100644 --- a/examples/all-clusters-app/all-clusters-common/src/laundry-washer-mode.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/laundry-washer-mode.cpp @@ -100,7 +100,7 @@ void emberAfLaundryWasherModeClusterInitCallback(chip::EndpointId endpointId) VerifyOrDie(gLaundryWasherModeDelegate == nullptr && gLaundryWasherModeInstance == nullptr); gLaundryWasherModeDelegate = new LaundryWasherMode::LaundryWasherModeDelegate; gLaundryWasherModeInstance = new ModeBase::Instance(gLaundryWasherModeDelegate, 0x1, LaundryWasherMode::Id, 0); - gLaundryWasherModeInstance->Init(); + TEMPORARY_RETURN_IGNORED gLaundryWasherModeInstance->Init(); } void emberAfLaundryWasherModeClusterShutdownCallback(chip::EndpointId endpointId) diff --git a/examples/all-clusters-app/all-clusters-common/src/microwave-oven-mode.cpp b/examples/all-clusters-app/all-clusters-common/src/microwave-oven-mode.cpp index d871f0baa76..fa11a2983b9 100644 --- a/examples/all-clusters-app/all-clusters-common/src/microwave-oven-mode.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/microwave-oven-mode.cpp @@ -101,7 +101,7 @@ void emberAfMicrowaveOvenModeClusterInitCallback(chip::EndpointId endpointId) VerifyOrDie(gMicrowaveOvenModeDelegate == nullptr && gMicrowaveOvenModeInstance == nullptr); gMicrowaveOvenModeDelegate = new MicrowaveOvenMode::ExampleMicrowaveOvenModeDelegate; gMicrowaveOvenModeInstance = new ModeBase::Instance(gMicrowaveOvenModeDelegate, endpointId, MicrowaveOvenMode::Id, 0); - gMicrowaveOvenModeInstance->Init(); + TEMPORARY_RETURN_IGNORED gMicrowaveOvenModeInstance->Init(); } void emberAfMicrowaveOvenModeClusterShutdownCallback(chip::EndpointId endpointId) diff --git a/examples/all-clusters-app/all-clusters-common/src/occupancy-sensing-stub.cpp b/examples/all-clusters-app/all-clusters-common/src/occupancy-sensing-stub.cpp index 41d3d1fabfe..7fdb4ac7164 100644 --- a/examples/all-clusters-app/all-clusters-common/src/occupancy-sensing-stub.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/occupancy-sensing-stub.cpp @@ -62,11 +62,11 @@ void emberAfOccupancySensingClusterInitCallback(EndpointId endpointId) if (gOccupancySensingClusterInstances[epIndex]) { - gOccupancySensingClusterInstances[epIndex]->Init(); + TEMPORARY_RETURN_IGNORED gOccupancySensingClusterInstances[epIndex]->Init(); - SetHoldTimeLimits(endpointId, holdTimeLimits); + TEMPORARY_RETURN_IGNORED SetHoldTimeLimits(endpointId, holdTimeLimits); - SetHoldTime(endpointId, holdTime); + TEMPORARY_RETURN_IGNORED SetHoldTime(endpointId, holdTime); } } else diff --git a/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp b/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp index e2a1be53e96..c2b0bdbe909 100644 --- a/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp @@ -211,9 +211,10 @@ void emberAfOperationalStateClusterInitCallback(chip::EndpointId endpointId) EndpointId operationalStateEndpoint = 0x01; gOperationalStateInstance = new OperationalState::Instance(gOperationalStateDelegate, operationalStateEndpoint); - gOperationalStateInstance->SetOperationalState(to_underlying(OperationalState::OperationalStateEnum::kStopped)); + TEMPORARY_RETURN_IGNORED gOperationalStateInstance->SetOperationalState( + to_underlying(OperationalState::OperationalStateEnum::kStopped)); - gOperationalStateInstance->Init(); + TEMPORARY_RETURN_IGNORED gOperationalStateInstance->Init(); } void emberAfOperationalStateClusterShutdownCallback(chip::EndpointId endpointId) diff --git a/examples/all-clusters-app/all-clusters-common/src/oven-modes.cpp b/examples/all-clusters-app/all-clusters-common/src/oven-modes.cpp index cfbc2febbd2..4f939721294 100644 --- a/examples/all-clusters-app/all-clusters-common/src/oven-modes.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/oven-modes.cpp @@ -102,7 +102,7 @@ void emberAfOvenModeClusterInitCallback(chip::EndpointId endpointId) VerifyOrDie(gOvenModeDelegate == nullptr && gOvenModeInstance == nullptr); gOvenModeDelegate = new OvenMode::OvenModeDelegate; gOvenModeInstance = new ModeBase::Instance(gOvenModeDelegate, 0x1, OvenMode::Id, 0x0); - gOvenModeInstance->Init(); + TEMPORARY_RETURN_IGNORED gOvenModeInstance->Init(); } void emberAfOvenModeClusterShutdownCallback(chip::EndpointId endpointId) diff --git a/examples/all-clusters-app/all-clusters-common/src/oven-operational-state-delegate.cpp b/examples/all-clusters-app/all-clusters-common/src/oven-operational-state-delegate.cpp index 6411a68dbb4..f10f319c180 100644 --- a/examples/all-clusters-app/all-clusters-common/src/oven-operational-state-delegate.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/oven-operational-state-delegate.cpp @@ -54,9 +54,10 @@ void emberAfOvenCavityOperationalStateClusterInitCallback(chip::EndpointId endpo gOvenCavityOperationalStateInstance = new OvenCavityOperationalState::Instance(gOvenCavityOperationalStateDelegate, operationalStateEndpoint); - gOvenCavityOperationalStateInstance->SetOperationalState(to_underlying(OperationalState::OperationalStateEnum::kStopped)); + TEMPORARY_RETURN_IGNORED gOvenCavityOperationalStateInstance->SetOperationalState( + to_underlying(OperationalState::OperationalStateEnum::kStopped)); - gOvenCavityOperationalStateInstance->Init(); + TEMPORARY_RETURN_IGNORED gOvenCavityOperationalStateInstance->Init(); } void emberAfOvenCavityOperationalStateClusterShutdownCallback(chip::EndpointId endpointId) diff --git a/examples/all-clusters-app/all-clusters-common/src/push-av-stream-transport-delegate-impl.cpp b/examples/all-clusters-app/all-clusters-common/src/push-av-stream-transport-delegate-impl.cpp deleted file mode 100644 index f524606c19e..00000000000 --- a/examples/all-clusters-app/all-clusters-common/src/push-av-stream-transport-delegate-impl.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * - * Copyright (c) 2025 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 -#include - -using namespace chip; -using namespace chip::app; -using namespace chip::app::DataModel; -using namespace chip::app::Clusters; -using namespace chip::app::Clusters::PushAvStreamTransport; -using chip::Protocols::InteractionModel::Status; - -Protocols::InteractionModel::Status -PushAvStreamTransportManager::AllocatePushTransport(const TransportOptionsStruct & transportOptions, const uint16_t connectionID, - FabricIndex accessingFabricIndex) -{ - PushAvStream stream{ connectionID, transportOptions, TransportStatusEnum::kInactive, PushAvStreamTransportStatusEnum::kIdle }; - - /*Store the allocated stream persistently*/ - pushavStreams.push_back(stream); - - return Status::Success; -} - -Protocols::InteractionModel::Status PushAvStreamTransportManager::DeallocatePushTransport(const uint16_t connectionID) -{ - pushavStreams.erase(std::remove_if(pushavStreams.begin(), pushavStreams.end(), - [connectionID](const PushAvStream & stream) { return stream.id == connectionID; }), - pushavStreams.end()); - ChipLogProgress(Zcl, "Deallocated Push AV Stream with ID: %d", connectionID); - return Status::Success; -} - -Protocols::InteractionModel::Status -PushAvStreamTransportManager::ModifyPushTransport(const uint16_t connectionID, const TransportOptionsStorage transportOptions) -{ - for (PushAvStream & stream : pushavStreams) - { - if (stream.id == connectionID) - { - ChipLogProgress(Zcl, "Modified Push AV Stream with ID: %d", connectionID); - return Status::Success; - } - } - ChipLogError(Zcl, "Allocated Push AV Stream with ID: %d not found", connectionID); - return Status::NotFound; -} - -Protocols::InteractionModel::Status PushAvStreamTransportManager::SetTransportStatus(const std::vector connectionIDList, - TransportStatusEnum transportStatus) -{ - for (PushAvStream & stream : pushavStreams) - { - for (uint16_t connectionID : connectionIDList) - { - if (stream.id == connectionID) - { - stream.transportStatus = transportStatus; - ChipLogProgress(Zcl, "Set Transport Status for Push AV Stream with ID: %d", connectionID); - } - } - } - return Status::Success; -} - -Protocols::InteractionModel::Status PushAvStreamTransportManager::ManuallyTriggerTransport( - const uint16_t connectionID, TriggerActivationReasonEnum activationReason, - const Optional & timeControl) -{ - // TODO: Validates the requested stream usage against the camera's resource management and stream priority policies. - for (PushAvStream & stream : pushavStreams) - { - if (stream.id == connectionID) - { - stream.connectionStatus = PushAvStreamTransportStatusEnum::kBusy; - ChipLogProgress(Zcl, "Transport triggered for Push AV Stream with ID: %d", connectionID); - } - } - return Status::Success; -} - -bool PushAvStreamTransportManager::ValidateStreamUsage(StreamUsageEnum streamUsage) -{ - return true; -} - -bool PushAvStreamTransportManager::ValidateSegmentDuration(uint16_t segmentDuration, - const Optional> & videoStreamId) -{ - return true; -} - -Protocols::InteractionModel::Status -PushAvStreamTransportManager::ValidateBandwidthLimit(StreamUsageEnum streamUsage, - const Optional> & videoStreamId, - const Optional> & audioStreamId) -{ - // TODO: Validates the requested stream usage against the camera's resource management. - // Returning Status::Success to pass through checks in the Server Implementation. - return Status::Success; -} - -Protocols::InteractionModel::Status PushAvStreamTransportManager::SelectVideoStream(StreamUsageEnum streamUsage, - uint16_t & videoStreamId) -{ - // TODO: Select and Assign videoStreamID from the allocated videoStreams - // Returning Status::Success to pass through checks in the Server Implementation. - return Status::Success; -} - -Protocols::InteractionModel::Status PushAvStreamTransportManager::SelectAudioStream(StreamUsageEnum streamUsage, - uint16_t & audioStreamId) -{ - // TODO: Select and Assign audioStreamID from the allocated audioStreams - // Returning Status::Success to pass through checks in the Server Implementation. - return Status::Success; -} - -Protocols::InteractionModel::Status PushAvStreamTransportManager::SetVideoStream(uint16_t videoStreamId) -{ - // TODO: Validate videoStreamID from the allocated videoStreams - // Returning Status::Success to pass through checks in the Server Implementation. - return Status::Success; -} - -Protocols::InteractionModel::Status PushAvStreamTransportManager::SetAudioStream(uint16_t audioStreamId) -{ - // TODO: Validate audioStreamID from the allocated audioStreams - // Returning Status::Success to pass through checks in the Server Implementation. - return Status::Success; -} - -Protocols::InteractionModel::Status PushAvStreamTransportManager::ValidateZoneId(uint16_t zoneId) -{ - // TODO: Validate zoneId from the allocated zones - // Returning Status::Success to pass through checks in the Server Implementation. - return Status::Success; -} - -bool PushAvStreamTransportManager::ValidateMotionZoneListSize(size_t zoneListSize) -{ - // TODO: Validate motion zone size - // Returning true to pass through checks in the Server Implementation. - return true; -} - -PushAvStreamTransportStatusEnum PushAvStreamTransportManager::GetTransportBusyStatus(const uint16_t connectionID) -{ - for (PushAvStream & stream : pushavStreams) - { - if (stream.id == connectionID) - { - return stream.connectionStatus; - } - } - return PushAvStreamTransportStatusEnum::kUnknown; -} - -void PushAvStreamTransportManager::OnAttributeChanged(AttributeId attributeId) -{ - ChipLogProgress(Zcl, "Attribute changed for AttributeId = " ChipLogFormatMEI, ChipLogValueMEI(attributeId)); -} - -void PushAvStreamTransportManager::Init() -{ - ChipLogProgress(Zcl, "Push AV Stream Transport Initialized"); -} -CHIP_ERROR -PushAvStreamTransportManager::LoadCurrentConnections(std::vector & currentConnections) -{ - ChipLogProgress(Zcl, "Push AV Current Connections loaded"); - - return CHIP_NO_ERROR; -} - -CHIP_ERROR -PushAvStreamTransportManager::PersistentAttributesLoadedCallback() -{ - ChipLogProgress(Zcl, "Push AV Stream Transport Persistent attributes loaded"); - - return CHIP_NO_ERROR; -} - -CHIP_ERROR PushAvStreamTransportManager::IsHardPrivacyModeActive(bool & isActive) -{ - isActive = false; - return CHIP_NO_ERROR; -} - -CHIP_ERROR PushAvStreamTransportManager::IsSoftRecordingPrivacyModeActive(bool & isActive) -{ - isActive = false; - return CHIP_NO_ERROR; -} - -CHIP_ERROR PushAvStreamTransportManager::IsSoftLivestreamPrivacyModeActive(bool & isActive) -{ - isActive = false; - return CHIP_NO_ERROR; -} diff --git a/examples/all-clusters-app/all-clusters-common/src/resource-monitoring-delegates.cpp b/examples/all-clusters-app/all-clusters-common/src/resource-monitoring-delegates.cpp index e6753f6de1f..a7667163529 100644 --- a/examples/all-clusters-app/all-clusters-common/src/resource-monitoring-delegates.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/resource-monitoring-delegates.cpp @@ -119,7 +119,7 @@ void emberAfActivatedCarbonFilterMonitoringClusterInitCallback(chip::EndpointId gActivatedCarbonFilterInstance = new ResourceMonitoring::Instance( gActivatedCarbonFilterDelegate, endpoint, ActivatedCarbonFilterMonitoring::Id, static_cast(gActivatedCarbonFeatureMap.to_ulong()), ResourceMonitoring::DegradationDirectionEnum::kDown, true); - gActivatedCarbonFilterInstance->Init(); + TEMPORARY_RETURN_IGNORED gActivatedCarbonFilterInstance->Init(); } void emberAfHepaFilterMonitoringClusterInitCallback(chip::EndpointId endpoint) @@ -130,7 +130,7 @@ void emberAfHepaFilterMonitoringClusterInitCallback(chip::EndpointId endpoint) gHepaFilterInstance = new ResourceMonitoring::Instance(gHepaFilterDelegate, endpoint, HepaFilterMonitoring::Id, static_cast(gHepaFilterFeatureMap.to_ulong()), ResourceMonitoring::DegradationDirectionEnum::kDown, true); - gHepaFilterInstance->Init(); + TEMPORARY_RETURN_IGNORED gHepaFilterInstance->Init(); } void emberAfActivatedCarbonFilterMonitoringClusterShutdownCallback(chip::EndpointId endpoint) @@ -154,23 +154,23 @@ CHIP_ERROR ImmutableReplacementProductListManager::Next(ReplacementProductStruct { case 0: { item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kUpc); - item.SetProductIdentifierValue(CharSpan::fromCharString("111112222233")); + TEMPORARY_RETURN_IGNORED item.SetProductIdentifierValue(CharSpan::fromCharString("111112222233")); break; case 1: item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kGtin8); - item.SetProductIdentifierValue(CharSpan::fromCharString("gtin8xxx")); + TEMPORARY_RETURN_IGNORED item.SetProductIdentifierValue(CharSpan::fromCharString("gtin8xxx")); break; case 2: item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kEan); - item.SetProductIdentifierValue(CharSpan::fromCharString("4444455555666")); + TEMPORARY_RETURN_IGNORED item.SetProductIdentifierValue(CharSpan::fromCharString("4444455555666")); break; case 3: item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kGtin14); - item.SetProductIdentifierValue(CharSpan::fromCharString("gtin14xxxxxxxx")); + TEMPORARY_RETURN_IGNORED item.SetProductIdentifierValue(CharSpan::fromCharString("gtin14xxxxxxxx")); break; case 4: item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kOem); - item.SetProductIdentifierValue(CharSpan::fromCharString("oem20xxxxxxxxxxxxxxx")); + TEMPORARY_RETURN_IGNORED item.SetProductIdentifierValue(CharSpan::fromCharString("oem20xxxxxxxxxxxxxxx")); break; default: return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; diff --git a/examples/all-clusters-app/all-clusters-common/src/rvc-modes.cpp b/examples/all-clusters-app/all-clusters-common/src/rvc-modes.cpp index 4430aec24c0..b18386fbdcb 100644 --- a/examples/all-clusters-app/all-clusters-common/src/rvc-modes.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/rvc-modes.cpp @@ -56,11 +56,13 @@ void RvcRunModeDelegate::HandleChangeToMode(uint8_t NewMode, ModeBase::Commands: auto rvcOpStateInstance = RvcOperationalState::GetRvcOperationalStateInstance(); if (NewMode == RvcRunMode::ModeIdle) { - rvcOpStateInstance->SetOperationalState(to_underlying(OperationalState::OperationalStateEnum::kStopped)); + TEMPORARY_RETURN_IGNORED rvcOpStateInstance->SetOperationalState( + to_underlying(OperationalState::OperationalStateEnum::kStopped)); } else { - rvcOpStateInstance->SetOperationalState(to_underlying(OperationalState::OperationalStateEnum::kRunning)); + TEMPORARY_RETURN_IGNORED rvcOpStateInstance->SetOperationalState( + to_underlying(OperationalState::OperationalStateEnum::kRunning)); } response.status = to_underlying(ModeBase::StatusCode::kSuccess); @@ -129,7 +131,7 @@ void emberAfRvcRunModeClusterInitCallback(chip::EndpointId endpointId) gRvcRunModeDelegate = new RvcRunMode::RvcRunModeDelegate; gRvcRunModeInstance = new ModeBase::Instance(gRvcRunModeDelegate, 0x1, RvcRunMode::Id, chip::to_underlying(RvcRunMode::Feature::kDirectModeChange)); - gRvcRunModeInstance->Init(); + TEMPORARY_RETURN_IGNORED gRvcRunModeInstance->Init(); } void emberAfRvcRunModeClusterShutdownCallback(chip::EndpointId endpointId) @@ -231,7 +233,7 @@ void emberAfRvcCleanModeClusterInitCallback(chip::EndpointId endpointId) gRvcCleanModeDelegate = new RvcCleanMode::RvcCleanModeDelegate; gRvcCleanModeInstance = new ModeBase::Instance(gRvcCleanModeDelegate, 0x1, RvcCleanMode::Id, chip::to_underlying(RvcCleanMode::Feature::kDirectModeChange)); - gRvcCleanModeInstance->Init(); + TEMPORARY_RETURN_IGNORED gRvcCleanModeInstance->Init(); } void emberAfRvcCleanModeClusterShutdownCallback(chip::EndpointId endpointId) diff --git a/examples/all-clusters-app/all-clusters-common/src/rvc-operational-state-delegate-impl.cpp b/examples/all-clusters-app/all-clusters-common/src/rvc-operational-state-delegate-impl.cpp index f7e6e02f95a..8329038002a 100644 --- a/examples/all-clusters-app/all-clusters-common/src/rvc-operational-state-delegate-impl.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/rvc-operational-state-delegate-impl.cpp @@ -115,9 +115,10 @@ void emberAfRvcOperationalStateClusterInitCallback(chip::EndpointId endpointId) EndpointId operationalStateEndpoint = 0x01; gRvcOperationalStateInstance = new RvcOperationalState::Instance(gRvcOperationalStateDelegate, operationalStateEndpoint); - gRvcOperationalStateInstance->SetOperationalState(to_underlying(OperationalState::OperationalStateEnum::kStopped)); + TEMPORARY_RETURN_IGNORED gRvcOperationalStateInstance->SetOperationalState( + to_underlying(OperationalState::OperationalStateEnum::kStopped)); - gRvcOperationalStateInstance->Init(); + TEMPORARY_RETURN_IGNORED gRvcOperationalStateInstance->Init(); } void emberAfRvcOperationalStateClusterShutdownCallback(chip::EndpointId endpointId) diff --git a/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp b/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp index 88c85f71fc3..1690ee3caac 100644 --- a/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp @@ -48,7 +48,8 @@ void emberAfPluginSmokeCoAlarmSelfTestRequestCommand(EndpointId endpointId) { ChipLogProgress(Support, "[Smoke-CO-Alarm] => Self test running"); - DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(kSelfTestingTimeoutSec), EndSelfTestingEventHandler, nullptr); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(kSelfTestingTimeoutSec), + EndSelfTestingEventHandler, nullptr); } bool HandleSmokeCOTestEventTrigger(uint64_t eventTrigger) diff --git a/examples/all-clusters-app/all-clusters-common/src/soil-measurement-stub.cpp b/examples/all-clusters-app/all-clusters-common/src/soil-measurement-stub.cpp index 51ec7e1e381..b8ef45922b9 100644 --- a/examples/all-clusters-app/all-clusters-common/src/soil-measurement-stub.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/soil-measurement-stub.cpp @@ -70,7 +70,7 @@ void emberAfSoilMeasurementClusterInitCallback(EndpointId endpoint) } // Set initial measured value to min since all clusters does not perform any actual measurements - gServer.Cluster().SetSoilMoistureMeasuredValue(kDefaultSoilMoistureMeasurementLimits.minMeasuredValue); + TEMPORARY_RETURN_IGNORED gServer.Cluster().SetSoilMoistureMeasuredValue(kDefaultSoilMoistureMeasurementLimits.minMeasuredValue); } void emberAfSoilMeasurementClusterShutdownCallback(EndpointId endpoint) diff --git a/examples/all-clusters-app/all-clusters-common/src/tcc-mode.cpp b/examples/all-clusters-app/all-clusters-common/src/tcc-mode.cpp index 8a7208f3477..b919f7fc58a 100644 --- a/examples/all-clusters-app/all-clusters-common/src/tcc-mode.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/tcc-mode.cpp @@ -95,7 +95,7 @@ void emberAfRefrigeratorAndTemperatureControlledCabinetModeClusterInitCallback(c VerifyOrDie(gTccModeDelegate == nullptr && gTccModeInstance == nullptr); gTccModeDelegate = new RefrigeratorAndTemperatureControlledCabinetMode::TccModeDelegate; gTccModeInstance = new ModeBase::Instance(gTccModeDelegate, 0x1, RefrigeratorAndTemperatureControlledCabinetMode::Id, 0); - gTccModeInstance->Init(); + TEMPORARY_RETURN_IGNORED gTccModeInstance->Init(); } void emberAfRefrigeratorAndTemperatureControlledCabinetModeClusterShutdownCallback(chip::EndpointId endpointId) diff --git a/examples/all-clusters-app/all-clusters-common/src/tls-certificate-management-instance.cpp b/examples/all-clusters-app/all-clusters-common/src/tls-certificate-management-instance.cpp index eb755aeaecd..dd53007e3f0 100644 --- a/examples/all-clusters-app/all-clusters-common/src/tls-certificate-management-instance.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/tls-certificate-management-instance.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -40,13 +40,13 @@ static constexpr uint16_t kMaxIntermediateCerts = 10; struct InlineBufferedRootCert : CertificateTable::BufferedRootCert { - PersistentStore buffer; + PersistenceBuffer buffer; InlineBufferedRootCert() : CertificateTable::BufferedRootCert(buffer) {} }; struct InlineBufferedClientCert : CertificateTable::BufferedClientCert { - PersistentStore buffer; + PersistenceBuffer buffer; InlineBufferedClientCert() : CertificateTable::BufferedClientCert(buffer) {} }; @@ -136,9 +136,6 @@ struct InlineEncodableClientCert : RefEncodableClientCert InlineEncodableClientCert() : RefEncodableClientCert(inlineCertificate) {} }; -static constexpr uint8_t kMaxRootCerts = kMaxRootCertificatesPerFabric; -static constexpr uint8_t kMaxClientCerts = kMaxClientCertificatesPerFabric; - CHIP_ERROR FingerprintMatch(const ByteSpan & fingerprint, const ByteSpan & cert, bool & outMatch) { std::array fingerprintPayload = { 0 }; @@ -188,7 +185,7 @@ CHIP_ERROR TlsCertificateManagementCommandDelegate::RootCertsForFabric(EndpointI VerifyOrReturnError(matterEndpoint == EndpointId(1), CHIP_IM_GLOBAL_STATUS(ConstraintError)); uint8_t numRootCerts; - mCertificateTable.GetRootCertificateCount(fabric, numRootCerts); + ReturnErrorOnFailure(mCertificateTable.GetRootCertificateCount(fabric, numRootCerts)); ScopedMemoryBuffer rootCertificatePayloads; ScopedMemoryBuffer rootCertificates; rootCertificatePayloads.Alloc(numRootCerts); @@ -350,7 +347,7 @@ CHIP_ERROR TlsCertificateManagementCommandDelegate::ClientCertsForFabric(Endpoin VerifyOrReturnError(matterEndpoint == EndpointId(1), CHIP_IM_GLOBAL_STATUS(ConstraintError)); uint8_t numClientCerts; - mCertificateTable.GetClientCertificateCount(fabric, numClientCerts); + ReturnErrorOnFailure(mCertificateTable.GetClientCertificateCount(fabric, numClientCerts)); UniquePtr certBuffer(New()); ScopedMemoryBuffer clientCertificatePayloads; ScopedMemoryBuffer clientCertificates; @@ -443,17 +440,18 @@ Status TlsCertificateManagementCommandDelegate::RemoveClientCert(EndpointId matt static CertificateTableImpl gCertificateTableInstance; TlsCertificateManagementCommandDelegate TlsCertificateManagementCommandDelegate::instance(gCertificateTableInstance); -static TlsCertificateManagementServer gTlsCertificateManagementClusterServerInstance = TlsCertificateManagementServer( - EndpointId(1), TlsCertificateManagementCommandDelegate::GetInstance(), TlsClientManagementCommandDelegate::GetInstance(), - gCertificateTableInstance, kMaxRootCerts, kMaxClientCerts); -void emberAfTlsCertificateManagementClusterInitCallback(EndpointId matterEndpoint) -{ - gCertificateTableInstance.SetEndpoint(EndpointId(1)); - gTlsCertificateManagementClusterServerInstance.Init(); -} +namespace chip { +namespace app { +namespace Clusters { -void emberAfTlsCertificateManagementClusterShutdownCallback(EndpointId matterEndpoint) +void InitializeTlsCertificateManagement() { - gTlsCertificateManagementClusterServerInstance.Finish(); + MatterTlsCertificateManagementSetDelegate(TlsCertificateManagementCommandDelegate::GetInstance()); + MatterTlsCertificateManagementSetDependencyChecker(TlsClientManagementCommandDelegate::GetInstance()); + MatterTlsCertificateManagementSetCertificateTable(gCertificateTableInstance); } + +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/examples/all-clusters-app/all-clusters-common/src/tls-client-management-instance.cpp b/examples/all-clusters-app/all-clusters-common/src/tls-client-management-instance.cpp index b06115baad8..2f0df52bb9f 100644 --- a/examples/all-clusters-app/all-clusters-common/src/tls-client-management-instance.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/tls-client-management-instance.cpp @@ -19,9 +19,12 @@ #include #include #include -#include +#include +#include #include +#include #include +#include #include #include @@ -37,8 +40,8 @@ using namespace chip::Platform; using namespace chip::TLV; using namespace Protocols::InteractionModel; -using EndpointSerializer = DefaultSerializer; -using InnerIterator = TableEntryDataConvertingIterator; +using EndpointSerializer = DefaultSerializer; +using InnerIterator = TableEntryDataConvertingIterator; namespace { enum class TagEndpoint : uint8_t @@ -67,11 +70,11 @@ static constexpr size_t kTlsEndpointMaxBytes = sizeof(chip::FabricIndex) /* fabricIndex */)); struct BufferedEndpoint { - TlsClientManagementDelegate::EndpointStructType mEndpoint; - PersistentStore mBuffer; + TLSClientManagementDelegate::EndpointStructType mEndpoint; + PersistenceBuffer mBuffer; }; -class GlobalEndpointData : public PersistentData +class GlobalEndpointData : public PersistableData { IncrementingIdHelper mEndpoints; EndpointId mEndpointId = kInvalidEndpointId; @@ -124,16 +127,10 @@ class GlobalEndpointData : public PersistentData return reader.ExitContainer(container); } - CHIP_ERROR Load(PersistentStorageDelegate * storage) override + CHIP_ERROR Load(PersistentStorageDelegate * storage) // NOLINT(bugprone-derived-method-shadowing-base-method) { - CHIP_ERROR err = PersistentData::Load(storage); - VerifyOrReturnError(CHIP_NO_ERROR == err || CHIP_ERROR_NOT_FOUND == err, err); - if (CHIP_ERROR_NOT_FOUND == err) - { - Clear(); - } - - return CHIP_NO_ERROR; + CHIP_ERROR err = PersistableData::Load(storage); + return err.NoErrorIf(CHIP_ERROR_NOT_FOUND); // NOT_FOUND is OK; DataAccessor::Load already called Clear() } CHIP_ERROR GetNextId(FabricIndex fabric, uint16_t & id) @@ -208,25 +205,25 @@ CHIP_ERROR EndpointSerializer::DeserializeId(TLV::TLVReader & reader, TlsEndpoin } template <> -CHIP_ERROR EndpointSerializer::SerializeData(TLV::TLVWriter & writer, const TlsClientManagementDelegate::EndpointStructType & data) +CHIP_ERROR EndpointSerializer::SerializeData(TLV::TLVWriter & writer, const TLSClientManagementDelegate::EndpointStructType & data) { return data.EncodeForRead(writer, TLV::ContextTag(TagEndpoint::kEndpointPayload), data.GetFabricIndex()); } template <> -CHIP_ERROR EndpointSerializer::DeserializeData(TLV::TLVReader & reader, TlsClientManagementDelegate::EndpointStructType & data) +CHIP_ERROR EndpointSerializer::DeserializeData(TLV::TLVReader & reader, TLSClientManagementDelegate::EndpointStructType & data) { ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::ContextTag(TagEndpoint::kEndpointPayload))); return data.Decode(reader); } template <> -void EndpointSerializer::Clear(TlsClientManagementDelegate::EndpointStructType & data) +void EndpointSerializer::Clear(TLSClientManagementDelegate::EndpointStructType & data) { - new (&data) TlsClientManagementDelegate::EndpointStructType(); + new (&data) TLSClientManagementDelegate::EndpointStructType(); } -template class chip::app::Storage::FabricTableImpl; +template class chip::app::Storage::FabricTableImpl; CHIP_ERROR TlsClientManagementCommandDelegate::Init(PersistentStorageDelegate & storage) { @@ -279,7 +276,11 @@ ClusterStatusCode TlsClientManagementCommandDelegate::ProvisionEndpoint( { numInFabric++; auto & endpointStruct = endpoint.mEndpoint; - if (endpointStruct.hostname.data_equal(provisionReq.hostname) && (endpointStruct.port == provisionReq.port)) + // A host/port collision is detected if we are either: + // - provisioning a new endpoint (endpointID is null) + // - updating an existing endpoint, but the colliding endpoint is not the one being updated. + if (endpointStruct.hostname.data_equal(provisionReq.hostname) && (endpointStruct.port == provisionReq.port) && + (provisionReq.endpointID.IsNull() || provisionReq.endpointID.Value() != endpointStruct.endpointID)) { installedCheck = ClusterStatusCode::ClusterSpecificFailure(StatusCodeEnum::kEndpointAlreadyInstalled); return CHIP_ERROR_BAD_REQUEST; @@ -291,7 +292,7 @@ ClusterStatusCode TlsClientManagementCommandDelegate::ProvisionEndpoint( if (provisionReq.endpointID.IsNull()) { - VerifyOrReturnError(numInFabric < mTlsClientManagementServer->GetMaxProvisioned(), + VerifyOrReturnError(numInFabric < mTLSClientManagementCluster->GetMaxProvisioned(), ClusterStatusCode(Status::ResourceExhausted)); EndpointSerializer::Clear(endpoint.mEndpoint); auto & endpointStruct = endpoint.mEndpoint; @@ -395,7 +396,11 @@ void TlsClientManagementCommandDelegate::RemoveFabric(FabricIndex fabric) UniquePtr globalData(New(EndpointId(1))); VerifyOrReturn(globalData); ReturnOnFailure(globalData->Load(mStorage)); - ReturnAndLogOnFailure(globalData->RemoveAll(*mStorage, fabric), Zcl, "Failure clearing TLS endpoint data for fabric"); + + // Not having endpoint data for a fabric is not an error; the fabric may never + // have had TLS endpoints provisioned. + ReturnAndLogOnFailure(globalData->RemoveAll(*mStorage, fabric).NoErrorIf(CHIP_ERROR_NOT_FOUND), Zcl, + "Failure clearing TLS endpoint data for fabric"); } CHIP_ERROR TlsClientManagementCommandDelegate::MutateEndpointReferenceCount(EndpointId matterEndpoint, FabricIndex fabric, @@ -423,16 +428,17 @@ CHIP_ERROR TlsClientManagementCommandDelegate::MutateEndpointReferenceCount(Endp static CertificateTableImpl gCertificateTableInstance; TlsClientManagementCommandDelegate TlsClientManagementCommandDelegate::instance; -static TlsClientManagementServer gTlsClientManagementClusterServerInstance = TlsClientManagementServer( - EndpointId(1), TlsClientManagementCommandDelegate::GetInstance(), gCertificateTableInstance, kMaxProvisionedEndpoints); -void emberAfTlsClientManagementClusterInitCallback(EndpointId matterEndpoint) -{ - gCertificateTableInstance.SetEndpoint(EndpointId(1)); - gTlsClientManagementClusterServerInstance.Init(); -} +namespace chip { +namespace app { +namespace Clusters { -void emberAfTlsClientManagementClusterShutdownCallback(EndpointId matterEndpoint) +void InitializeTlsClientManagement() { - gTlsClientManagementClusterServerInstance.Finish(); + MatterTlsClientManagementSetDelegate(TlsClientManagementCommandDelegate::GetInstance()); + MatterTlsClientManagementSetCertificateTable(gCertificateTableInstance); } + +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/examples/all-clusters-app/ameba/chip_main.cmake b/examples/all-clusters-app/ameba/chip_main.cmake index 63a24daf0eb..898b9826f43 100644 --- a/examples/all-clusters-app/ameba/chip_main.cmake +++ b/examples/all-clusters-app/ameba/chip_main.cmake @@ -157,7 +157,6 @@ list( ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/air-quality-instance.cpp - ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/camera-av-settings-user-level-management-stub.cpp ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/chime-instance.cpp ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/concentration-measurement-instances.cpp ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/energy-preference-delegate.cpp diff --git a/examples/all-clusters-app/ameba/main/chipinterface.cpp b/examples/all-clusters-app/ameba/main/chipinterface.cpp index a53613caff1..8882f9ab9e8 100755 --- a/examples/all-clusters-app/ameba/main/chipinterface.cpp +++ b/examples/all-clusters-app/ameba/main/chipinterface.cpp @@ -132,18 +132,14 @@ static void InitServer(intptr_t context) { // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; + initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(initParams.persistentStorageDelegate); #if CONFIG_ENABLE_AMEBA_TEST_EVENT_TRIGGER static AmebaTestEventTriggerDelegate sTestEventTriggerDelegate{ ByteSpan(sTestEventTriggerEnableKey) }; initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; #endif - static AmebaObserver sAmebaObserver; - initParams.appDelegate = &sAmebaObserver; - - initParams.InitializeStaticResourcesBeforeServerInit(); - initParams.dataModelProvider = CodegenDataModelProviderInstance(initParams.persistentStorageDelegate); - #if CONFIG_ENABLE_AMEBA_CRYPTO ChipLogProgress(DeviceLayer, "platform crypto enabled!"); static chip::AmebaPersistentStorageOperationalKeystore sAmebaPersistentStorageOpKeystore; @@ -151,10 +147,11 @@ static void InitServer(intptr_t context) initParams.operationalKeystore = &sAmebaPersistentStorageOpKeystore; #endif + static AmebaObserver sAmebaObserver; + initParams.appDelegate = &sAmebaObserver; + chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); - // TODO: Use our own DeviceInfoProvider - chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); #if CHIP_ENABLE_AMEBA_TERMS_AND_CONDITION const Optional termsAndConditions = Optional( diff --git a/examples/all-clusters-app/esp32/partitions.csv b/examples/all-clusters-app/esp32/partitions.csv index 530cbadc617..c8b96a645f0 100644 --- a/examples/all-clusters-app/esp32/partitions.csv +++ b/examples/all-clusters-app/esp32/partitions.csv @@ -3,5 +3,9 @@ nvs, data, nvs, , 0xC000, otadata, data, ota, , 0x2000, phy_init, data, phy, , 0x1000, -ota_0, app, ota_0, , 1900K, -ota_1, app, ota_1, , 1900K, +ota_0, app, ota_0, , 3800K, +# This partition table is meant only for all-clusters-app. +# OTA_0 partition size has been increased to fit all features, +# and OTA_1 has been removed. This makes the app non-OTA upgradable. +# Do NOT use this partition table in production builds, +# production images must include an OTA_1 partition. diff --git a/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp b/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp index da94135ca40..c0cdea442e4 100644 --- a/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp +++ b/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp @@ -559,7 +559,7 @@ void AllClustersAppCommandHandler::HandleCommand(intptr_t context) else if (name == "SimulateConfigurationVersionChange") { uint32_t configurationVersion = 0; - ConfigurationMgr().GetConfigurationVersion(configurationVersion); + TEMPORARY_RETURN_IGNORED ConfigurationMgr().GetConfigurationVersion(configurationVersion); configurationVersion++; if (ConfigurationMgr().StoreConfigurationVersion(configurationVersion + 1) != CHIP_NO_ERROR) @@ -592,7 +592,7 @@ void AllClustersAppCommandHandler::HandleCommand(intptr_t context) } else if (name == "UserIntentCommissioningStart") { - Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow(); + TEMPORARY_RETURN_IGNORED Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow(); } else { @@ -616,7 +616,8 @@ void AllClustersAppCommandHandler::OnRebootSignalHandler(BootReasonType bootReas if (ConfigurationMgr().StoreBootReason(static_cast(bootReason)) == CHIP_NO_ERROR) { Server::GetInstance().GenerateShutDownEvent(); - PlatformMgr().ScheduleWork([](intptr_t) { PlatformMgr().StopEventLoopTask(); }); + TEMPORARY_RETURN_IGNORED PlatformMgr().ScheduleWork( + [](intptr_t) { TEMPORARY_RETURN_IGNORED PlatformMgr().StopEventLoopTask(); }); } else { @@ -915,15 +916,18 @@ void AllClustersAppCommandHandler::OnOvenOperationalStateChange(std::string devi OperationalState::Instance * operationalStateInstance = OvenCavityOperationalState::GetOperationalStateInstance(); if (operation == "Start" || operation == "Resume") { - operationalStateInstance->SetOperationalState(to_underlying(OperationalState::OperationalStateEnum::kRunning)); + TEMPORARY_RETURN_IGNORED operationalStateInstance->SetOperationalState( + to_underlying(OperationalState::OperationalStateEnum::kRunning)); } else if (operation == "Pause") { - operationalStateInstance->SetOperationalState(to_underlying(OperationalState::OperationalStateEnum::kPaused)); + TEMPORARY_RETURN_IGNORED operationalStateInstance->SetOperationalState( + to_underlying(OperationalState::OperationalStateEnum::kPaused)); } else if (operation == "Stop") { - operationalStateInstance->SetOperationalState(to_underlying(OperationalState::OperationalStateEnum::kStopped)); + TEMPORARY_RETURN_IGNORED operationalStateInstance->SetOperationalState( + to_underlying(OperationalState::OperationalStateEnum::kStopped)); } else if (operation == "OnFault") { @@ -967,7 +971,7 @@ void AllClustersAppCommandHandler::OnSoilMoistureChange(EndpointId endpointId, D ChipLogDetail(NotSpecified, "Set SoilMoisture value to %u", soilMoisture.Value()); } - SoilMeasurement::SetSoilMoistureMeasuredValue(soilMoisture); + TEMPORARY_RETURN_IGNORED SoilMeasurement::SetSoilMoistureMeasuredValue(soilMoisture); } void AllClustersAppCommandHandler::HandleSetOccupancyChange(EndpointId endpointId, uint8_t newOccupancyValue) @@ -1044,5 +1048,6 @@ void AllClustersCommandDelegate::OnEventCommandReceived(const char * json) return; } - chip::DeviceLayer::PlatformMgr().ScheduleWork(AllClustersAppCommandHandler::HandleCommand, reinterpret_cast(handler)); + TEMPORARY_RETURN_IGNORED chip::DeviceLayer::PlatformMgr().ScheduleWork(AllClustersAppCommandHandler::HandleCommand, + reinterpret_cast(handler)); } diff --git a/examples/all-clusters-app/linux/AppOptions.cpp b/examples/all-clusters-app/linux/AppOptions.cpp index d0dd6250dd4..dcd9d88fdc8 100644 --- a/examples/all-clusters-app/linux/AppOptions.cpp +++ b/examples/all-clusters-app/linux/AppOptions.cpp @@ -67,7 +67,7 @@ struct MockClock : public ClockBase MockClock() : mRealClock(SystemClock()) { Clock::Internal::SetSystemClockForTesting(this); } ~MockClock() { Clock::Internal::SetSystemClockForTesting(&mRealClock); } - void SetUTCTime(Microseconds64 aOverride) { GetOffsetFrom(mRealClock, aOverride, mOffset); } + void SetUTCTime(Microseconds64 aOverride) { TEMPORARY_RETURN_IGNORED GetOffsetFrom(mRealClock, aOverride, mOffset); } Microseconds64 GetMonotonicMicroseconds64() override { return mRealClock.GetMonotonicMicroseconds64(); } Milliseconds64 GetMonotonicMilliseconds64() override { return mRealClock.GetMonotonicMilliseconds64(); } diff --git a/examples/all-clusters-app/linux/BUILD.gn b/examples/all-clusters-app/linux/BUILD.gn index 1bf679b50c0..a868694254d 100644 --- a/examples/all-clusters-app/linux/BUILD.gn +++ b/examples/all-clusters-app/linux/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Project CHIP Authors +# Copyright (c) 2020-2026 Project CHIP Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -34,8 +34,6 @@ source_set("chip-all-clusters-common") { "${chip_root}/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/boolcfg-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/camera-av-settings-user-level-management-stub.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/camera-av-stream-delegate-impl.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/chime-instance.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/concentration-measurement-instances.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/dishwasher-alarm-stub.cpp", @@ -50,7 +48,6 @@ source_set("chip-all-clusters-common") { "${chip_root}/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/oven-modes.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/oven-operational-state-delegate.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/push-av-stream-transport-delegate-impl.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/resource-monitoring-delegates.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/rvc-modes.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/rvc-operational-state-delegate-impl.cpp", diff --git a/examples/all-clusters-app/linux/ButtonEventsSimulator.cpp b/examples/all-clusters-app/linux/ButtonEventsSimulator.cpp index 0122eba4336..2e6e638cbc6 100644 --- a/examples/all-clusters-app/linux/ButtonEventsSimulator.cpp +++ b/examples/all-clusters-app/linux/ButtonEventsSimulator.cpp @@ -196,7 +196,7 @@ void ButtonEventsSimulator::SetState(ButtonEventsSimulator::State newState) void ButtonEventsSimulator::StartTimer(System::Clock::Timeout duration) { - chip::DeviceLayer::SystemLayer().StartTimer(duration, &ButtonEventsSimulator::OnTimerDone, this); + TEMPORARY_RETURN_IGNORED chip::DeviceLayer::SystemLayer().StartTimer(duration, &ButtonEventsSimulator::OnTimerDone, this); } void ButtonEventsSimulator::Next() diff --git a/examples/all-clusters-app/linux/main-common.cpp b/examples/all-clusters-app/linux/main-common.cpp index 6ea446f4ff3..239c629ac91 100644 --- a/examples/all-clusters-app/linux/main-common.cpp +++ b/examples/all-clusters-app/linux/main-common.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2026 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,7 +22,6 @@ #include "WindowCoveringManager.h" #include "air-quality-instance.h" #include "app-common/zap-generated/ids/Clusters.h" -#include "camera-av-settings-user-level-management-instance.h" #include "dishwasher-mode.h" #include "include/diagnostic-logs-provider-delegate-impl.h" #include "include/tv-callbacks.h" @@ -33,7 +32,6 @@ #include "operational-state-delegate-impl.h" #include "oven-modes.h" #include "oven-operational-state-delegate.h" -#include "push-av-stream-transport-delegate-impl.h" #include "resource-monitoring-delegates.h" #include "rvc-modes.h" #include "rvc-operational-state-delegate-impl.h" @@ -51,7 +49,6 @@ #include #include #include -#include #include #include #include @@ -119,7 +116,6 @@ Clusters::TemperatureControl::AppSupportedTemperatureLevelsDelegate sAppSupporte Clusters::ModeSelect::StaticSupportedModesManager sStaticSupportedModesManager; Clusters::ValveConfigurationAndControl::ValveControlDelegate sValveDelegate; Clusters::TimeSynchronization::ExtendedTimeSyncDelegate sTimeSyncDelegate; -Clusters::PushAvStreamTransport::PushAvStreamTransportManager gPushAvStreamTransportManager; // Please refer to https://github.com/CHIP-Specifications/connectedhomeip-spec/blob/master/src/namespaces constexpr const uint8_t kNamespaceCommon = 7; @@ -193,7 +189,7 @@ void ApplicationInit() if ((!path.empty()) and (sChipNamedPipeCommands.Start(path, &sAllClustersCommandDelegate) != CHIP_NO_ERROR)) { ChipLogError(NotSpecified, "Failed to start CHIP NamedPipeCommands"); - sChipNamedPipeCommands.Stop(); + TEMPORARY_RETURN_IGNORED sChipNamedPipeCommands.Stop(); } #ifdef MATTER_DM_PLUGIN_DISHWASHER_ALARM_SERVER @@ -213,20 +209,21 @@ void ApplicationInit() VerifyOrDie(Clusters::UnitLocalization::UnitLocalizationServer::Instance().SetTemperatureUnit( Clusters::UnitLocalization::TempUnitEnum::kFahrenheit) == CHIP_NO_ERROR); - Clusters::PushAvStreamTransport::SetDelegate(chip::EndpointId(1), &gPushAvStreamTransportManager); - Clusters::PushAvStreamTransport::SetTLSClientManagementDelegate(chip::EndpointId(1), - &Clusters::TlsClientManagementCommandDelegate::GetInstance()); - VerifyOrDie(CodegenDataModelProvider::Instance().Registry().Register(gIdentifyCluster1.Registration()) == CHIP_NO_ERROR); VerifyOrDie(CodegenDataModelProvider::Instance().Registry().Register(gIdentifyCluster2.Registration()) == CHIP_NO_ERROR); VerifyOrDie(CodegenDataModelProvider::Instance().Registry().Register(gIdentifyCluster3.Registration()) == CHIP_NO_ERROR); VerifyOrDie(CodegenDataModelProvider::Instance().Registry().Register(gIdentifyCluster4.Registration()) == CHIP_NO_ERROR); - SetTagList(/* endpoint= */ 0, Span(gEp0TagList)); - SetTagList(/* endpoint= */ 1, Span(gEp1TagList)); - SetTagList(/* endpoint= */ 2, Span(gEp2TagList)); - SetTagList(/* endpoint= */ 3, Span(gEp3TagList)); - SetTagList(/* endpoint= */ 4, Span(gEp4TagList)); + TEMPORARY_RETURN_IGNORED SetTagList(/* endpoint= */ 0, + Span(gEp0TagList)); + TEMPORARY_RETURN_IGNORED SetTagList(/* endpoint= */ 1, + Span(gEp1TagList)); + TEMPORARY_RETURN_IGNORED SetTagList(/* endpoint= */ 2, + Span(gEp2TagList)); + TEMPORARY_RETURN_IGNORED SetTagList(/* endpoint= */ 3, + Span(gEp3TagList)); + TEMPORARY_RETURN_IGNORED SetTagList(/* endpoint= */ 4, + Span(gEp4TagList)); } void ApplicationShutdown() diff --git a/examples/all-clusters-app/linux/main.cpp b/examples/all-clusters-app/linux/main.cpp index 2d83c132eec..5736618b620 100644 --- a/examples/all-clusters-app/linux/main.cpp +++ b/examples/all-clusters-app/linux/main.cpp @@ -19,6 +19,8 @@ #include "AppMain.h" #include "AppOptions.h" #include "binding-handler.h" +#include "tls-certificate-management-instance.h" +#include "tls-client-management-instance.h" // Network commissioning namespace { @@ -31,6 +33,11 @@ int main(int argc, char * argv[]) ChipLinuxAppInit(argc, argv, AppOptions::GetOptions(), chip::MakeOptional(kNetworkCommissioningEndpointSecondary)) == 0); VerifyOrDie(InitBindingHandlers() == CHIP_NO_ERROR); + // Initialize TLS Client and Certificate Management delegates before server starts + // This must be called before ChipLinuxAppMainLoop() which initializes the server + chip::app::Clusters::InitializeTlsClientManagement(); + chip::app::Clusters::InitializeTlsCertificateManagement(); + ChipLinuxAppMainLoop(); return 0; diff --git a/examples/all-clusters-app/nxp/rt/rt1060/BUILD.gn b/examples/all-clusters-app/nxp/rt/rt1060/BUILD.gn deleted file mode 100644 index 4faecbd23a4..00000000000 --- a/examples/all-clusters-app/nxp/rt/rt1060/BUILD.gn +++ /dev/null @@ -1,304 +0,0 @@ -# Copyright (c) 2021-2023 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") -import("//build_overrides/chip.gni") -import("//build_overrides/nxp_sdk.gni") -import("//build_overrides/openthread.gni") -import("${chip_root}/src/platform/device.gni") - -#allows to get common NXP SDK gn options -import("${nxp_sdk_build_root}/nxp_sdk.gni") - -# Allows to get various RT gn options -import("${nxp_sdk_build_root}/${nxp_sdk_name}/rt_sdk.gni") - -import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") -import( - "${nxp_sdk_build_root}/${nxp_sdk_name}/${rt_platform}/${rt_platform}.gni") -import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") - -assert(current_os == "freertos") -assert(target_os == "freertos") -assert(nxp_platform == "rt/rt1060") - -declare_args() { - # Allows to enable to ota_provider support - enable_ota_provider = false - - # Allows to connect to a predefine Wi-Fi network at boot - wifi_auto_connect_at_boot = false - wifi_auto_connect_at_boot_ssid = "" - wifi_auto_connect_at_boot_password = "" - - # Setup discriminator as argument - setup_discriminator = 3840 -} - -example_platform_dir = - "${nxp_sdk_matter_support_root}/examples/platform/${nxp_platform}" -common_example_dir = "${chip_root}/examples/platform/nxp/common" - -app_common_folder = "all-clusters-app/all-clusters-common" - -# Create here the SDK instance. -# Particular sources/defines/includes could be added/changed depending on the target application. -rt_sdk("sdk") { - defines = [] - - cflags = [] - public_deps = [] - public_configs = [] - sources = [] - include_dirs = [] - - # Indicate paths to default board files - include_dirs += [ "${example_platform_dir}/board/" ] - - # RT1060 rev A use same pin mux as rev B - # If user needs different pin mux files for rev A and rev B boards, the source and include from below needs to be updated accordingly - if (evkname == "evkmimxrt1060") { - include_dirs += [ "${example_platform_dir}/board/evkbmimxrt1060/" ] - sources += [ "${example_platform_dir}/board/evkbmimxrt1060/pin_mux.c" ] - } else { - include_dirs += [ "${example_platform_dir}/board/${evkname}/" ] - sources += [ "${example_platform_dir}/board/${evkname}/pin_mux.c" ] - } - - if (iw416_transceiver || w8801_transceiver || iwx12_transceiver) { - if (evkname == "evkmimxrt1060") { - include_dirs += [ "${example_platform_dir}/board/evkbmimxrt1060/" ] - sources += - [ "${example_platform_dir}/board/evkbmimxrt1060/sdmmc_config.c" ] - sources += - [ "${example_platform_dir}/board/evkbmimxrt1060/wifi_bt_config.c" ] - } else { - include_dirs += [ "${example_platform_dir}/board/${evkname}/" ] - sources += [ "${example_platform_dir}/board/${evkname}/sdmmc_config.c" ] - sources += [ "${example_platform_dir}/board/${evkname}/wifi_bt_config.c" ] - } - } - - sources += [ "${example_platform_dir}/board/hardware_init.c" ] - sources += [ "${example_platform_dir}/board/clock_config.c" ] - sources += [ "${example_platform_dir}/board/board.c" ] - sources += [ "${example_platform_dir}/board/peripherals.c" ] - - # Indicate the path to CHIPProjectConfig.h - include_dirs += [ "include/config" ] - - # Indicate the default path to FreeRTOSConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/freeRTOS" ] - - # Indicate the default path to OpenThreadConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/openthread" ] - - # For matter with BR feature, increase FreeRTOS heap size - if (chip_enable_wifi && chip_enable_openthread) { - defines += [ "configTOTAL_HEAP_SIZE=(size_t)(170 * 1024)" ] - } - - defines += [ - "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", - ] -} - -# Create the SDK driver instance. -# Particular sources/defines/includes could be added to add other drivers not available in the default sdk driver template -rt1060_sdk_drivers("sdk_driver") { -} - -rt_executable("all_cluster_app") { - output_name = "chip-rt1060-all-cluster-example" - - defines = [ - "CONFIG_RENDEZVOUS_MODE=7", - "CONFIG_APP_FREERTOS_OS=1", - ] - - if (chip_enable_openthread) { - defines += [ "CONFIG_NET_L2_OPENTHREAD=1" ] - } - - include_dirs = [ - "../../common/main/include", - "../../common/main", - "${chip_root}/examples/all-clusters-app/all-clusters-common/include", - "${chip_root}/examples/providers/", - ] - - sources = [ - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp", - "../../common/main/AppTask.cpp", - "../../common/main/DeviceCallbacks.cpp", - "../../common/main/ZclCallbacks.cpp", - "../../common/main/include/AppEvent.h", - "../../common/main/include/AppTask.h", - "../../common/main/include/DeviceCallbacks.h", - "../../common/main/main.cpp", - ] - - # App common files - include_dirs += [ - "${common_example_dir}/icd/include", - "${common_example_dir}/matter_cli/include", - "${common_example_dir}/device_manager/include", - "${common_example_dir}/device_callbacks/include", - "${common_example_dir}/matter_button/include", - "${common_example_dir}/factory_data/include", - "${common_example_dir}/app_task/include", - ] - - sources += [ - "${chip_root}/examples/platform/nxp/${nxp_platform}/factory_data/source/AppFactoryDataExample.cpp", - "${common_example_dir}/app_task/source/AppTaskBase.cpp", - "${common_example_dir}/app_task/source/AppTaskFreeRTOS.cpp", - "${common_example_dir}/device_callbacks/source/CommonDeviceCallbacks.cpp", - "${common_example_dir}/device_manager/source/CHIPDeviceManager.cpp", - "${common_example_dir}/icd/source/ICDUtil.cpp", - "${common_example_dir}/matter_button/source/ButtonRegistrationEmpty.cpp", - ] - - deps = [ - "${chip_root}/examples/${app_common_folder}", - "${chip_root}/examples/providers:device_info_provider_please_do_not_reuse_as_is", - "${chip_root}/src/app/clusters/network-commissioning:network-commissioning", - "${chip_root}/src/setup_payload:onboarding-codes-utils", - ] - - sources += [ - "${chip_root}/examples/${app_common_folder}/src/bridged-actions-stub.cpp", - "${chip_root}/examples/${app_common_folder}/src/smco-stub.cpp", - "${chip_root}/examples/${app_common_folder}/src/static-supported-modes-manager.cpp", - ] - - if (nxp_enable_matter_cli) { - defines += [ "ENABLE_CHIP_SHELL" ] - deps += [ - "${chip_root}/examples/shell/shell_common:shell_common", - "${chip_root}/src/lib/shell:shell", - ] - sources += [ - "${common_example_dir}/matter_cli/source/AppCLIBase.cpp", - "${common_example_dir}/matter_cli/source/AppCLIFreeRTOS.cpp", - ] - } - - if (chip_enable_ota_requestor) { - include_dirs += [ "${common_example_dir}/ota_requestor/include" ] - sources += [ - "${common_example_dir}/ota_requestor/source/OTARequestorInitiator.cpp", - "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorCommon.cpp", - ] - } - - if (wifi_auto_connect_at_boot) { - assert(wifi_auto_connect_at_boot_ssid != "" && - wifi_auto_connect_at_boot_password != "", - "WiFi SSID and password must be specified at build time!") - - defines += [ - "CONFIG_CHIP_APP_WIFI_CONNECT_AT_BOOT=1", - "CONFIG_CHIP_APP_WIFI_SSID=\"${wifi_auto_connect_at_boot_ssid}\"", - "CONFIG_CHIP_APP_WIFI_PASSWORD=\"${wifi_auto_connect_at_boot_password}\"", - ] - - include_dirs += [ "${common_example_dir}/wifi_connect/include" ] - sources += [ "${common_example_dir}/wifi_connect/source/WifiConnect.cpp" ] - } - - if (enable_ota_provider) { - defines += [ "CONFIG_CHIP_OTA_PROVIDER=1" ] - - include_dirs += [ - "${common_example_dir}/ota_provider/include", - "${common_example_dir}/ota_provider/ota-provider-common", - ] - - sources += [ - "${common_example_dir}/ota_provider/ota-provider-common/RTBdxOtaSender.cpp", - "${common_example_dir}/ota_provider/ota-provider-common/RTOTAProviderExample.cpp", - "${common_example_dir}/ota_provider/source/OTAProvider.cpp", - ] - - deps += [ - "${chip_root}/src/app/server", - "${chip_root}/src/protocols/bdx", - "${chip_root}/third_party/jsoncpp", - ] - } - - if (chip_enable_ble) { - defines += [ "APP_BT_DEVICE_NAME=\"NXP-AllClustersApp\"" ] - } - - # In case a dedicated assert function needs to be supported the flag sdk_fsl_assert_support should be set to false - # The would add to the build a dedicated application assert implementation. - if (!sdk_fsl_assert_support) { - sources += [ "${common_example_dir}/app_assert/source/AppAssert.cpp" ] - } - - cflags = [ "-Wconversion" ] - - ldscript = - "${example_platform_dir}/app/ldscripts/MIMXRT1062xxxxx_flexspi_nor.ld" - - inputs = [ ldscript ] - - ldflags = [ - "-T" + rebase_path(ldscript, root_build_dir), - "-fno-common", - "-Wl,--defsym=__stack_size__=2048", - "-ffreestanding", - "-fno-builtin", - "-mapcs", - "-u qspiflash_config", - "-u image_vector_table", - "-u boot_data", - "-u dcd_data", - "-Wl,-print-memory-usage", - "-Wl,--no-warn-rwx-segments", - ] - - if (evkname == "evkcmimxrt1060") { - ldflags += [ "-Wl,--defsym=gFlashSize_d=0x1000000" ] - } - - if (enable_ota_provider) { - # As the OTA file will be stored in the littlefs file system, it is required to increase the size of the file system - # To be able to store an OTA file with a MAX size of 640K, - # it recommended to size the file system with: - # 161 sectors of 4K => reserved for the OTA file - # 32 sectors of 4K => reserved for Matter/OT/BLE settings storage - ldflags += [ "-Wl,--defsym=gNVMSectorCountLink_d=193" ] - } - - if (chip_enable_ota_requestor) { - # If OTA build flag is enabled, - # we would need to reserve enough space for the bootloader (MCUBoot) - # MCUBoot requires 0x11000 Bytes to be reserved at the base of the flash - # Consequently, some sections will need to be shifted - ldflags += [ "-Wl,--defsym=__m_mcuboot_size__=0x40000" ] - } - - output_dir = root_out_dir -} - -group("rt1060") { - deps = [ ":all_cluster_app" ] -} - -group("default") { - deps = [ ":rt1060" ] -} diff --git a/examples/all-clusters-app/nxp/rt/rt1060/args.gni b/examples/all-clusters-app/nxp/rt/rt1060/args.gni deleted file mode 100644 index c2d91a5db7b..00000000000 --- a/examples/all-clusters-app/nxp/rt/rt1060/args.gni +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2023 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") - -# SDK target definitions -nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") -nxp_sdk_driver_target = get_label_info(":sdk_driver", "label_no_toolchain") diff --git a/examples/all-clusters-app/nxp/rt/rt1060/build_overrides b/examples/all-clusters-app/nxp/rt/rt1060/build_overrides deleted file mode 120000 index f10867042f4..00000000000 --- a/examples/all-clusters-app/nxp/rt/rt1060/build_overrides +++ /dev/null @@ -1 +0,0 @@ -../../../../build_overrides \ No newline at end of file diff --git a/examples/all-clusters-app/nxp/rt/rt1060/include/config/CHIPProjectConfig.h b/examples/all-clusters-app/nxp/rt/rt1060/include/config/CHIPProjectConfig.h deleted file mode 100644 index 0ca6dc65b21..00000000000 --- a/examples/all-clusters-app/nxp/rt/rt1060/include/config/CHIPProjectConfig.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2020 Google LLC. - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Example project configuration file for CHIP. - * - * This is a place to put application or project-specific overrides - * to the default configuration values for general CHIP features. - * - */ - -#pragma once - -/* - * Tells to the platform Factory Data Provider whether to use the example configuration or real/provisioned data. - */ -#ifndef CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -#define CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA 0 -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID - * - * 0xFFF1: Test vendor. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1 - -/** - * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID - * - */ -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8005 - -#if !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -// Use a default pairing code if one hasn't been provisioned in flash. -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 -#endif - -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 -#endif - -// Use a default pairing code if one hasn't been provisioned in flash. -#define CHIP_DEVICE_CONFIG_USE_TEST_PAIRING_CODE "CHIPUS" - -/** - * CHIP_DEVICE_CONFIG_USE_TEST_SERIAL_NUMBER - * - * Enables the use of a hard-coded default serial number if none - * is found in CHIP NV storage. - */ -#define CHIP_DEVICE_CONFIG_USE_TEST_SERIAL_NUMBER "DUMMY_SN" - -#endif /* !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA */ - -/** - * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION - * - * The hardware version number assigned to device or product by the device vendor. This - * number is scoped to the device product id, and typically corresponds to a revision of the - * physical device, a change to its packaging, and/or a change to its marketing presentation. - * This value is generally *not* incremented for device software versions. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 100 - -#ifndef CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING "v0.1.0" -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING - * - * A string identifying the software version running on the device. - * CHIP currently expects the software version to be in the format - * {MAJOR_VERSION}.0d{MINOR_VERSION} - */ -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION NXP_CONFIG_DEVICE_SOFTWARE_VERSION -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "NXP Semiconductors" -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "NXP Demo App" -#endif - -#ifndef CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION -//-> format_version = 1 -//-> vendor_id = 0xFFF1 -//-> product_id_array = [ 0x8000, 0x8001, 0x8002, 0x8003, 0x8004, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009, 0x800A, 0x800B, -// 0x800C, 0x800D, 0x800E, 0x800F, 0x8010, 0x8011, 0x8012, 0x8013, 0x8014, 0x8015, 0x8016, 0x8017, 0x8018, 0x8019, 0x801A, -// 0x801B, 0x801C, 0x801D, 0x801E, 0x801F, 0x8020, 0x8021, 0x8022, 0x8023, 0x8024, 0x8025, 0x8026, 0x8027, 0x8028, 0x8029, -// 0x802A, 0x802B, 0x802C, 0x802D, 0x802E, 0x802F, 0x8030, 0x8031, 0x8032, 0x8033, 0x8034, 0x8035, 0x8036, 0x8037, 0x8038, -// 0x8039, 0x803A, 0x803B, 0x803C, 0x803D, 0x803E, 0x803F, 0x8040, 0x8041, 0x8042, 0x8043, 0x8044, 0x8045, 0x8046, 0x8047, -// 0x8048, 0x8049, 0x804A, 0x804B, 0x804C, 0x804D, 0x804E, 0x804F, 0x8050, 0x8051, 0x8052, 0x8053, 0x8054, 0x8055, 0x8056, -// 0x8057, 0x8058, 0x8059, 0x805A, 0x805B, 0x805C, 0x805D, 0x805E, 0x805F, 0x8060, 0x8061, 0x8062, 0x8063 ] -//-> device_type_id = 0x0016 -//-> certificate_id = "ZIG20142ZB330003-24" -//-> security_level = 0 -//-> security_information = 0 -//-> version_number = 0x2694 -//-> certification_type = 0 -//-> dac_origin_vendor_id is not present -//-> dac_origin_product_id is not present -#define CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION \ - { \ - 0x30, 0x82, 0x02, 0x19, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0x0a, 0x30, \ - 0x82, 0x02, 0x06, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, \ - 0x02, 0x01, 0x30, 0x82, 0x01, 0x71, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, \ - 0x01, 0x62, 0x04, 0x82, 0x01, 0x5e, 0x15, 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, \ - 0x05, 0x01, 0x80, 0x05, 0x02, 0x80, 0x05, 0x03, 0x80, 0x05, 0x04, 0x80, 0x05, 0x05, 0x80, 0x05, 0x06, 0x80, 0x05, \ - 0x07, 0x80, 0x05, 0x08, 0x80, 0x05, 0x09, 0x80, 0x05, 0x0a, 0x80, 0x05, 0x0b, 0x80, 0x05, 0x0c, 0x80, 0x05, 0x0d, \ - 0x80, 0x05, 0x0e, 0x80, 0x05, 0x0f, 0x80, 0x05, 0x10, 0x80, 0x05, 0x11, 0x80, 0x05, 0x12, 0x80, 0x05, 0x13, 0x80, \ - 0x05, 0x14, 0x80, 0x05, 0x15, 0x80, 0x05, 0x16, 0x80, 0x05, 0x17, 0x80, 0x05, 0x18, 0x80, 0x05, 0x19, 0x80, 0x05, \ - 0x1a, 0x80, 0x05, 0x1b, 0x80, 0x05, 0x1c, 0x80, 0x05, 0x1d, 0x80, 0x05, 0x1e, 0x80, 0x05, 0x1f, 0x80, 0x05, 0x20, \ - 0x80, 0x05, 0x21, 0x80, 0x05, 0x22, 0x80, 0x05, 0x23, 0x80, 0x05, 0x24, 0x80, 0x05, 0x25, 0x80, 0x05, 0x26, 0x80, \ - 0x05, 0x27, 0x80, 0x05, 0x28, 0x80, 0x05, 0x29, 0x80, 0x05, 0x2a, 0x80, 0x05, 0x2b, 0x80, 0x05, 0x2c, 0x80, 0x05, \ - 0x2d, 0x80, 0x05, 0x2e, 0x80, 0x05, 0x2f, 0x80, 0x05, 0x30, 0x80, 0x05, 0x31, 0x80, 0x05, 0x32, 0x80, 0x05, 0x33, \ - 0x80, 0x05, 0x34, 0x80, 0x05, 0x35, 0x80, 0x05, 0x36, 0x80, 0x05, 0x37, 0x80, 0x05, 0x38, 0x80, 0x05, 0x39, 0x80, \ - 0x05, 0x3a, 0x80, 0x05, 0x3b, 0x80, 0x05, 0x3c, 0x80, 0x05, 0x3d, 0x80, 0x05, 0x3e, 0x80, 0x05, 0x3f, 0x80, 0x05, \ - 0x40, 0x80, 0x05, 0x41, 0x80, 0x05, 0x42, 0x80, 0x05, 0x43, 0x80, 0x05, 0x44, 0x80, 0x05, 0x45, 0x80, 0x05, 0x46, \ - 0x80, 0x05, 0x47, 0x80, 0x05, 0x48, 0x80, 0x05, 0x49, 0x80, 0x05, 0x4a, 0x80, 0x05, 0x4b, 0x80, 0x05, 0x4c, 0x80, \ - 0x05, 0x4d, 0x80, 0x05, 0x4e, 0x80, 0x05, 0x4f, 0x80, 0x05, 0x50, 0x80, 0x05, 0x51, 0x80, 0x05, 0x52, 0x80, 0x05, \ - 0x53, 0x80, 0x05, 0x54, 0x80, 0x05, 0x55, 0x80, 0x05, 0x56, 0x80, 0x05, 0x57, 0x80, 0x05, 0x58, 0x80, 0x05, 0x59, \ - 0x80, 0x05, 0x5a, 0x80, 0x05, 0x5b, 0x80, 0x05, 0x5c, 0x80, 0x05, 0x5d, 0x80, 0x05, 0x5e, 0x80, 0x05, 0x5f, 0x80, \ - 0x05, 0x60, 0x80, 0x05, 0x61, 0x80, 0x05, 0x62, 0x80, 0x05, 0x63, 0x80, 0x18, 0x24, 0x03, 0x16, 0x2c, 0x04, 0x13, \ - 0x5a, 0x49, 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x34, \ - 0x24, 0x05, 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x94, 0x26, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7d, 0x30, 0x7b, 0x02, \ - 0x01, 0x03, 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, \ - 0xf5, 0x04, 0xf3, 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, \ - 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x24, 0xe5, \ - 0xd1, 0xf4, 0x7a, 0x7d, 0x7b, 0x0d, 0x20, 0x6a, 0x26, 0xef, 0x69, 0x9b, 0x7c, 0x97, 0x57, 0xb7, 0x2d, 0x46, 0x90, \ - 0x89, 0xde, 0x31, 0x92, 0xe6, 0x78, 0xc7, 0x45, 0xe7, 0xf6, 0x0c, 0x02, 0x21, 0x00, 0xf8, 0xaa, 0x2f, 0xa7, 0x11, \ - 0xfc, 0xb7, 0x9b, 0x97, 0xe3, 0x97, 0xce, 0xda, 0x66, 0x7b, 0xae, 0x46, 0x4e, 0x2b, 0xd3, 0xff, 0xdf, 0xc3, 0xcc, \ - 0xed, 0x7a, 0xa8, 0xca, 0x5f, 0x4c, 0x1a, 0x7c \ - } -#endif - -/** - * CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC - * - * Enables synchronizing the device's real time clock with a remote CHIP Time service - * using the CHIP Time Sync protocol. - */ -// #define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 1 - -/** - * CHIP_CONFIG_EVENT_LOGGING_WDM_OFFLOAD - * - * Select the ability to offload event logs to any interested subscribers using WDM. - */ -#define CHIP_CONFIG_EVENT_LOGGING_WDM_OFFLOAD 1 - -/** - * CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS - * - * Enable recording UTC timestamps. - */ -#define CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1 - -/** - * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE - * - * A size, in bytes, of the individual debug event logging buffer. - */ -#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512) - -/** - * CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE - * - * For a development build, set the default importance of events to be logged as Debug. - * Since debug is the lowest importance level, this means all standard, critical, info and - * debug importance level vi events get logged. - */ -#if BUILD_RELEASE -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Production -#else -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug -#endif // BUILD_RELEASE - -/* Increasing the retransmission interval of the MRP messages after subsequent failures */ -#ifndef CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL -#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32) -#endif - -#define CHIP_CONFIG_ENABLE_ACL_EXTENSIONS 1 diff --git a/examples/all-clusters-app/nxp/rt/rt1060/third_party/connectedhomeip b/examples/all-clusters-app/nxp/rt/rt1060/third_party/connectedhomeip deleted file mode 120000 index 305f2077ffe..00000000000 --- a/examples/all-clusters-app/nxp/rt/rt1060/third_party/connectedhomeip +++ /dev/null @@ -1 +0,0 @@ -../../../../../.. \ No newline at end of file diff --git a/examples/all-clusters-app/nxp/rt/rt1170/.gn b/examples/all-clusters-app/nxp/rt/rt1170/.gn deleted file mode 100644 index 59dcfeb229a..00000000000 --- a/examples/all-clusters-app/nxp/rt/rt1170/.gn +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) 2020 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") -import("//build_overrides/chip.gni") - -# The location of the build configuration file. -buildconfig = "${build_root}/config/BUILDCONFIG.gn" - -# CHIP uses angle bracket includes. -check_system_includes = true - -default_args = { - target_cpu = "arm" - target_os = "freertos" - - import("//args.gni") - - # Import common example GN args - import("${chip_root}/examples/platform/nxp/common/gn/args.gni") - - # Import default platform configs - import("${chip_root}/src/platform/nxp/rt/rt1170/args.gni") -} diff --git a/examples/all-clusters-app/nxp/rt/rt1170/BUILD.gn b/examples/all-clusters-app/nxp/rt/rt1170/BUILD.gn deleted file mode 100644 index 1976700c579..00000000000 --- a/examples/all-clusters-app/nxp/rt/rt1170/BUILD.gn +++ /dev/null @@ -1,250 +0,0 @@ -# Copyright (c) 2021-2023 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") -import("//build_overrides/chip.gni") -import("//build_overrides/nxp_sdk.gni") -import("//build_overrides/openthread.gni") -import("${chip_root}/src/platform/device.gni") - -#allows to get common NXP SDK gn options -import("${nxp_sdk_build_root}/nxp_sdk.gni") - -# Allows to get various RT gn options -import("${nxp_sdk_build_root}/${nxp_sdk_name}/rt_sdk.gni") - -import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") -import( - "${nxp_sdk_build_root}/${nxp_sdk_name}/${rt_platform}/${rt_platform}.gni") -import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") - -assert(current_os == "freertos") -assert(target_os == "freertos") -assert(nxp_platform == "rt/rt1170") - -declare_args() { - # Allows to connect to a predefine Wi-Fi network at boot - wifi_auto_connect_at_boot = false - wifi_auto_connect_at_boot_ssid = "" - wifi_auto_connect_at_boot_password = "" - - # Setup discriminator as argument - setup_discriminator = 3840 -} - -example_platform_dir = - "${nxp_sdk_matter_support_root}/examples/platform/${nxp_platform}" -common_example_dir = "${chip_root}/examples/platform/nxp/common" - -app_common_folder = "all-clusters-app/all-clusters-common" - -# Create here the SDK instance. -# Particular sources/defines/includes could be added/changed depending on the target application. -rt_sdk("sdk") { - defines = [] - - cflags = [] - public_deps = [] - public_configs = [] - sources = [] - include_dirs = [] - - # Indicate paths to default board files - include_dirs += [ "${example_platform_dir}/board/" ] - sources += [ "${example_platform_dir}/board/pin_mux.c" ] - sources += [ "${example_platform_dir}/board/hardware_init.c" ] - sources += [ "${example_platform_dir}/board/clock_config.c" ] - sources += [ "${example_platform_dir}/board/board.c" ] - sources += [ "${example_platform_dir}/board/peripherals.c" ] - sources += [ "${example_platform_dir}/board/sdmmc_config.c" ] - sources += [ "${example_platform_dir}/board/wifi_bt_config.c" ] - - # Indicate the path to CHIPProjectConfig.h - include_dirs += [ "include/config" ] - - # Indicate the default path to FreeRTOSConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/freeRTOS" ] - - # Indicate the default path to OpenThreadConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/openthread" ] - - # For matter with BR feature, increase FreeRTOS heap size - if (chip_enable_wifi && chip_enable_openthread) { - defines += [ "configTOTAL_HEAP_SIZE=(size_t)(170 * 1024)" ] - } - - defines += [ - "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", - ] -} - -# Create the SDK driver instance. -# Particular sources/defines/includes could be added to add other drivers not available in the default sdk driver template -rt1170_sdk_drivers("sdk_driver") { -} - -rt_executable("all_cluster_app") { - output_name = "chip-rt1170-all-cluster-example" - - defines = [ - "CONFIG_RENDEZVOUS_MODE=7", - "CONFIG_APP_FREERTOS_OS=1", - ] - - if (chip_enable_openthread) { - defines += [ "CONFIG_NET_L2_OPENTHREAD=1" ] - } - - include_dirs = [ - "../../common/main/include", - "../../common/main", - "${chip_root}/examples/all-clusters-app/all-clusters-common/include", - "${chip_root}/examples/providers/", - ] - - sources = [ - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp", - "../../common/main/AppTask.cpp", - "../../common/main/DeviceCallbacks.cpp", - "../../common/main/ZclCallbacks.cpp", - "../../common/main/include/AppEvent.h", - "../../common/main/include/AppTask.h", - "../../common/main/include/DeviceCallbacks.h", - "../../common/main/main.cpp", - ] - - # App common files - include_dirs += [ - "${common_example_dir}/icd/include", - "${common_example_dir}/matter_button/include", - "${common_example_dir}/matter_cli/include", - "${common_example_dir}/device_manager/include", - "${common_example_dir}/device_callbacks/include", - "${common_example_dir}/factory_data/include", - "${common_example_dir}/app_task/include", - ] - - sources += [ - "${common_example_dir}/app_task/source/AppTaskBase.cpp", - "${common_example_dir}/app_task/source/AppTaskFreeRTOS.cpp", - "${common_example_dir}/device_callbacks/source/CommonDeviceCallbacks.cpp", - "${common_example_dir}/device_manager/source/CHIPDeviceManager.cpp", - "${common_example_dir}/factory_data/source/AppFactoryDataDefaultImpl.cpp", - "${common_example_dir}/icd/source/ICDUtil.cpp", - "${common_example_dir}/matter_button/source/ButtonRegistrationEmpty.cpp", - ] - - deps = [ - "${chip_root}/examples/${app_common_folder}", - "${chip_root}/examples/providers:device_info_provider_please_do_not_reuse_as_is", - "${chip_root}/src/app/clusters/network-commissioning:network-commissioning", - "${chip_root}/src/setup_payload:onboarding-codes-utils", - ] - - sources += [ - "${chip_root}/examples/${app_common_folder}/src/bridged-actions-stub.cpp", - "${chip_root}/examples/${app_common_folder}/src/smco-stub.cpp", - "${chip_root}/examples/${app_common_folder}/src/static-supported-modes-manager.cpp", - ] - - if (nxp_enable_matter_cli) { - defines += [ "ENABLE_CHIP_SHELL" ] - deps += [ - "${chip_root}/examples/shell/shell_common:shell_common", - "${chip_root}/src/lib/shell:shell", - ] - sources += [ - "${common_example_dir}/matter_cli/source/AppCLIBase.cpp", - "${common_example_dir}/matter_cli/source/AppCLIFreeRTOS.cpp", - ] - } - - if (chip_enable_ota_requestor) { - include_dirs += [ "${common_example_dir}/ota_requestor/include" ] - sources += [ - "${common_example_dir}/ota_requestor/source/OTARequestorInitiator.cpp", - "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorCommon.cpp", - ] - } - - if (wifi_auto_connect_at_boot) { - assert(wifi_auto_connect_at_boot_ssid != "" && - wifi_auto_connect_at_boot_password != "", - "WiFi SSID and password must be specified at build time!") - - defines += [ - "CONFIG_CHIP_APP_WIFI_CONNECT_AT_BOOT=1", - "CONFIG_CHIP_APP_WIFI_SSID=\"${wifi_auto_connect_at_boot_ssid}\"", - "CONFIG_CHIP_APP_WIFI_PASSWORD=\"${wifi_auto_connect_at_boot_password}\"", - ] - - include_dirs += [ "${common_example_dir}/wifi_connect/include" ] - sources += [ "${common_example_dir}/wifi_connect/source/WifiConnect.cpp" ] - } - - if (chip_enable_ble) { - defines += [ "APP_BT_DEVICE_NAME=\"NXP-AllClustersApp\"" ] - } - - # In case a dedicated assert function needs to be supported the flag sdk_fsl_assert_support should be set to false - # The would add to the build a dedicated application assert implementation. - if (!sdk_fsl_assert_support) { - sources += [ "${common_example_dir}/app_assert/source/AppAssert.cpp" ] - } - - cflags = [ "-Wconversion" ] - - ldscript = - "${example_platform_dir}/app/ldscripts/MIMXRT1176xxxxx_cm7_flexspi_nor.ld" - - inputs = [ ldscript ] - - ldflags = [ - "-T" + rebase_path(ldscript, root_build_dir), - "-fno-common", - "-Wl,--defsym=__stack_size__=2048", - "-ffreestanding", - "-fno-builtin", - "-mapcs", - "-u qspiflash_config", - "-u image_vector_table", - "-u boot_data", - "-u dcd_data", - "-Wl,-print-memory-usage", - "-Wl,--no-warn-rwx-segments", - ] - - if (chip_enable_ota_requestor) { - if (no_mcuboot) { - # If "no_mcuboot" is set to true, the application will be linked at the base of the flash. - print( - "Warning : The OTA Requestor is enabled without MCUBoot. This will prevent the application from applying software updates.") - } else { - # we need to reserve enough space for the bootloader (MCUBoot) - # MCUBoot requires 0x40000 Bytes to be reserved at the base of the flash - # Consequently, some sections will need to be shifted - ldflags += [ "-Wl,--defsym=__m_mcuboot_size__=0x40000" ] - } - } - - output_dir = root_out_dir -} - -group("rt1170") { - deps = [ ":all_cluster_app" ] -} - -group("default") { - deps = [ ":rt1170" ] -} diff --git a/examples/all-clusters-app/nxp/rt/rt1170/args.gni b/examples/all-clusters-app/nxp/rt/rt1170/args.gni deleted file mode 100644 index c2d91a5db7b..00000000000 --- a/examples/all-clusters-app/nxp/rt/rt1170/args.gni +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2023 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") - -# SDK target definitions -nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") -nxp_sdk_driver_target = get_label_info(":sdk_driver", "label_no_toolchain") diff --git a/examples/all-clusters-app/nxp/rt/rt1170/build_overrides b/examples/all-clusters-app/nxp/rt/rt1170/build_overrides deleted file mode 120000 index f10867042f4..00000000000 --- a/examples/all-clusters-app/nxp/rt/rt1170/build_overrides +++ /dev/null @@ -1 +0,0 @@ -../../../../build_overrides \ No newline at end of file diff --git a/examples/all-clusters-app/nxp/rt/rt1170/include/config/CHIPProjectConfig.h b/examples/all-clusters-app/nxp/rt/rt1170/include/config/CHIPProjectConfig.h deleted file mode 100644 index 0ca6dc65b21..00000000000 --- a/examples/all-clusters-app/nxp/rt/rt1170/include/config/CHIPProjectConfig.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2020 Google LLC. - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Example project configuration file for CHIP. - * - * This is a place to put application or project-specific overrides - * to the default configuration values for general CHIP features. - * - */ - -#pragma once - -/* - * Tells to the platform Factory Data Provider whether to use the example configuration or real/provisioned data. - */ -#ifndef CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -#define CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA 0 -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID - * - * 0xFFF1: Test vendor. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1 - -/** - * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID - * - */ -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8005 - -#if !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -// Use a default pairing code if one hasn't been provisioned in flash. -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 -#endif - -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 -#endif - -// Use a default pairing code if one hasn't been provisioned in flash. -#define CHIP_DEVICE_CONFIG_USE_TEST_PAIRING_CODE "CHIPUS" - -/** - * CHIP_DEVICE_CONFIG_USE_TEST_SERIAL_NUMBER - * - * Enables the use of a hard-coded default serial number if none - * is found in CHIP NV storage. - */ -#define CHIP_DEVICE_CONFIG_USE_TEST_SERIAL_NUMBER "DUMMY_SN" - -#endif /* !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA */ - -/** - * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION - * - * The hardware version number assigned to device or product by the device vendor. This - * number is scoped to the device product id, and typically corresponds to a revision of the - * physical device, a change to its packaging, and/or a change to its marketing presentation. - * This value is generally *not* incremented for device software versions. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 100 - -#ifndef CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING "v0.1.0" -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING - * - * A string identifying the software version running on the device. - * CHIP currently expects the software version to be in the format - * {MAJOR_VERSION}.0d{MINOR_VERSION} - */ -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION NXP_CONFIG_DEVICE_SOFTWARE_VERSION -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "NXP Semiconductors" -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "NXP Demo App" -#endif - -#ifndef CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION -//-> format_version = 1 -//-> vendor_id = 0xFFF1 -//-> product_id_array = [ 0x8000, 0x8001, 0x8002, 0x8003, 0x8004, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009, 0x800A, 0x800B, -// 0x800C, 0x800D, 0x800E, 0x800F, 0x8010, 0x8011, 0x8012, 0x8013, 0x8014, 0x8015, 0x8016, 0x8017, 0x8018, 0x8019, 0x801A, -// 0x801B, 0x801C, 0x801D, 0x801E, 0x801F, 0x8020, 0x8021, 0x8022, 0x8023, 0x8024, 0x8025, 0x8026, 0x8027, 0x8028, 0x8029, -// 0x802A, 0x802B, 0x802C, 0x802D, 0x802E, 0x802F, 0x8030, 0x8031, 0x8032, 0x8033, 0x8034, 0x8035, 0x8036, 0x8037, 0x8038, -// 0x8039, 0x803A, 0x803B, 0x803C, 0x803D, 0x803E, 0x803F, 0x8040, 0x8041, 0x8042, 0x8043, 0x8044, 0x8045, 0x8046, 0x8047, -// 0x8048, 0x8049, 0x804A, 0x804B, 0x804C, 0x804D, 0x804E, 0x804F, 0x8050, 0x8051, 0x8052, 0x8053, 0x8054, 0x8055, 0x8056, -// 0x8057, 0x8058, 0x8059, 0x805A, 0x805B, 0x805C, 0x805D, 0x805E, 0x805F, 0x8060, 0x8061, 0x8062, 0x8063 ] -//-> device_type_id = 0x0016 -//-> certificate_id = "ZIG20142ZB330003-24" -//-> security_level = 0 -//-> security_information = 0 -//-> version_number = 0x2694 -//-> certification_type = 0 -//-> dac_origin_vendor_id is not present -//-> dac_origin_product_id is not present -#define CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION \ - { \ - 0x30, 0x82, 0x02, 0x19, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0x0a, 0x30, \ - 0x82, 0x02, 0x06, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, \ - 0x02, 0x01, 0x30, 0x82, 0x01, 0x71, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, \ - 0x01, 0x62, 0x04, 0x82, 0x01, 0x5e, 0x15, 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, \ - 0x05, 0x01, 0x80, 0x05, 0x02, 0x80, 0x05, 0x03, 0x80, 0x05, 0x04, 0x80, 0x05, 0x05, 0x80, 0x05, 0x06, 0x80, 0x05, \ - 0x07, 0x80, 0x05, 0x08, 0x80, 0x05, 0x09, 0x80, 0x05, 0x0a, 0x80, 0x05, 0x0b, 0x80, 0x05, 0x0c, 0x80, 0x05, 0x0d, \ - 0x80, 0x05, 0x0e, 0x80, 0x05, 0x0f, 0x80, 0x05, 0x10, 0x80, 0x05, 0x11, 0x80, 0x05, 0x12, 0x80, 0x05, 0x13, 0x80, \ - 0x05, 0x14, 0x80, 0x05, 0x15, 0x80, 0x05, 0x16, 0x80, 0x05, 0x17, 0x80, 0x05, 0x18, 0x80, 0x05, 0x19, 0x80, 0x05, \ - 0x1a, 0x80, 0x05, 0x1b, 0x80, 0x05, 0x1c, 0x80, 0x05, 0x1d, 0x80, 0x05, 0x1e, 0x80, 0x05, 0x1f, 0x80, 0x05, 0x20, \ - 0x80, 0x05, 0x21, 0x80, 0x05, 0x22, 0x80, 0x05, 0x23, 0x80, 0x05, 0x24, 0x80, 0x05, 0x25, 0x80, 0x05, 0x26, 0x80, \ - 0x05, 0x27, 0x80, 0x05, 0x28, 0x80, 0x05, 0x29, 0x80, 0x05, 0x2a, 0x80, 0x05, 0x2b, 0x80, 0x05, 0x2c, 0x80, 0x05, \ - 0x2d, 0x80, 0x05, 0x2e, 0x80, 0x05, 0x2f, 0x80, 0x05, 0x30, 0x80, 0x05, 0x31, 0x80, 0x05, 0x32, 0x80, 0x05, 0x33, \ - 0x80, 0x05, 0x34, 0x80, 0x05, 0x35, 0x80, 0x05, 0x36, 0x80, 0x05, 0x37, 0x80, 0x05, 0x38, 0x80, 0x05, 0x39, 0x80, \ - 0x05, 0x3a, 0x80, 0x05, 0x3b, 0x80, 0x05, 0x3c, 0x80, 0x05, 0x3d, 0x80, 0x05, 0x3e, 0x80, 0x05, 0x3f, 0x80, 0x05, \ - 0x40, 0x80, 0x05, 0x41, 0x80, 0x05, 0x42, 0x80, 0x05, 0x43, 0x80, 0x05, 0x44, 0x80, 0x05, 0x45, 0x80, 0x05, 0x46, \ - 0x80, 0x05, 0x47, 0x80, 0x05, 0x48, 0x80, 0x05, 0x49, 0x80, 0x05, 0x4a, 0x80, 0x05, 0x4b, 0x80, 0x05, 0x4c, 0x80, \ - 0x05, 0x4d, 0x80, 0x05, 0x4e, 0x80, 0x05, 0x4f, 0x80, 0x05, 0x50, 0x80, 0x05, 0x51, 0x80, 0x05, 0x52, 0x80, 0x05, \ - 0x53, 0x80, 0x05, 0x54, 0x80, 0x05, 0x55, 0x80, 0x05, 0x56, 0x80, 0x05, 0x57, 0x80, 0x05, 0x58, 0x80, 0x05, 0x59, \ - 0x80, 0x05, 0x5a, 0x80, 0x05, 0x5b, 0x80, 0x05, 0x5c, 0x80, 0x05, 0x5d, 0x80, 0x05, 0x5e, 0x80, 0x05, 0x5f, 0x80, \ - 0x05, 0x60, 0x80, 0x05, 0x61, 0x80, 0x05, 0x62, 0x80, 0x05, 0x63, 0x80, 0x18, 0x24, 0x03, 0x16, 0x2c, 0x04, 0x13, \ - 0x5a, 0x49, 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x34, \ - 0x24, 0x05, 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x94, 0x26, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7d, 0x30, 0x7b, 0x02, \ - 0x01, 0x03, 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, \ - 0xf5, 0x04, 0xf3, 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, \ - 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x24, 0xe5, \ - 0xd1, 0xf4, 0x7a, 0x7d, 0x7b, 0x0d, 0x20, 0x6a, 0x26, 0xef, 0x69, 0x9b, 0x7c, 0x97, 0x57, 0xb7, 0x2d, 0x46, 0x90, \ - 0x89, 0xde, 0x31, 0x92, 0xe6, 0x78, 0xc7, 0x45, 0xe7, 0xf6, 0x0c, 0x02, 0x21, 0x00, 0xf8, 0xaa, 0x2f, 0xa7, 0x11, \ - 0xfc, 0xb7, 0x9b, 0x97, 0xe3, 0x97, 0xce, 0xda, 0x66, 0x7b, 0xae, 0x46, 0x4e, 0x2b, 0xd3, 0xff, 0xdf, 0xc3, 0xcc, \ - 0xed, 0x7a, 0xa8, 0xca, 0x5f, 0x4c, 0x1a, 0x7c \ - } -#endif - -/** - * CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC - * - * Enables synchronizing the device's real time clock with a remote CHIP Time service - * using the CHIP Time Sync protocol. - */ -// #define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 1 - -/** - * CHIP_CONFIG_EVENT_LOGGING_WDM_OFFLOAD - * - * Select the ability to offload event logs to any interested subscribers using WDM. - */ -#define CHIP_CONFIG_EVENT_LOGGING_WDM_OFFLOAD 1 - -/** - * CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS - * - * Enable recording UTC timestamps. - */ -#define CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1 - -/** - * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE - * - * A size, in bytes, of the individual debug event logging buffer. - */ -#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512) - -/** - * CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE - * - * For a development build, set the default importance of events to be logged as Debug. - * Since debug is the lowest importance level, this means all standard, critical, info and - * debug importance level vi events get logged. - */ -#if BUILD_RELEASE -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Production -#else -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug -#endif // BUILD_RELEASE - -/* Increasing the retransmission interval of the MRP messages after subsequent failures */ -#ifndef CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL -#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32) -#endif - -#define CHIP_CONFIG_ENABLE_ACL_EXTENSIONS 1 diff --git a/examples/all-clusters-app/nxp/rt/rt1170/third_party/connectedhomeip b/examples/all-clusters-app/nxp/rt/rt1170/third_party/connectedhomeip deleted file mode 120000 index 305f2077ffe..00000000000 --- a/examples/all-clusters-app/nxp/rt/rt1170/third_party/connectedhomeip +++ /dev/null @@ -1 +0,0 @@ -../../../../../.. \ No newline at end of file diff --git a/examples/all-clusters-app/nxp/rt/rw61x/.gn b/examples/all-clusters-app/nxp/rt/rw61x/.gn deleted file mode 100644 index cbbec24fe8c..00000000000 --- a/examples/all-clusters-app/nxp/rt/rw61x/.gn +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (c) 2020 Project CHIP Authors -# Copyright 2023 NXP -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") -import("//build_overrides/chip.gni") - -# The location of the build configuration file. -buildconfig = "${build_root}/config/BUILDCONFIG.gn" - -# CHIP uses angle bracket includes. -check_system_includes = true - -default_args = { - target_cpu = "arm" - target_os = "freertos" - - import("//args.gni") - - # Import common example GN args - import("${chip_root}/examples/platform/nxp/common/gn/args.gni") - - # Import default platform configs - import("${chip_root}/src/platform/nxp/rt/rw61x/args.gni") -} diff --git a/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn b/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn deleted file mode 100644 index d5469323248..00000000000 --- a/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn +++ /dev/null @@ -1,273 +0,0 @@ -# Copyright (c) 2021 Project CHIP Authors -# Copyright 2023-2024 NXP -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") -import("//build_overrides/chip.gni") -import("//build_overrides/nxp_sdk.gni") -import("//build_overrides/openthread.gni") -import("${chip_root}/src/platform/device.gni") - -#allows to get common NXP SDK gn options -import("${nxp_sdk_build_root}/nxp_sdk.gni") - -# Allows to get various RT gn options -import("${nxp_sdk_build_root}/${nxp_sdk_name}/rt_sdk.gni") - -import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") -import( - "${nxp_sdk_build_root}/${nxp_sdk_name}/${rt_platform}/${rt_platform}.gni") -import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") - -assert(current_os == "freertos") -assert(target_os == "freertos") -assert(nxp_platform == "rt/rw61x") - -declare_args() { - # Allows to connect to a predefine Wi-Fi network at boot - wifi_auto_connect_at_boot = false - wifi_auto_connect_at_boot_ssid = "" - wifi_auto_connect_at_boot_password = "" - - # Setup discriminator as argument - setup_discriminator = 3840 -} - -example_platform_dir = - "${nxp_sdk_matter_support_root}/examples/platform/${nxp_platform}" -common_example_dir = "${chip_root}/examples/platform/nxp/common" - -app_common_folder = "all-clusters-app/all-clusters-common" - -# Create here the SDK instance. -# Particular sources/defines/includes could be added/changed depending on the target application. -rt_sdk("sdk") { - defines = [] - - cflags = [] - public_deps = [] - public_configs = [] - sources = [] - include_dirs = [] - - # Indicate paths to default board files - include_dirs += [ "${example_platform_dir}/board/" ] - sources += [ "${example_platform_dir}/board/pin_mux.c" ] - sources += [ "${example_platform_dir}/board/hardware_init.c" ] - sources += [ "${example_platform_dir}/board/peripherals.c" ] - - if (board_version == "frdm") { - include_dirs += [ "${example_platform_dir}/board/frdmrw612/" ] - sources += [ "${example_platform_dir}/board/frdmrw612/clock_config.c" ] - sources += [ "${example_platform_dir}/board/frdmrw612/board.c" ] - } else { - include_dirs += [ "${example_platform_dir}/board/rdrw612bga/" ] - sources += [ "${example_platform_dir}/board/rdrw612bga/clock_config.c" ] - sources += [ "${example_platform_dir}/board/rdrw612bga/board.c" ] - } - - # Indicate the path to CHIPProjectConfig.h - include_dirs += [ "include/config" ] - - # Indicate the default path to FreeRTOSConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/freeRTOS" ] - - # Indicate the default path to OpenThreadConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/openthread" ] - - # For matter with BR feature, increase FreeRTOS heap size - if (chip_enable_wifi && chip_enable_openthread) { - defines += [ "configTOTAL_HEAP_SIZE=(size_t)(170 * 1024)" ] - } - - defines += [ - "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", - ] -} - -# Create the SDK driver instance. -# Particular sources/defines/includes could be added to add other drivers not available in the default sdk driver template -rw61x_sdk_drivers("sdk_driver") { -} - -rt_executable("all_cluster_app") { - output_name = "chip-rw61x-all-cluster-example" - - defines = [ - "CONFIG_RENDEZVOUS_MODE=7", - "CONFIG_APP_FREERTOS_OS=1", - ] - - if (chip_enable_openthread) { - defines += [ "CONFIG_NET_L2_OPENTHREAD=1" ] - } - - include_dirs = [ - "../../common/main/include", - "../../common/main", - "${chip_root}/examples/all-clusters-app/all-clusters-common/include", - "${chip_root}/examples/providers/", - ] - - sources = [ - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp", - "../../common/main/AppTask.cpp", - "../../common/main/DeviceCallbacks.cpp", - "../../common/main/ZclCallbacks.cpp", - "../../common/main/include/AppEvent.h", - "../../common/main/include/AppTask.h", - "../../common/main/include/DeviceCallbacks.h", - "../../common/main/main.cpp", - ] - - if (nxp_enable_secure_whole_factory_data || - nxp_enable_secure_EL2GO_factory_data) { - sources += [ "${chip_root}/examples/platform/nxp/${nxp_platform}/factory_data/source/AppFactoryDataExample.cpp" ] - if (nxp_enable_secure_whole_factory_data) { - defines += [ "ENABLE_SECURE_WHOLE_FACTORY_DATA" ] - } - } else { - sources += [ - "${common_example_dir}/factory_data/source/AppFactoryDataDefaultImpl.cpp", - ] - } - - # App common files - include_dirs += [ - "${common_example_dir}/icd/include", - "${common_example_dir}/matter_button/include", - "${common_example_dir}/matter_cli/include", - "${common_example_dir}/device_manager/include", - "${common_example_dir}/device_callbacks/include", - "${common_example_dir}/app_task/include", - "${common_example_dir}/factory_data/include", - "${common_example_dir}/operational_keystore/include", - ] - - sources += [ - "${common_example_dir}/app_task/source/AppTaskBase.cpp", - "${common_example_dir}/app_task/source/AppTaskFreeRTOS.cpp", - "${common_example_dir}/device_callbacks/source/CommonDeviceCallbacks.cpp", - "${common_example_dir}/device_manager/source/CHIPDeviceManager.cpp", - "${common_example_dir}/icd/source/ICDUtil.cpp", - "${common_example_dir}/matter_button/source/ButtonRegistrationEmpty.cpp", - "${common_example_dir}/operational_keystore/source/OperationalKeystoreS50.cpp", - ] - - deps = [ - "${chip_root}/examples/${app_common_folder}", - "${chip_root}/examples/providers:device_info_provider_please_do_not_reuse_as_is", - "${chip_root}/src/app/clusters/network-commissioning:network-commissioning", - "${chip_root}/src/platform/logging:default", - "${chip_root}/src/setup_payload:onboarding-codes-utils", - ] - - # Operational key secure storage - defines += [ "CONFIG_OPERATIONAL_KEYSTORE=1" ] - - sources += [ - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp", - ] - - if (nxp_enable_matter_cli) { - defines += [ "ENABLE_CHIP_SHELL" ] - deps += [ - "${chip_root}/examples/shell/shell_common:shell_common", - "${chip_root}/src/lib/shell:shell", - ] - sources += [ - "${common_example_dir}/matter_cli/source/AppCLIBase.cpp", - "${common_example_dir}/matter_cli/source/AppCLIFreeRTOS.cpp", - ] - } - - if (chip_enable_ota_requestor) { - include_dirs += [ "${common_example_dir}/ota_requestor/include" ] - sources += [ - "${common_example_dir}/ota_requestor/source/OTARequestorInitiator.cpp", - "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorCommon.cpp", - ] - } - - if (wifi_auto_connect_at_boot) { - assert(wifi_auto_connect_at_boot_ssid != "" && - wifi_auto_connect_at_boot_password != "", - "WiFi SSID and password must be specified at build time!") - - defines += [ - "CONFIG_CHIP_APP_WIFI_CONNECT_AT_BOOT=1", - "CONFIG_CHIP_APP_WIFI_SSID=\"${wifi_auto_connect_at_boot_ssid}\"", - "CONFIG_CHIP_APP_WIFI_PASSWORD=\"${wifi_auto_connect_at_boot_password}\"", - ] - - include_dirs += [ "${common_example_dir}/wifi_connect/include" ] - sources += [ "${common_example_dir}/wifi_connect/source/WifiConnect.cpp" ] - } - - if (chip_enable_ble) { - defines += [ "APP_BT_DEVICE_NAME=\"NXP-AllClustersApp\"" ] - } - - # In case a dedicated assert function needs to be supported the flag sdk_fsl_assert_support should be set to false - # The would add to the build a dedicated application assert implementation. - if (!sdk_fsl_assert_support) { - sources += [ "${common_example_dir}/app_assert/source/AppAssert.cpp" ] - } - - cflags = [ "-Wconversion" ] - - ldscript = "${example_platform_dir}/app/ldscripts/RW610_flash.ld" - - inputs = [ ldscript ] - - ldflags = [ - "-T" + rebase_path(ldscript, root_build_dir), - "-fno-common", - "-Wl,--defsym=__stack_size__=2048", - "-ffreestanding", - "-fno-builtin", - "-mapcs", - "-u qspiflash_config", - "-u image_vector_table", - "-u boot_data", - "-u dcd_data", - "-Wl,-print-memory-usage", - "-Wl,--no-warn-rwx-segments", - ] - - if (chip_enable_ota_requestor) { - if (no_mcuboot) { - # If "no_mcuboot" is set to true, the application will be linked at the base of the flash. - print( - "Warning : The OTA Requestor is enabled without MCUBoot. This will prevent the application from applying software updates.") - } else { - # we need to reserve enough space for the bootloader (MCUBoot) - # MCUBoot requires 0x20000 Bytes to be reserved at the base of the flash - # Consequently, some sections will need to be shifted - ldflags += [ "-Wl,--defsym=__m_mcuboot_size__=0x20000" ] - } - } - - output_dir = root_out_dir -} - -group("rw61x") { - deps = [ ":all_cluster_app" ] -} - -group("default") { - deps = [ ":rw61x" ] -} diff --git a/examples/all-clusters-app/nxp/rt/rw61x/args.gni b/examples/all-clusters-app/nxp/rt/rw61x/args.gni deleted file mode 100644 index c2d91a5db7b..00000000000 --- a/examples/all-clusters-app/nxp/rt/rw61x/args.gni +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2023 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") - -# SDK target definitions -nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") -nxp_sdk_driver_target = get_label_info(":sdk_driver", "label_no_toolchain") diff --git a/examples/all-clusters-app/nxp/rt/rw61x/build_overrides b/examples/all-clusters-app/nxp/rt/rw61x/build_overrides deleted file mode 120000 index f10867042f4..00000000000 --- a/examples/all-clusters-app/nxp/rt/rw61x/build_overrides +++ /dev/null @@ -1 +0,0 @@ -../../../../build_overrides \ No newline at end of file diff --git a/examples/all-clusters-app/nxp/rt/rw61x/include/config/CHIPProjectConfig.h b/examples/all-clusters-app/nxp/rt/rw61x/include/config/CHIPProjectConfig.h deleted file mode 100644 index 8847f9fd6ba..00000000000 --- a/examples/all-clusters-app/nxp/rt/rw61x/include/config/CHIPProjectConfig.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2020 Google LLC. - * Copyright 2023 NXP - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Example project configuration file for CHIP. - * - * This is a place to put application or project-specific overrides - * to the default configuration values for general CHIP features. - * - */ - -#pragma once - -/* - * Tells to the platform Factory Data Provider whether to use the example configuration or real/provisioned data. - */ -#ifndef CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -#define CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA 0 -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID - * - * 0xFFF1: Test vendor. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1 - -/** - * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID - * - */ -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8005 - -#if !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -// Use a default pairing code if one hasn't been provisioned in flash. -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 -#endif - -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 -#endif - -// Use a default pairing code if one hasn't been provisioned in flash. -#define CHIP_DEVICE_CONFIG_USE_TEST_PAIRING_CODE "CHIPUS" - -/** - * CHIP_DEVICE_CONFIG_USE_TEST_SERIAL_NUMBER - * - * Enables the use of a hard-coded default serial number if none - * is found in CHIP NV storage. - */ -#define CHIP_DEVICE_CONFIG_USE_TEST_SERIAL_NUMBER "DUMMY_SN" - -#endif /* !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA */ - -/** - * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION - * - * The hardware version number assigned to device or product by the device vendor. This - * number is scoped to the device product id, and typically corresponds to a revision of the - * physical device, a change to its packaging, and/or a change to its marketing presentation. - * This value is generally *not* incremented for device software versions. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 100 - -#ifndef CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING "v0.1.0" -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING - * - * A string identifying the software version running on the device. - * CHIP currently expects the software version to be in the format - * {MAJOR_VERSION}.0d{MINOR_VERSION} - */ -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION NXP_CONFIG_DEVICE_SOFTWARE_VERSION -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "NXP Semiconductors" -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "NXP Demo App" -#endif - -#ifndef CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION -//-> format_version = 1 -//-> vendor_id = 0xFFF1 -//-> product_id_array = [ 0x8000, 0x8001, 0x8002, 0x8003, 0x8004, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009, 0x800A, 0x800B, -// 0x800C, 0x800D, 0x800E, 0x800F, 0x8010, 0x8011, 0x8012, 0x8013, 0x8014, 0x8015, 0x8016, 0x8017, 0x8018, 0x8019, 0x801A, -// 0x801B, 0x801C, 0x801D, 0x801E, 0x801F, 0x8020, 0x8021, 0x8022, 0x8023, 0x8024, 0x8025, 0x8026, 0x8027, 0x8028, 0x8029, -// 0x802A, 0x802B, 0x802C, 0x802D, 0x802E, 0x802F, 0x8030, 0x8031, 0x8032, 0x8033, 0x8034, 0x8035, 0x8036, 0x8037, 0x8038, -// 0x8039, 0x803A, 0x803B, 0x803C, 0x803D, 0x803E, 0x803F, 0x8040, 0x8041, 0x8042, 0x8043, 0x8044, 0x8045, 0x8046, 0x8047, -// 0x8048, 0x8049, 0x804A, 0x804B, 0x804C, 0x804D, 0x804E, 0x804F, 0x8050, 0x8051, 0x8052, 0x8053, 0x8054, 0x8055, 0x8056, -// 0x8057, 0x8058, 0x8059, 0x805A, 0x805B, 0x805C, 0x805D, 0x805E, 0x805F, 0x8060, 0x8061, 0x8062, 0x8063 ] -//-> device_type_id = 0x0016 -//-> certificate_id = "ZIG20142ZB330003-24" -//-> security_level = 0 -//-> security_information = 0 -//-> version_number = 0x2694 -//-> certification_type = 0 -//-> dac_origin_vendor_id is not present -//-> dac_origin_product_id is not present -#define CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION \ - { \ - 0x30, 0x82, 0x02, 0x19, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0x0a, 0x30, \ - 0x82, 0x02, 0x06, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, \ - 0x02, 0x01, 0x30, 0x82, 0x01, 0x71, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, \ - 0x01, 0x62, 0x04, 0x82, 0x01, 0x5e, 0x15, 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, \ - 0x05, 0x01, 0x80, 0x05, 0x02, 0x80, 0x05, 0x03, 0x80, 0x05, 0x04, 0x80, 0x05, 0x05, 0x80, 0x05, 0x06, 0x80, 0x05, \ - 0x07, 0x80, 0x05, 0x08, 0x80, 0x05, 0x09, 0x80, 0x05, 0x0a, 0x80, 0x05, 0x0b, 0x80, 0x05, 0x0c, 0x80, 0x05, 0x0d, \ - 0x80, 0x05, 0x0e, 0x80, 0x05, 0x0f, 0x80, 0x05, 0x10, 0x80, 0x05, 0x11, 0x80, 0x05, 0x12, 0x80, 0x05, 0x13, 0x80, \ - 0x05, 0x14, 0x80, 0x05, 0x15, 0x80, 0x05, 0x16, 0x80, 0x05, 0x17, 0x80, 0x05, 0x18, 0x80, 0x05, 0x19, 0x80, 0x05, \ - 0x1a, 0x80, 0x05, 0x1b, 0x80, 0x05, 0x1c, 0x80, 0x05, 0x1d, 0x80, 0x05, 0x1e, 0x80, 0x05, 0x1f, 0x80, 0x05, 0x20, \ - 0x80, 0x05, 0x21, 0x80, 0x05, 0x22, 0x80, 0x05, 0x23, 0x80, 0x05, 0x24, 0x80, 0x05, 0x25, 0x80, 0x05, 0x26, 0x80, \ - 0x05, 0x27, 0x80, 0x05, 0x28, 0x80, 0x05, 0x29, 0x80, 0x05, 0x2a, 0x80, 0x05, 0x2b, 0x80, 0x05, 0x2c, 0x80, 0x05, \ - 0x2d, 0x80, 0x05, 0x2e, 0x80, 0x05, 0x2f, 0x80, 0x05, 0x30, 0x80, 0x05, 0x31, 0x80, 0x05, 0x32, 0x80, 0x05, 0x33, \ - 0x80, 0x05, 0x34, 0x80, 0x05, 0x35, 0x80, 0x05, 0x36, 0x80, 0x05, 0x37, 0x80, 0x05, 0x38, 0x80, 0x05, 0x39, 0x80, \ - 0x05, 0x3a, 0x80, 0x05, 0x3b, 0x80, 0x05, 0x3c, 0x80, 0x05, 0x3d, 0x80, 0x05, 0x3e, 0x80, 0x05, 0x3f, 0x80, 0x05, \ - 0x40, 0x80, 0x05, 0x41, 0x80, 0x05, 0x42, 0x80, 0x05, 0x43, 0x80, 0x05, 0x44, 0x80, 0x05, 0x45, 0x80, 0x05, 0x46, \ - 0x80, 0x05, 0x47, 0x80, 0x05, 0x48, 0x80, 0x05, 0x49, 0x80, 0x05, 0x4a, 0x80, 0x05, 0x4b, 0x80, 0x05, 0x4c, 0x80, \ - 0x05, 0x4d, 0x80, 0x05, 0x4e, 0x80, 0x05, 0x4f, 0x80, 0x05, 0x50, 0x80, 0x05, 0x51, 0x80, 0x05, 0x52, 0x80, 0x05, \ - 0x53, 0x80, 0x05, 0x54, 0x80, 0x05, 0x55, 0x80, 0x05, 0x56, 0x80, 0x05, 0x57, 0x80, 0x05, 0x58, 0x80, 0x05, 0x59, \ - 0x80, 0x05, 0x5a, 0x80, 0x05, 0x5b, 0x80, 0x05, 0x5c, 0x80, 0x05, 0x5d, 0x80, 0x05, 0x5e, 0x80, 0x05, 0x5f, 0x80, \ - 0x05, 0x60, 0x80, 0x05, 0x61, 0x80, 0x05, 0x62, 0x80, 0x05, 0x63, 0x80, 0x18, 0x24, 0x03, 0x16, 0x2c, 0x04, 0x13, \ - 0x5a, 0x49, 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x34, \ - 0x24, 0x05, 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x94, 0x26, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7d, 0x30, 0x7b, 0x02, \ - 0x01, 0x03, 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, \ - 0xf5, 0x04, 0xf3, 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, \ - 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x24, 0xe5, \ - 0xd1, 0xf4, 0x7a, 0x7d, 0x7b, 0x0d, 0x20, 0x6a, 0x26, 0xef, 0x69, 0x9b, 0x7c, 0x97, 0x57, 0xb7, 0x2d, 0x46, 0x90, \ - 0x89, 0xde, 0x31, 0x92, 0xe6, 0x78, 0xc7, 0x45, 0xe7, 0xf6, 0x0c, 0x02, 0x21, 0x00, 0xf8, 0xaa, 0x2f, 0xa7, 0x11, \ - 0xfc, 0xb7, 0x9b, 0x97, 0xe3, 0x97, 0xce, 0xda, 0x66, 0x7b, 0xae, 0x46, 0x4e, 0x2b, 0xd3, 0xff, 0xdf, 0xc3, 0xcc, \ - 0xed, 0x7a, 0xa8, 0xca, 0x5f, 0x4c, 0x1a, 0x7c \ - } -#endif - -/** - * CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC - * - * Enables synchronizing the device's real time clock with a remote CHIP Time service - * using the CHIP Time Sync protocol. - */ -// #define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 1 - -/** - * CHIP_CONFIG_EVENT_LOGGING_WDM_OFFLOAD - * - * Select the ability to offload event logs to any interested subscribers using WDM. - */ -#define CHIP_CONFIG_EVENT_LOGGING_WDM_OFFLOAD 1 - -/** - * CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS - * - * Enable recording UTC timestamps. - */ -#define CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1 - -/** - * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE - * - * A size, in bytes, of the individual debug event logging buffer. - */ -#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512) - -/** - * CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE - * - * For a development build, set the default importance of events to be logged as Debug. - * Since debug is the lowest importance level, this means all standard, critical, info and - * debug importance level vi events get logged. - */ -#if BUILD_RELEASE -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Production -#else -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug -#endif // BUILD_RELEASE - -/* Increasing the retransmission interval of the MRP messages after subsequent failures */ -#ifndef CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL -#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32) -#endif - -#define CHIP_CONFIG_ENABLE_ACL_EXTENSIONS 1 diff --git a/examples/all-clusters-app/nxp/rt/rw61x/third_party/connectedhomeip b/examples/all-clusters-app/nxp/rt/rw61x/third_party/connectedhomeip deleted file mode 120000 index 305f2077ffe..00000000000 --- a/examples/all-clusters-app/nxp/rt/rw61x/third_party/connectedhomeip +++ /dev/null @@ -1 +0,0 @@ -../../../../../.. \ No newline at end of file diff --git a/examples/all-clusters-app/nxp/zephyr/CMakeLists.txt b/examples/all-clusters-app/nxp/zephyr/CMakeLists.txt index 0d0f66c0c86..a6852252fd5 100644 --- a/examples/all-clusters-app/nxp/zephyr/CMakeLists.txt +++ b/examples/all-clusters-app/nxp/zephyr/CMakeLists.txt @@ -88,6 +88,13 @@ if(CONFIG_CHIP_OTA_REQUESTOR) ) endif() +if (CONFIG_CHIP_FACTORY_DATA) + target_sources(app PRIVATE + ${CHIP_ROOT}/src/platform/nxp/zephyr/FactoryDataProviderImpl.cpp + ${CHIP_ROOT}/src/platform/nxp/common/factory_data/legacy/FactoryDataProvider.cpp + ) +endif() + chip_configure_data_model(app ZAP_FILE ${ALL_CLUSTERS_COMMON_DIR}/all-clusters-app.zap ) diff --git a/examples/all-clusters-app/realtek/data_model/all-clusters-app.matter b/examples/all-clusters-app/realtek/data_model/all-clusters-app.matter index 4ef3dc9175a..cd0429e71c4 100644 --- a/examples/all-clusters-app/realtek/data_model/all-clusters-app.matter +++ b/examples/all-clusters-app/realtek/data_model/all-clusters-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter index 285d3c79afc..9efdb6ac9c4 100644 --- a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter +++ b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/bridge-app/bridge-common/bridge-app.matter b/examples/bridge-app/bridge-common/bridge-app.matter index a6922edeaff..03797b95853 100644 --- a/examples/bridge-app/bridge-common/bridge-app.matter +++ b/examples/bridge-app/bridge-common/bridge-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/bridge-app/linux/bridged-actions-stub.cpp b/examples/bridge-app/linux/bridged-actions-stub.cpp index 80de3027db4..e55a382e2cd 100644 --- a/examples/bridge-app/linux/bridged-actions-stub.cpp +++ b/examples/bridge-app/linux/bridged-actions-stub.cpp @@ -263,5 +263,5 @@ void emberAfActionsClusterInitCallback(EndpointId endpoint) gLinuxActionsDelegateImpl.SetEndpointId(endpoint); sActionsServer = std::make_unique(endpoint, gLinuxActionsDelegateImpl); - sActionsServer->Init(); + TEMPORARY_RETURN_IGNORED sActionsServer->Init(); } diff --git a/examples/bridge-app/linux/main.cpp b/examples/bridge-app/linux/main.cpp index 22cd37ee826..aa8e3be5d3f 100644 --- a/examples/bridge-app/linux/main.cpp +++ b/examples/bridge-app/linux/main.cpp @@ -409,7 +409,7 @@ void CallReportingCallback(intptr_t closure) void ScheduleReportingCallback(Device * dev, ClusterId cluster, AttributeId attribute) { auto * path = Platform::New(dev->GetEndpointId(), cluster, attribute); - PlatformMgr().ScheduleWork(CallReportingCallback, reinterpret_cast(path)); + TEMPORARY_RETURN_IGNORED PlatformMgr().ScheduleWork(CallReportingCallback, reinterpret_cast(path)); } } // anonymous namespace @@ -490,12 +490,12 @@ Protocols::InteractionModel::Status HandleReadBridgedDeviceBasicAttribute(Device else if ((attributeId == NodeLabel::Id) && (maxReadLength == 32)) { MutableByteSpan zclNameSpan(buffer, maxReadLength); - MakeZclCharString(zclNameSpan, dev->GetName()); + TEMPORARY_RETURN_IGNORED MakeZclCharString(zclNameSpan, dev->GetName()); } else if ((attributeId == UniqueID::Id) && (maxReadLength == 32)) { MutableByteSpan zclUniqueIdSpan(buffer, maxReadLength); - MakeZclCharString(zclUniqueIdSpan, dev->GetUniqueId()); + TEMPORARY_RETURN_IGNORED MakeZclCharString(zclUniqueIdSpan, dev->GetUniqueId()); } else if ((attributeId == ConfigurationVersion::Id) && (maxReadLength == 4)) { @@ -678,35 +678,36 @@ class BridgedPowerSourceAttrAccess : public AttributeAccessInterface switch (aPath.mAttributeId) { case PowerSource::Attributes::BatChargeLevel::Id: - aEncoder.Encode(dev->GetBatChargeLevel()); + TEMPORARY_RETURN_IGNORED aEncoder.Encode(dev->GetBatChargeLevel()); break; case PowerSource::Attributes::Order::Id: - aEncoder.Encode(dev->GetOrder()); + TEMPORARY_RETURN_IGNORED aEncoder.Encode(dev->GetOrder()); break; case PowerSource::Attributes::Status::Id: - aEncoder.Encode(dev->GetStatus()); + TEMPORARY_RETURN_IGNORED aEncoder.Encode(dev->GetStatus()); break; case PowerSource::Attributes::Description::Id: - aEncoder.Encode(chip::CharSpan(dev->GetDescription().c_str(), dev->GetDescription().size())); + TEMPORARY_RETURN_IGNORED aEncoder.Encode( + chip::CharSpan(dev->GetDescription().c_str(), dev->GetDescription().size())); break; case PowerSource::Attributes::EndpointList::Id: { std::vector & list = dev->GetEndpointList(); DataModel::List dm_list(chip::Span(list.data(), list.size())); - aEncoder.Encode(dm_list); + TEMPORARY_RETURN_IGNORED aEncoder.Encode(dm_list); break; } case PowerSource::Attributes::ClusterRevision::Id: - aEncoder.Encode(ZCL_POWER_SOURCE_CLUSTER_REVISION); + TEMPORARY_RETURN_IGNORED aEncoder.Encode(ZCL_POWER_SOURCE_CLUSTER_REVISION); break; case PowerSource::Attributes::FeatureMap::Id: - aEncoder.Encode(dev->GetFeatureMap()); + TEMPORARY_RETURN_IGNORED aEncoder.Encode(dev->GetFeatureMap()); break; case PowerSource::Attributes::BatReplacementNeeded::Id: - aEncoder.Encode(false); + TEMPORARY_RETURN_IGNORED aEncoder.Encode(false); break; case PowerSource::Attributes::BatReplaceability::Id: - aEncoder.Encode(PowerSource::BatReplaceabilityEnum::kNotReplaceable); + TEMPORARY_RETURN_IGNORED aEncoder.Encode(PowerSource::BatReplaceabilityEnum::kNotReplaceable); break; default: return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); @@ -751,7 +752,7 @@ void runOnOffRoomAction(Room * room, bool actionOn, EndpointId endpointId, uint1 { Actions::Events::StateChanged::Type event{ actionID, invokeID, Actions::ActionStateEnum::kActive }; EventNumber eventNumber; - chip::app::LogEvent(event, endpointId, eventNumber); + TEMPORARY_RETURN_IGNORED chip::app::LogEvent(event, endpointId, eventNumber); } // Check and run the action for ActionLight1 - ActionLight4 @@ -776,7 +777,7 @@ void runOnOffRoomAction(Room * room, bool actionOn, EndpointId endpointId, uint1 { Actions::Events::StateChanged::Type event{ actionID, invokeID, Actions::ActionStateEnum::kInactive }; EventNumber eventNumber; - chip::app::LogEvent(event, endpointId, eventNumber); + TEMPORARY_RETURN_IGNORED chip::app::LogEvent(event, endpointId, eventNumber); } } @@ -1085,7 +1086,7 @@ void ApplicationInit() if ((!path.empty()) and (sChipNamedPipeCommands.Start(path, &sBridgeCommandDelegate) != CHIP_NO_ERROR)) { ChipLogError(NotSpecified, "Failed to start CHIP NamedPipeCommands"); - sChipNamedPipeCommands.Stop(); + TEMPORARY_RETURN_IGNORED sChipNamedPipeCommands.Stop(); } AttributeAccessInterfaceRegistry::Instance().Register(&gPowerAttrAccess); @@ -1165,5 +1166,6 @@ void BridgeCommandDelegate::OnEventCommandReceived(const char * json) return; } - chip::DeviceLayer::PlatformMgr().ScheduleWork(BridgeAppCommandHandler::HandleCommand, reinterpret_cast(handler)); + TEMPORARY_RETURN_IGNORED chip::DeviceLayer::PlatformMgr().ScheduleWork(BridgeAppCommandHandler::HandleCommand, + reinterpret_cast(handler)); } diff --git a/examples/camera-app/camera-common/BUILD.gn b/examples/camera-app/camera-common/BUILD.gn index 55b2a8c0478..d4ec07e1620 100644 --- a/examples/camera-app/camera-common/BUILD.gn +++ b/examples/camera-app/camera-common/BUILD.gn @@ -41,7 +41,6 @@ source_set("camera-lib") { "include/camera-device-interface.h", "include/media-controller/media-controller.h", "include/transport/transport.h", - "include/webrtc-provider-controller/webrtc-provider-controller.h", "src/camera-app.cpp", ] @@ -56,7 +55,12 @@ source_set("camera-lib") { deps = [ "${chip_root}/examples/camera-app/camera-common", + "${chip_root}/src/app/clusters/camera-av-settings-user-level-management-server", "${chip_root}/src/app/clusters/push-av-stream-transport-server", + "${chip_root}/src/app/clusters/webrtc-transport-provider-server", "${chip_root}/src/lib", ] + + public_deps = + [ "${chip_root}/src/app/clusters/camera-av-stream-management-server" ] } diff --git a/examples/camera-app/camera-common/camera-app.matter b/examples/camera-app/camera-common/camera-app.matter index 4bbbdf12283..4c595f9c0d2 100644 --- a/examples/camera-app/camera-common/camera-app.matter +++ b/examples/camera-app/camera-common/camera-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } @@ -2528,279 +2530,6 @@ cluster ZoneManagement = 1360 { command access(invoke: manage) RemoveTrigger(RemoveTriggerRequest): DefaultSuccess = 5; } -/** The Camera AV Stream Management cluster is used to allow clients to manage, control, and configure various audio, video, and snapshot streams on a camera. */ -cluster CameraAvStreamManagement = 1361 { - revision 1; - - enum AudioCodecEnum : enum8 { - kOPUS = 0 [spec_name = "OPUS"]; - kAACLC = 1 [spec_name = "AAC-LC"]; - } - - enum ImageCodecEnum : enum8 { - kJPEG = 0 [spec_name = "JPEG"]; - } - - enum TriStateAutoEnum : enum8 { - kOff = 0; - kOn = 1; - kAuto = 2; - } - - enum TwoWayTalkSupportTypeEnum : enum8 { - kNotSupported = 0; - kHalfDuplex = 1; - kFullDuplex = 2; - } - - enum VideoCodecEnum : enum8 { - kH264 = 0; - kHEVC = 1 [spec_name = "HEVC"]; - kVVC = 2 [spec_name = "VVC"]; - kAV1 = 3 [spec_name = "AV1"]; - } - - bitmap Feature : bitmap32 { - kAudio = 0x1; - kVideo = 0x2; - kSnapshot = 0x4; - kPrivacy = 0x8; - kSpeaker = 0x10; - kImageControl = 0x20; - kWatermark = 0x40; - kOnScreenDisplay = 0x80; - kLocalStorage = 0x100; - kHighDynamicRange = 0x200; - kNightVision = 0x400; - } - - struct VideoResolutionStruct { - int16u width = 0; - int16u height = 1; - } - - struct VideoStreamStruct { - int16u videoStreamID = 0; - StreamUsageEnum streamUsage = 1; - VideoCodecEnum videoCodec = 2; - int16u minFrameRate = 3; - int16u maxFrameRate = 4; - VideoResolutionStruct minResolution = 5; - VideoResolutionStruct maxResolution = 6; - int32u minBitRate = 7; - int32u maxBitRate = 8; - int16u keyFrameInterval = 9; - optional boolean watermarkEnabled = 10; - optional boolean OSDEnabled = 11; - int8u referenceCount = 12; - } - - struct SnapshotStreamStruct { - int16u snapshotStreamID = 0; - ImageCodecEnum imageCodec = 1; - int16u frameRate = 2; - VideoResolutionStruct minResolution = 3; - VideoResolutionStruct maxResolution = 4; - int8u quality = 5; - int8u referenceCount = 6; - boolean encodedPixels = 7; - boolean hardwareEncoder = 8; - optional boolean watermarkEnabled = 9; - optional boolean OSDEnabled = 10; - } - - struct SnapshotCapabilitiesStruct { - VideoResolutionStruct resolution = 0; - int16u maxFrameRate = 1; - ImageCodecEnum imageCodec = 2; - boolean requiresEncodedPixels = 3; - optional boolean requiresHardwareEncoder = 4; - } - - struct RateDistortionTradeOffPointsStruct { - VideoCodecEnum codec = 0; - VideoResolutionStruct resolution = 1; - int32u minBitRate = 2; - } - - struct AudioCapabilitiesStruct { - int8u maxNumberOfChannels = 0; - AudioCodecEnum supportedCodecs[] = 1; - int32u supportedSampleRates[] = 2; - int8u supportedBitDepths[] = 3; - } - - struct AudioStreamStruct { - int16u audioStreamID = 0; - StreamUsageEnum streamUsage = 1; - AudioCodecEnum audioCodec = 2; - int8u channelCount = 3; - int32u sampleRate = 4; - int32u bitRate = 5; - int8u bitDepth = 6; - int8u referenceCount = 7; - } - - struct VideoSensorParamsStruct { - int16u sensorWidth = 0; - int16u sensorHeight = 1; - int16u maxFPS = 2; - optional int16u maxHDRFPS = 3; - } - - readonly attribute optional int8u maxConcurrentEncoders = 0; - readonly attribute optional int32u maxEncodedPixelRate = 1; - readonly attribute optional VideoSensorParamsStruct videoSensorParams = 2; - readonly attribute optional boolean nightVisionUsesInfrared = 3; - readonly attribute optional VideoResolutionStruct minViewportResolution = 4; - readonly attribute optional RateDistortionTradeOffPointsStruct rateDistortionTradeOffPoints[] = 5; - readonly attribute int32u maxContentBufferSize = 6; - readonly attribute optional AudioCapabilitiesStruct microphoneCapabilities = 7; - readonly attribute optional AudioCapabilitiesStruct speakerCapabilities = 8; - readonly attribute optional TwoWayTalkSupportTypeEnum twoWayTalkSupport = 9; - readonly attribute optional SnapshotCapabilitiesStruct snapshotCapabilities[] = 10; - readonly attribute int32u maxNetworkBandwidth = 11; - readonly attribute optional int16u currentFrameRate = 12; - attribute access(read: manage, write: manage) optional boolean HDRModeEnabled = 13; - readonly attribute StreamUsageEnum supportedStreamUsages[] = 14; - readonly attribute optional VideoStreamStruct allocatedVideoStreams[] = 15; - readonly attribute optional AudioStreamStruct allocatedAudioStreams[] = 16; - readonly attribute optional SnapshotStreamStruct allocatedSnapshotStreams[] = 17; - readonly attribute StreamUsageEnum streamUsagePriorities[] = 18; - attribute optional boolean softRecordingPrivacyModeEnabled = 19; - attribute optional boolean softLivestreamPrivacyModeEnabled = 20; - readonly attribute optional boolean hardPrivacyModeOn = 21; - attribute access(read: manage, write: manage) optional TriStateAutoEnum nightVision = 22; - attribute access(read: manage, write: manage) optional TriStateAutoEnum nightVisionIllum = 23; - attribute access(read: manage, write: manage) optional ViewportStruct viewport = 24; - attribute access(read: manage, write: manage) optional boolean speakerMuted = 25; - attribute access(read: manage, write: manage) optional int8u speakerVolumeLevel = 26; - readonly attribute access(read: manage) optional int8u speakerMaxLevel = 27; - readonly attribute access(read: manage) optional int8u speakerMinLevel = 28; - attribute access(read: manage, write: manage) optional boolean microphoneMuted = 29; - attribute access(read: manage, write: manage) optional int8u microphoneVolumeLevel = 30; - readonly attribute access(read: manage) optional int8u microphoneMaxLevel = 31; - readonly attribute access(read: manage) optional int8u microphoneMinLevel = 32; - attribute access(read: manage, write: manage) optional boolean microphoneAGCEnabled = 33; - attribute access(read: manage, write: manage) optional int16u imageRotation = 34; - attribute access(read: manage, write: manage) optional boolean imageFlipHorizontal = 35; - attribute access(read: manage, write: manage) optional boolean imageFlipVertical = 36; - attribute access(read: manage, write: manage) optional boolean localVideoRecordingEnabled = 37; - attribute access(read: manage, write: manage) optional boolean localSnapshotRecordingEnabled = 38; - attribute access(read: manage, write: manage) optional boolean statusLightEnabled = 39; - attribute access(read: manage, write: manage) optional ThreeLevelAutoEnum statusLightBrightness = 40; - readonly attribute command_id generatedCommandList[] = 65528; - readonly attribute command_id acceptedCommandList[] = 65529; - readonly attribute attrib_id attributeList[] = 65531; - readonly attribute bitmap32 featureMap = 65532; - readonly attribute int16u clusterRevision = 65533; - - request struct AudioStreamAllocateRequest { - StreamUsageEnum streamUsage = 0; - AudioCodecEnum audioCodec = 1; - int8u channelCount = 2; - int32u sampleRate = 3; - int32u bitRate = 4; - int8u bitDepth = 5; - } - - response struct AudioStreamAllocateResponse = 1 { - int16u audioStreamID = 0; - } - - request struct AudioStreamDeallocateRequest { - int16u audioStreamID = 0; - } - - request struct VideoStreamAllocateRequest { - StreamUsageEnum streamUsage = 0; - VideoCodecEnum videoCodec = 1; - int16u minFrameRate = 2; - int16u maxFrameRate = 3; - VideoResolutionStruct minResolution = 4; - VideoResolutionStruct maxResolution = 5; - int32u minBitRate = 6; - int32u maxBitRate = 7; - int16u keyFrameInterval = 8; - optional boolean watermarkEnabled = 9; - optional boolean OSDEnabled = 10; - } - - response struct VideoStreamAllocateResponse = 4 { - int16u videoStreamID = 0; - } - - request struct VideoStreamModifyRequest { - int16u videoStreamID = 0; - optional boolean watermarkEnabled = 1; - optional boolean OSDEnabled = 2; - } - - request struct VideoStreamDeallocateRequest { - int16u videoStreamID = 0; - } - - request struct SnapshotStreamAllocateRequest { - ImageCodecEnum imageCodec = 0; - int16u maxFrameRate = 1; - VideoResolutionStruct minResolution = 2; - VideoResolutionStruct maxResolution = 3; - int8u quality = 4; - optional boolean watermarkEnabled = 5; - optional boolean OSDEnabled = 6; - } - - response struct SnapshotStreamAllocateResponse = 8 { - int16u snapshotStreamID = 0; - } - - request struct SnapshotStreamModifyRequest { - int16u snapshotStreamID = 0; - optional boolean watermarkEnabled = 1; - optional boolean OSDEnabled = 2; - } - - request struct SnapshotStreamDeallocateRequest { - int16u snapshotStreamID = 0; - } - - request struct SetStreamPrioritiesRequest { - StreamUsageEnum streamPriorities[] = 0; - } - - request struct CaptureSnapshotRequest { - nullable int16u snapshotStreamID = 0; - VideoResolutionStruct requestedResolution = 1; - } - - response struct CaptureSnapshotResponse = 13 { - octet_string data = 0; - ImageCodecEnum imageCodec = 1; - VideoResolutionStruct resolution = 2; - } - - /** This command SHALL allocate an audio stream on the camera and return an allocated audio stream identifier. */ - command access(invoke: manage) AudioStreamAllocate(AudioStreamAllocateRequest): AudioStreamAllocateResponse = 0; - /** This command SHALL deallocate an audio stream on the camera, corresponding to the given audio stream identifier. */ - command access(invoke: manage) AudioStreamDeallocate(AudioStreamDeallocateRequest): DefaultSuccess = 2; - /** This command SHALL allocate a video stream on the camera and return an allocated video stream identifier. */ - command access(invoke: manage) VideoStreamAllocate(VideoStreamAllocateRequest): VideoStreamAllocateResponse = 3; - /** This command SHALL be used to modify a stream specified by the VideoStreamID. */ - command access(invoke: manage) VideoStreamModify(VideoStreamModifyRequest): DefaultSuccess = 5; - /** This command SHALL deallocate a video stream on the camera, corresponding to the given video stream identifier. */ - command access(invoke: manage) VideoStreamDeallocate(VideoStreamDeallocateRequest): DefaultSuccess = 6; - /** This command SHALL allocate a snapshot stream on the device and return an allocated snapshot stream identifier. */ - command access(invoke: manage) SnapshotStreamAllocate(SnapshotStreamAllocateRequest): SnapshotStreamAllocateResponse = 7; - /** This command SHALL be used to modify a stream specified by the VideoStreamID. */ - command access(invoke: manage) SnapshotStreamModify(SnapshotStreamModifyRequest): DefaultSuccess = 9; - /** This command SHALL deallocate an snapshot stream on the camera, corresponding to the given snapshot stream identifier. */ - command access(invoke: manage) SnapshotStreamDeallocate(SnapshotStreamDeallocateRequest): DefaultSuccess = 10; - /** This command SHALL set the relative priorities of the various stream usages on the camera. */ - command access(invoke: administer) SetStreamPriorities(SetStreamPrioritiesRequest): DefaultSuccess = 11; - /** This command SHALL return a Snapshot from the camera. */ - command CaptureSnapshot(CaptureSnapshotRequest): CaptureSnapshotResponse = 12; -} - /** This cluster provides an interface into controls associated with the operation of a device that provides pan, tilt, and zoom functions, either mechanically, or against a digital image. */ cluster CameraAvSettingsUserLevelManagement = 1362 { revision 1; @@ -2906,7 +2635,7 @@ cluster CameraAvSettingsUserLevelManagement = 1362 { /** The WebRTC transport provider cluster provides a way for stream providers (e.g. Cameras) to stream or receive their data through WebRTC. */ cluster WebRTCTransportProvider = 1363 { - revision 1; + revision 2; bitmap Feature : bitmap32 { kMetadata = 0x1; @@ -2934,6 +2663,8 @@ cluster WebRTCTransportProvider = 1363 { optional char_string<16> ICETransportPolicy = 5; optional boolean metadataEnabled = 6; optional SFrameStruct SFrameConfig = 7; + optional int16u videoStreams[] = 8; + optional int16u audioStreams[] = 9; } response struct SolicitOfferResponse = 1 { @@ -2954,6 +2685,8 @@ cluster WebRTCTransportProvider = 1363 { optional char_string<16> ICETransportPolicy = 7; optional boolean metadataEnabled = 8; optional SFrameStruct SFrameConfig = 9; + optional int16u videoStreams[] = 10; + optional int16u audioStreams[] = 11; } response struct ProvideOfferResponse = 3 { @@ -2991,7 +2724,7 @@ cluster WebRTCTransportProvider = 1363 { /** The WebRTC transport requestor cluster provides a way for stream consumers (e.g. Matter Stream Viewer) to establish a WebRTC connection with a stream provider. */ cluster WebRTCTransportRequestor = 1364 { - revision 1; + revision 2; readonly attribute access(read: administer) WebRTCSessionStruct currentSessions[] = 0; readonly attribute command_id generatedCommandList[] = 65528; @@ -3034,7 +2767,7 @@ cluster WebRTCTransportRequestor = 1364 { /** This cluster implements the upload of Audio and Video streams from the Push AV Stream Transport Cluster using suitable push-based transports. */ cluster PushAvStreamTransport = 1365 { - revision 1; + revision 2; enum CMAFInterfaceEnum : enum8 { kInterface1 = 0; @@ -3061,6 +2794,8 @@ cluster PushAvStreamTransport = 1365 { kInvalidOptions = 9; kInvalidStreamUsage = 10; kInvalidTime = 11; + kInvalidPreRollLength = 12; + kDuplicateStreamValues = 13; } enum TransportStatusEnum : enum8 { @@ -3078,6 +2813,7 @@ cluster PushAvStreamTransport = 1365 { kUserInitiated = 0; kAutomation = 1; kEmergency = 2; + kDoorbellPressed = 3; } bitmap Feature : bitmap32 { @@ -3097,6 +2833,16 @@ cluster PushAvStreamTransport = 1365 { optional int8u sensitivity = 1; } + struct AudioStreamStruct { + char_string<16> audioStreamName = 0; + int16u audioStreamID = 1; + } + + struct VideoStreamStruct { + char_string<16> videoStreamName = 0; + int16u videoStreamID = 1; + } + struct TransportTriggerOptionsStruct { TransportTriggerTypeEnum triggerType = 0; optional nullable TransportZoneOptionsStruct motionZones[] = 1; @@ -3131,6 +2877,8 @@ cluster PushAvStreamTransport = 1365 { IngestMethodsEnum ingestMethod = 6; ContainerOptionsStruct containerOptions = 7; optional epoch_s expiryTime = 8; + optional VideoStreamStruct videoStreams[] = 9; + optional AudioStreamStruct audioStreams[] = 10; } fabric_scoped struct TransportConfigurationStruct { @@ -3149,10 +2897,14 @@ cluster PushAvStreamTransport = 1365 { int16u connectionID = 0; TransportTriggerTypeEnum triggerType = 1; optional TriggerActivationReasonEnum activationReason = 2; + ContainerFormatEnum containerType = 3; + optional int64u CMAFSessionNumber = 4; } info event PushTransportEnd = 1 { int16u connectionID = 0; + ContainerFormatEnum containerType = 1; + optional int64u CMAFSessionNumber = 2; } readonly attribute SupportedFormatStruct supportedFormats[] = 0; @@ -3216,13 +2968,17 @@ cluster PushAvStreamTransport = 1365 { /** This cluster provides facilities to configure and play Chime sounds, such as those used in a doorbell. */ cluster Chime = 1366 { - revision 1; + revision 2; struct ChimeSoundStruct { int8u chimeID = 0; char_string<48> name = 1; } + info event ChimeStartedPlaying = 0 { + int8u chimeID = 0; + } + readonly attribute ChimeSoundStruct installedChimeSounds[] = 0; attribute int8u selectedChime = 1; attribute boolean enabled = 2; @@ -3232,7 +2988,12 @@ cluster Chime = 1366 { readonly attribute bitmap32 featureMap = 65532; readonly attribute int16u clusterRevision = 65533; - command PlayChimeSound(): DefaultSuccess = 0; + request struct PlayChimeSoundRequest { + optional int8u chimeID = 0; + } + + /** This command will play the currently selected chime or the chime passed in. */ + command PlayChimeSound(PlayChimeSoundRequest): DefaultSuccess = 0; } /** This Cluster is used to manage TLS Client Certificates and to provision @@ -3919,85 +3680,21 @@ endpoint 1 { handle command RemoveTrigger; } - server cluster CameraAvStreamManagement { - callback attribute maxConcurrentEncoders; - callback attribute maxEncodedPixelRate; - callback attribute videoSensorParams; - callback attribute nightVisionUsesInfrared; - callback attribute minViewportResolution; - callback attribute rateDistortionTradeOffPoints; - callback attribute maxContentBufferSize; - callback attribute microphoneCapabilities; - callback attribute speakerCapabilities; - callback attribute twoWayTalkSupport; - callback attribute snapshotCapabilities; - callback attribute maxNetworkBandwidth; - callback attribute currentFrameRate; - callback attribute HDRModeEnabled; - callback attribute supportedStreamUsages; - callback attribute allocatedVideoStreams; - callback attribute allocatedAudioStreams; - callback attribute allocatedSnapshotStreams; - callback attribute streamUsagePriorities; - callback attribute softRecordingPrivacyModeEnabled; - callback attribute softLivestreamPrivacyModeEnabled; - callback attribute hardPrivacyModeOn; - callback attribute nightVision; - callback attribute nightVisionIllum; - callback attribute viewport; - callback attribute speakerMuted; - callback attribute speakerVolumeLevel; - callback attribute speakerMaxLevel; - callback attribute speakerMinLevel; - callback attribute microphoneMuted; - callback attribute microphoneVolumeLevel; - callback attribute microphoneMaxLevel; - callback attribute microphoneMinLevel; - callback attribute microphoneAGCEnabled; - callback attribute imageRotation; - callback attribute imageFlipHorizontal; - callback attribute imageFlipVertical; - callback attribute localVideoRecordingEnabled; - callback attribute localSnapshotRecordingEnabled; - callback attribute statusLightEnabled; - callback attribute statusLightBrightness; - callback attribute generatedCommandList; - callback attribute acceptedCommandList; - callback attribute attributeList; - callback attribute featureMap; - ram attribute clusterRevision default = 1; - - handle command AudioStreamAllocate; - handle command AudioStreamAllocateResponse; - handle command AudioStreamDeallocate; - handle command VideoStreamAllocate; - handle command VideoStreamAllocateResponse; - handle command VideoStreamModify; - handle command VideoStreamDeallocate; - handle command SnapshotStreamAllocate; - handle command SnapshotStreamAllocateResponse; - handle command SnapshotStreamModify; - handle command SnapshotStreamDeallocate; - handle command SetStreamPriorities; - handle command CaptureSnapshot; - handle command CaptureSnapshotResponse; - } - server cluster CameraAvSettingsUserLevelManagement { callback attribute MPTZPosition; - ram attribute maxPresets default = 5; + callback attribute maxPresets; callback attribute MPTZPresets; callback attribute DPTZStreams; - ram attribute zoomMax default = 100; - ram attribute tiltMin default = -90; - ram attribute tiltMax default = 90; - ram attribute panMin default = -180; - ram attribute panMax default = 180; - ram attribute movementState; + callback attribute zoomMax; + callback attribute tiltMin; + callback attribute tiltMax; + callback attribute panMin; + callback attribute panMax; + callback attribute movementState; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute attributeList; - ram attribute featureMap default = 31; + callback attribute featureMap; ram attribute clusterRevision default = 1; handle command MPTZSetPosition; diff --git a/examples/camera-app/camera-common/camera-app.zap b/examples/camera-app/camera-common/camera-app.zap index cfd548634d9..c18aaa65119 100644 --- a/examples/camera-app/camera-common/camera-app.zap +++ b/examples/camera-app/camera-common/camera-app.zap @@ -5636,867 +5636,6 @@ } ] }, - { - "name": "Camera AV Stream Management", - "code": 1361, - "mfgCode": null, - "define": "CAMERA_AV_STREAM_MANAGEMENT_CLUSTER", - "side": "server", - "enabled": 1, - "apiMaturity": "provisional", - "commands": [ - { - "name": "AudioStreamAllocate", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "AudioStreamAllocateResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "AudioStreamDeallocate", - "code": 2, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "VideoStreamAllocate", - "code": 3, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "VideoStreamAllocateResponse", - "code": 4, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "VideoStreamModify", - "code": 5, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "VideoStreamDeallocate", - "code": 6, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "SnapshotStreamAllocate", - "code": 7, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "SnapshotStreamAllocateResponse", - "code": 8, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "SnapshotStreamModify", - "code": 9, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "SnapshotStreamDeallocate", - "code": 10, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "SetStreamPriorities", - "code": 11, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "CaptureSnapshot", - "code": 12, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "CaptureSnapshotResponse", - "code": 13, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "MaxConcurrentEncoders", - "code": 0, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MaxEncodedPixelRate", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "int32u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "VideoSensorParams", - "code": 2, - "mfgCode": null, - "side": "server", - "type": "VideoSensorParamsStruct", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "NightVisionUsesInfrared", - "code": 3, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MinViewportResolution", - "code": 4, - "mfgCode": null, - "side": "server", - "type": "VideoResolutionStruct", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "RateDistortionTradeOffPoints", - "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": "MaxContentBufferSize", - "code": 6, - "mfgCode": null, - "side": "server", - "type": "int32u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MicrophoneCapabilities", - "code": 7, - "mfgCode": null, - "side": "server", - "type": "AudioCapabilitiesStruct", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "SpeakerCapabilities", - "code": 8, - "mfgCode": null, - "side": "server", - "type": "AudioCapabilitiesStruct", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "TwoWayTalkSupport", - "code": 9, - "mfgCode": null, - "side": "server", - "type": "TwoWayTalkSupportTypeEnum", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "SnapshotCapabilities", - "code": 10, - "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": "MaxNetworkBandwidth", - "code": 11, - "mfgCode": null, - "side": "server", - "type": "int32u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "CurrentFrameRate", - "code": 12, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "HDRModeEnabled", - "code": 13, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "SupportedStreamUsages", - "code": 14, - "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": "AllocatedVideoStreams", - "code": 15, - "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": "AllocatedAudioStreams", - "code": 16, - "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": "AllocatedSnapshotStreams", - "code": 17, - "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": "StreamUsagePriorities", - "code": 18, - "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": "SoftRecordingPrivacyModeEnabled", - "code": 19, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "SoftLivestreamPrivacyModeEnabled", - "code": 20, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "HardPrivacyModeOn", - "code": 21, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "NightVision", - "code": 22, - "mfgCode": null, - "side": "server", - "type": "TriStateAutoEnum", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "NightVisionIllum", - "code": 23, - "mfgCode": null, - "side": "server", - "type": "TriStateAutoEnum", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "Viewport", - "code": 24, - "mfgCode": null, - "side": "server", - "type": "ViewportStruct", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "SpeakerMuted", - "code": 25, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "SpeakerVolumeLevel", - "code": 26, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "SpeakerMaxLevel", - "code": 27, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "SpeakerMinLevel", - "code": 28, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MicrophoneMuted", - "code": 29, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MicrophoneVolumeLevel", - "code": 30, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MicrophoneMaxLevel", - "code": 31, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MicrophoneMinLevel", - "code": 32, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MicrophoneAGCEnabled", - "code": 33, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ImageRotation", - "code": 34, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ImageFlipHorizontal", - "code": 35, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ImageFlipVertical", - "code": 36, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "LocalVideoRecordingEnabled", - "code": 37, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "LocalSnapshotRecordingEnabled", - "code": 38, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "StatusLightEnabled", - "code": 39, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "StatusLightBrightness", - "code": 40, - "mfgCode": null, - "side": "server", - "type": "ThreeLevelAutoEnum", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "GeneratedCommandList", - "code": 65528, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AcceptedCommandList", - "code": 65529, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AttributeList", - "code": 65531, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "FeatureMap", - "code": 65532, - "mfgCode": null, - "side": "server", - "type": "bitmap32", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ClusterRevision", - "code": 65533, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "1", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - } - ] - }, { "name": "Camera AV Settings User Level Management", "code": 1362, diff --git a/examples/camera-app/camera-common/include/camera-app.h b/examples/camera-app/camera-common/include/camera-app.h index 9c202867818..272d0e66bf5 100644 --- a/examples/camera-app/camera-common/include/camera-app.h +++ b/examples/camera-app/camera-common/include/camera-app.h @@ -23,6 +23,7 @@ #include "camera-device-interface.h" #include #include +#include #include #include @@ -45,15 +46,18 @@ class CameraApp CameraDeviceInterface * mCameraDevice; // SDK cluster servers - std::unique_ptr mWebRTCTransportProviderPtr; + chip::app::LazyRegisteredServerCluster + mWebRTCTransportProviderServer; std::unique_ptr mChimeServerPtr; - std::unique_ptr mAVStreamMgmtServerPtr; - std::unique_ptr - mAVSettingsUserLevelMgmtServerPtr; + chip::app::LazyRegisteredServerCluster + mAVSettingsUserLevelMgmtServer; + chip::app::LazyRegisteredServerCluster + mAVStreamMgmtServer; std::unique_ptr mZoneMgmtServerPtr; - // Helper to set attribute defaults for CameraAVStreamMgmt - void InitializeCameraAVStreamMgmt(); + // Method to instantiate CameraAVStreamMgmt and set attribute defaults for initialization. + void CreateAndInitializeCameraAVStreamMgmt(); + CHIP_ERROR InitializeCameraAVStreamMgmt(); }; void CameraAppInit(CameraDeviceInterface * cameraDevice); diff --git a/examples/camera-app/camera-common/include/camera-avstream-controller/camera-avstream-controller.h b/examples/camera-app/camera-common/include/camera-avstream-controller/camera-avstream-controller.h index ab38790fd56..ee9f8ae279c 100644 --- a/examples/camera-app/camera-common/include/camera-avstream-controller/camera-avstream-controller.h +++ b/examples/camera-app/camera-common/include/camera-avstream-controller/camera-avstream-controller.h @@ -18,7 +18,8 @@ #pragma once -#include +#include +#include namespace chip { namespace app { @@ -33,13 +34,17 @@ class CameraAVStreamController public: virtual ~CameraAVStreamController() = default; - virtual CHIP_ERROR ValidateStreamUsage(StreamUsageEnum streamUsage, Optional> & videoStreamId, - Optional> & audioStreamId) = 0; + virtual CHIP_ERROR ValidateStreamUsage(StreamUsageEnum streamUsage, Optional> & videoStreams, + Optional> & audioStreams) = 0; virtual CHIP_ERROR ValidateVideoStreamID(uint16_t videoStreamId) = 0; virtual CHIP_ERROR ValidateAudioStreamID(uint16_t audioStreamId) = 0; + virtual CHIP_ERROR ValidateVideoStreams(const std::vector & videoStreams) = 0; + + virtual CHIP_ERROR ValidateAudioStreams(const std::vector & audioStreams) = 0; + virtual CHIP_ERROR IsHardPrivacyModeActive(bool & isActive) = 0; virtual CHIP_ERROR IsSoftRecordingPrivacyModeActive(bool & isActive) = 0; @@ -64,6 +69,20 @@ class CameraAVStreamController virtual void GetBandwidthForStreams(const Optional> & videoStreamId, const Optional> & audioStreamId, uint32_t & outBandwidthbps) = 0; + + /** + * @brief Called by transports when they start using the corresponding audio and video streams. + * + */ + virtual CHIP_ERROR OnTransportAcquireAudioVideoStreams(const std::vector & audioStreams, + const std::vector & videoStreams) = 0; + + /** + * @brief Called by transports when they release the corresponding audio and video streams. + * + */ + virtual CHIP_ERROR OnTransportReleaseAudioVideoStreams(const std::vector & audioStreams, + const std::vector & videoStreams) = 0; }; } // namespace CameraAvStreamManagement diff --git a/examples/camera-app/camera-common/include/camera-device-interface.h b/examples/camera-app/camera-common/include/camera-device-interface.h index 77465263909..d17a4d5a473 100644 --- a/examples/camera-app/camera-common/include/camera-device-interface.h +++ b/examples/camera-app/camera-common/include/camera-device-interface.h @@ -19,12 +19,11 @@ #pragma once #include "camera-avstream-controller.h" #include "media-controller.h" -#include "webrtc-provider-controller.h" -#include -#include +#include +#include #include -#include -#include +#include +#include #include using chip::app::Clusters::CameraAvStreamManagement::AudioCapabilitiesStruct; @@ -72,8 +71,8 @@ struct AudioStream bool IsCompatible(const AudioStreamStruct & inputParams) const { return (audioStreamParams.audioCodec == inputParams.audioCodec && - audioStreamParams.channelCount == inputParams.channelCount && - audioStreamParams.sampleRate == inputParams.sampleRate && audioStreamParams.bitDepth == inputParams.bitDepth); + audioStreamParams.channelCount >= inputParams.channelCount && + audioStreamParams.sampleRate >= inputParams.sampleRate && audioStreamParams.bitDepth >= inputParams.bitDepth); } }; @@ -84,8 +83,9 @@ struct SnapshotStream void * snapshotContext; // Platform-specific context object associated with // snapshot stream; - bool IsCompatible(const chip::app::Clusters::CameraAvStreamManagement::CameraAVStreamMgmtDelegate::SnapshotStreamAllocateArgs & - inputParams) const + bool + IsCompatible(const chip::app::Clusters::CameraAvStreamManagement::CameraAVStreamManagementDelegate::SnapshotStreamAllocateArgs & + inputParams) const { return (snapshotStreamParams.imageCodec == inputParams.imageCodec && snapshotStreamParams.frameRate <= inputParams.maxFrameRate && @@ -125,17 +125,18 @@ class CameraDeviceInterface // Getter for WebRTCProvider Delegate virtual chip::app::Clusters::WebRTCTransportProvider::Delegate & GetWebRTCProviderDelegate() = 0; - // Getter for WebRTCProvider Controller - virtual chip::app::Clusters::WebRTCTransportProvider::WebRTCTransportProviderController & GetWebRTCProviderController() = 0; + // Set the WebRTC Transport Provider server instance + virtual void + SetWebRTCTransportProvider(chip::app::Clusters::WebRTCTransportProvider::WebRTCTransportProviderCluster * provider) = 0; // Getter for CameraAVStreamManagement Delegate - virtual chip::app::Clusters::CameraAvStreamManagement::CameraAVStreamMgmtDelegate & GetCameraAVStreamMgmtDelegate() = 0; + virtual chip::app::Clusters::CameraAvStreamManagement::CameraAVStreamManagementDelegate & GetCameraAVStreamMgmtDelegate() = 0; // Getter for CameraAVStreamManagement Controller virtual chip::app::Clusters::CameraAvStreamManagement::CameraAVStreamController & GetCameraAVStreamMgmtController() = 0; // Getter for CameraAVSettingsUserLevelManagement Delegate - virtual chip::app::Clusters::CameraAvSettingsUserLevelManagement::Delegate & GetCameraAVSettingsUserLevelMgmtDelegate() = 0; + virtual chip::app::Clusters::CameraAvSettingsUserLevelManagementDelegate & GetCameraAVSettingsUserLevelMgmtDelegate() = 0; // Getter for ZoneManagement Delegate virtual chip::app::Clusters::ZoneManagement::Delegate & GetZoneManagementDelegate() = 0; @@ -146,8 +147,6 @@ class CameraDeviceInterface // Getter for PushAVStreamTransport Delegate virtual chip::app::Clusters::PushAvStreamTransportDelegate & GetPushAVTransportDelegate() = 0; - virtual void HandlePushAvZoneTrigger(uint16_t zoneId) = 0; - // Class defining the Camera HAL interface class CameraHALInterface { @@ -186,7 +185,8 @@ class CameraDeviceInterface // Allocate snapshot stream virtual CameraError AllocateSnapshotStream( - const chip::app::Clusters::CameraAvStreamManagement::CameraAVStreamMgmtDelegate::SnapshotStreamAllocateArgs & args, + const chip::app::Clusters::CameraAvStreamManagement::CameraAVStreamManagementDelegate::SnapshotStreamAllocateArgs & + args, uint16_t & outStreamID) = 0; // Start snapshot stream @@ -388,7 +388,7 @@ class CameraDeviceInterface UpdateZoneTrigger(const chip::app::Clusters::ZoneManagement::ZoneTriggerControlStruct & zoneTrigger) = 0; // Remove a zone trigger - virtual CameraError RemoveZoneTrigger(uint16_t zoneID) = 0; + virtual CameraError RemoveZoneTrigger(uint16_t zoneId) = 0; class ZoneEventCallback { diff --git a/examples/camera-app/camera-common/include/media-controller/media-controller.h b/examples/camera-app/camera-common/include/media-controller/media-controller.h index 5f0146ce338..b7dd7171571 100644 --- a/examples/camera-app/camera-common/include/media-controller/media-controller.h +++ b/examples/camera-app/camera-common/include/media-controller/media-controller.h @@ -27,8 +27,8 @@ struct Connection { Transport * transport; - uint16_t videoStreamID; - uint16_t audioStreamID; + std::vector videoStreams; + std::vector audioStreams; }; // Media Controller @@ -38,8 +38,9 @@ class MediaController MediaController() {} virtual ~MediaController() {} // Transports register themselves with the media-controller for receiving - // media from stream sources. - virtual void RegisterTransport(Transport * transport, uint16_t videoStreamID, uint16_t audioStreamID) = 0; + // media from stream sources. Supports multiple video and audio streams per transport. + virtual void RegisterTransport(Transport * transport, const std::vector & videoStreams, + const std::vector & audioStreams) = 0; // Transports must first unregister from the media-controller when they are // getting destroyed. virtual void UnregisterTransport(Transport * transport) = 0; @@ -48,7 +49,7 @@ class MediaController virtual Transport * GetTransportForAudioStream(uint16_t audioStreamID) = 0; // Media controller goes through registered transports and dispatches media // if the transport is ready. - virtual void DistributeVideo(const uint8_t * data, size_t size, uint16_t videoStreamID) = 0; - virtual void DistributeAudio(const uint8_t * data, size_t size, uint16_t audioStreamID) = 0; - virtual void SetPreRollLength(Transport * transport, uint16_t PreRollBufferLength) = 0; + virtual void DistributeVideo(const uint8_t * data, size_t size, uint16_t videoStreamID, int64_t timestamp) = 0; + virtual void DistributeAudio(const uint8_t * data, size_t size, uint16_t audioStreamID, int64_t timestamp) = 0; + virtual void SetPreRollLength(Transport * transport, uint16_t PreRollBufferLength) = 0; }; diff --git a/examples/camera-app/camera-common/include/transport/transport.h b/examples/camera-app/camera-common/include/transport/transport.h index 90a36f081bd..bf82ca99950 100644 --- a/examples/camera-app/camera-common/include/transport/transport.h +++ b/examples/camera-app/camera-common/include/transport/transport.h @@ -23,6 +23,7 @@ #include #include #pragma once + // Base class for media transports(WebRTC, PushAV) // Media Transports would implement this interface for the Media controller to // use. diff --git a/examples/camera-app/camera-common/src/camera-app.cpp b/examples/camera-app/camera-common/src/camera-app.cpp index 0f1e377a6c1..4c0bc7938db 100644 --- a/examples/camera-app/camera-common/src/camera-app.cpp +++ b/examples/camera-app/camera-common/src/camera-app.cpp @@ -16,6 +16,7 @@ * limitations under the License. */ #include "camera-app.h" +#include "data-model-providers/codegen/CodegenDataModelProvider.h" #include "tls-certificate-management-instance.h" #include "tls-client-management-instance.h" #include @@ -27,7 +28,6 @@ using namespace chip::app::Clusters::Chime; using namespace chip::app::Clusters::PushAvStreamTransport; using namespace chip::app::Clusters::WebRTCTransportProvider; using namespace chip::app::Clusters::CameraAvStreamManagement; -using namespace chip::app::Clusters::CameraAvSettingsUserLevelManagement; using namespace chip::app::Clusters::ZoneManagement; static constexpr uint32_t kBitsPerMegabit = 1000000; @@ -44,17 +44,148 @@ CameraApp::CameraApp(chip::EndpointId aClustersEndpoint, CameraDeviceInterface * // Instantiate Chime Server mChimeServerPtr = std::make_unique(mEndpoint, mCameraDevice->GetChimeDelegate()); - // Instantiate WebRTCTransport Provider - mWebRTCTransportProviderPtr = - std::make_unique(mCameraDevice->GetWebRTCProviderDelegate(), mEndpoint); - Clusters::PushAvStreamTransport::SetDelegate(mEndpoint, &(mCameraDevice->GetPushAVTransportDelegate())); Clusters::PushAvStreamTransport::SetTLSClientManagementDelegate(mEndpoint, &Clusters::TlsClientManagementCommandDelegate::GetInstance()); - Clusters::PushAvStreamTransport::SetTlsCertificateManagementDelegate( + Clusters::PushAvStreamTransport::SetTLSCertificateManagementDelegate( mEndpoint, &Clusters::TlsCertificateManagementCommandDelegate::GetInstance()); + + // Fetch all initialization parameters for CameraAVSettingsUserLevelMgmt Server + BitFlags avsumFeatures( + CameraAvSettingsUserLevelManagement::Feature::kDigitalPTZ, CameraAvSettingsUserLevelManagement::Feature::kMechanicalPan, + CameraAvSettingsUserLevelManagement::Feature::kMechanicalTilt, + CameraAvSettingsUserLevelManagement::Feature::kMechanicalZoom, + CameraAvSettingsUserLevelManagement::Feature::kMechanicalPresets); + + const uint8_t appMaxPresets = 5; + + // Instantiate the CameraAVSettingsUserLevelMgmt Server + mAVSettingsUserLevelMgmtServer.Create(mEndpoint, avsumFeatures, appMaxPresets); + mAVSettingsUserLevelMgmtServer.Cluster().SetDelegate(&mCameraDevice->GetCameraAVSettingsUserLevelMgmtDelegate()); + CHIP_ERROR err = CodegenDataModelProvider::Instance().Registry().Register(mAVSettingsUserLevelMgmtServer.Registration()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Camera, "Failed to register CameraAvSettingsUserLevelManagement on endpoint %u: %" CHIP_ERROR_FORMAT, + mEndpoint, err.Format()); + } + + TEMPORARY_RETURN_IGNORED mAVSettingsUserLevelMgmtServer.Cluster().SetPanMin(mCameraDevice->GetCameraHALInterface().GetPanMin()); + TEMPORARY_RETURN_IGNORED mAVSettingsUserLevelMgmtServer.Cluster().SetPanMax(mCameraDevice->GetCameraHALInterface().GetPanMax()); + TEMPORARY_RETURN_IGNORED mAVSettingsUserLevelMgmtServer.Cluster().SetTiltMin( + mCameraDevice->GetCameraHALInterface().GetTiltMin()); + TEMPORARY_RETURN_IGNORED mAVSettingsUserLevelMgmtServer.Cluster().SetTiltMax( + mCameraDevice->GetCameraHALInterface().GetTiltMax()); + TEMPORARY_RETURN_IGNORED mAVSettingsUserLevelMgmtServer.Cluster().SetZoomMax( + mCameraDevice->GetCameraHALInterface().GetZoomMax()); + + // Fetch all initialization parameters for the ZoneManagement Server + BitFlags zoneMgmtFeatures( + ZoneManagement::Feature::kTwoDimensionalCartesianZone, ZoneManagement::Feature::kPerZoneSensitivity, + ZoneManagement::Feature::kUserDefined, ZoneManagement::Feature::kFocusZones); + + uint8_t appMaxZones = mCameraDevice->GetCameraHALInterface().GetMaxZones(); + uint8_t appMaxUserDefinedZones = mCameraDevice->GetCameraHALInterface().GetMaxUserDefinedZones(); + uint8_t sensitivityMax = mCameraDevice->GetCameraHALInterface().GetSensitivityMax(); + VideoSensorParamsStruct sensorParams = mCameraDevice->GetCameraHALInterface().GetVideoSensorParams(); + TwoDCartesianVertexStruct appTwoDCartesianMax = {}; + appTwoDCartesianMax.x = sensorParams.sensorWidth - 1; + appTwoDCartesianMax.y = sensorParams.sensorHeight - 1; + + // Instantiate the ZoneManagement Server + mZoneMgmtServerPtr = std::make_unique(mCameraDevice->GetZoneManagementDelegate(), mEndpoint, zoneMgmtFeatures, + appMaxUserDefinedZones, appMaxZones, sensitivityMax, appTwoDCartesianMax); + + TEMPORARY_RETURN_IGNORED mZoneMgmtServerPtr->SetSensitivity(mCameraDevice->GetCameraHALInterface().GetDetectionSensitivity()); +} + +CHIP_ERROR CameraApp::InitializeCameraAVStreamMgmt() +{ + VerifyOrReturnError(mAVStreamMgmtServer.IsConstructed(), CHIP_ERROR_INCORRECT_STATE); + + // Set the attribute defaults + if (mCameraDevice->GetCameraHALInterface().GetCameraSupportsHDR()) + { + ReturnErrorOnFailure(mAVStreamMgmtServer.Cluster().SetHDRModeEnabled(mCameraDevice->GetCameraHALInterface().GetHDRMode())); + } + + if (mCameraDevice->GetCameraHALInterface().GetCameraSupportsSoftPrivacy()) + { + ReturnErrorOnFailure(mAVStreamMgmtServer.Cluster().SetSoftRecordingPrivacyModeEnabled( + mCameraDevice->GetCameraHALInterface().GetSoftRecordingPrivacyModeEnabled())); + ReturnErrorOnFailure(mAVStreamMgmtServer.Cluster().SetSoftLivestreamPrivacyModeEnabled( + mCameraDevice->GetCameraHALInterface().GetSoftLivestreamPrivacyModeEnabled())); + } + + if (mCameraDevice->GetCameraHALInterface().HasHardPrivacySwitch()) + { + ReturnErrorOnFailure( + mAVStreamMgmtServer.Cluster().SetHardPrivacyModeOn(mCameraDevice->GetCameraHALInterface().GetHardPrivacyMode())); + } + + if (mCameraDevice->GetCameraHALInterface().GetCameraSupportsNightVision()) + { + ReturnErrorOnFailure(mAVStreamMgmtServer.Cluster().SetNightVision(mCameraDevice->GetCameraHALInterface().GetNightVision())); + } + + ReturnErrorOnFailure(mAVStreamMgmtServer.Cluster().SetViewport(mCameraDevice->GetCameraHALInterface().GetViewport())); + + if (mCameraDevice->GetCameraHALInterface().HasSpeaker()) + { + ReturnErrorOnFailure( + mAVStreamMgmtServer.Cluster().SetSpeakerMuted(mCameraDevice->GetCameraHALInterface().GetSpeakerMuted())); + ReturnErrorOnFailure( + mAVStreamMgmtServer.Cluster().SetSpeakerVolumeLevel(mCameraDevice->GetCameraHALInterface().GetSpeakerVolume())); + ReturnErrorOnFailure( + mAVStreamMgmtServer.Cluster().SetSpeakerMaxLevel(mCameraDevice->GetCameraHALInterface().GetSpeakerMaxLevel())); + ReturnErrorOnFailure( + mAVStreamMgmtServer.Cluster().SetSpeakerMinLevel(mCameraDevice->GetCameraHALInterface().GetSpeakerMinLevel())); + } + + if (mCameraDevice->GetCameraHALInterface().HasMicrophone()) + { + ReturnErrorOnFailure( + mAVStreamMgmtServer.Cluster().SetMicrophoneMuted(mCameraDevice->GetCameraHALInterface().GetMicrophoneMuted())); + ReturnErrorOnFailure( + mAVStreamMgmtServer.Cluster().SetMicrophoneVolumeLevel(mCameraDevice->GetCameraHALInterface().GetMicrophoneVolume())); + ReturnErrorOnFailure( + mAVStreamMgmtServer.Cluster().SetMicrophoneMaxLevel(mCameraDevice->GetCameraHALInterface().GetMicrophoneMaxLevel())); + ReturnErrorOnFailure( + mAVStreamMgmtServer.Cluster().SetMicrophoneMinLevel(mCameraDevice->GetCameraHALInterface().GetMicrophoneMinLevel())); + } + + // Video and Snapshot features are already enabled. + if (mCameraDevice->GetCameraHALInterface().HasLocalStorage()) + { + ReturnErrorOnFailure(mAVStreamMgmtServer.Cluster().SetLocalVideoRecordingEnabled( + mCameraDevice->GetCameraHALInterface().GetLocalVideoRecordingEnabled())); + ReturnErrorOnFailure(mAVStreamMgmtServer.Cluster().SetLocalSnapshotRecordingEnabled( + mCameraDevice->GetCameraHALInterface().GetLocalSnapshotRecordingEnabled())); + } + + if (mCameraDevice->GetCameraHALInterface().HasStatusLight()) + { + ReturnErrorOnFailure( + mAVStreamMgmtServer.Cluster().SetStatusLightEnabled(mCameraDevice->GetCameraHALInterface().GetStatusLightEnabled())); + } + + if (mCameraDevice->GetCameraHALInterface().GetCameraSupportsImageControl()) + { + ReturnErrorOnFailure( + mAVStreamMgmtServer.Cluster().SetImageRotation(mCameraDevice->GetCameraHALInterface().GetImageRotation())); + ReturnErrorOnFailure( + mAVStreamMgmtServer.Cluster().SetImageFlipVertical(mCameraDevice->GetCameraHALInterface().GetImageFlipVertical())); + ReturnErrorOnFailure( + mAVStreamMgmtServer.Cluster().SetImageFlipHorizontal(mCameraDevice->GetCameraHALInterface().GetImageFlipHorizontal())); + } + + return mAVStreamMgmtServer.Cluster().Init(); +} + +void CameraApp::CreateAndInitializeCameraAVStreamMgmt() +{ + // Fetch all initialization parameters for CameraAVStreamMgmt Server BitFlags avsmFeatures; BitFlags avsmOptionalAttrs; @@ -146,148 +277,68 @@ CameraApp::CameraApp(chip::EndpointId aClustersEndpoint, CameraDeviceInterface * std::vector streamUsagePriorities = mCameraDevice->GetCameraHALInterface().GetStreamUsagePriorities(); // Instantiate the CameraAVStreamMgmt Server - mAVStreamMgmtServerPtr = std::make_unique( - mCameraDevice->GetCameraAVStreamMgmtDelegate(), mEndpoint, avsmFeatures, avsmOptionalAttrs, maxConcurrentVideoEncoders, - maxEncodedPixelRate, sensorParams, nightVisionUsesInfrared, minViewport, rateDistortionTradeOffPoints, maxContentBufferSize, - micCapabilities, spkrCapabilities, twowayTalkSupport, snapshotCapabilities, maxNetworkBandwidth, supportedStreamUsages, - streamUsagePriorities); - - // Fetch all initialization parameters for CameraAVSettingsUserLevelMgmt Server - BitFlags avsumFeatures( - CameraAvSettingsUserLevelManagement::Feature::kDigitalPTZ, CameraAvSettingsUserLevelManagement::Feature::kMechanicalPan, - CameraAvSettingsUserLevelManagement::Feature::kMechanicalTilt, - CameraAvSettingsUserLevelManagement::Feature::kMechanicalZoom, - CameraAvSettingsUserLevelManagement::Feature::kMechanicalPresets); - BitFlags avsumAttrs( - CameraAvSettingsUserLevelManagement::OptionalAttributes::kMptzPosition, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kMaxPresets, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kMptzPresets, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kDptzStreams, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kZoomMax, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kTiltMin, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kTiltMax, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kPanMin, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kPanMax, - CameraAvSettingsUserLevelManagement::OptionalAttributes::kMovementState); - const uint8_t appMaxPresets = 5; - - // Instantiate the CameraAVSettingsUserLevelMgmt Server - mAVSettingsUserLevelMgmtServerPtr = std::make_unique( - mEndpoint, mCameraDevice->GetCameraAVSettingsUserLevelMgmtDelegate(), avsumFeatures, avsumAttrs, appMaxPresets); - - mAVSettingsUserLevelMgmtServerPtr->SetPanMin(mCameraDevice->GetCameraHALInterface().GetPanMin()); - mAVSettingsUserLevelMgmtServerPtr->SetPanMax(mCameraDevice->GetCameraHALInterface().GetPanMax()); - mAVSettingsUserLevelMgmtServerPtr->SetTiltMin(mCameraDevice->GetCameraHALInterface().GetTiltMin()); - mAVSettingsUserLevelMgmtServerPtr->SetTiltMax(mCameraDevice->GetCameraHALInterface().GetTiltMax()); - mAVSettingsUserLevelMgmtServerPtr->SetZoomMax(mCameraDevice->GetCameraHALInterface().GetZoomMax()); - - // Fetch all initialization parameters for the ZoneManagement Server - BitFlags zoneMgmtFeatures( - ZoneManagement::Feature::kTwoDimensionalCartesianZone, ZoneManagement::Feature::kPerZoneSensitivity, - ZoneManagement::Feature::kUserDefined, ZoneManagement::Feature::kFocusZones); - - uint8_t appMaxZones = mCameraDevice->GetCameraHALInterface().GetMaxZones(); - uint8_t appMaxUserDefinedZones = mCameraDevice->GetCameraHALInterface().GetMaxUserDefinedZones(); - uint8_t sensitivityMax = mCameraDevice->GetCameraHALInterface().GetSensitivityMax(); - TwoDCartesianVertexStruct appTwoDCartesianMax = {}; - appTwoDCartesianMax.x = sensorParams.sensorWidth - 1; - appTwoDCartesianMax.y = sensorParams.sensorHeight - 1; - - // Instantiate the ZoneManagement Server - mZoneMgmtServerPtr = std::make_unique(mCameraDevice->GetZoneManagementDelegate(), mEndpoint, zoneMgmtFeatures, - appMaxUserDefinedZones, appMaxZones, sensitivityMax, appTwoDCartesianMax); - - mZoneMgmtServerPtr->SetSensitivity(mCameraDevice->GetCameraHALInterface().GetDetectionSensitivity()); -} - -void CameraApp::InitializeCameraAVStreamMgmt() -{ - // Set the attribute defaults - if (mCameraDevice->GetCameraHALInterface().GetCameraSupportsHDR()) - { - mAVStreamMgmtServerPtr->SetHDRModeEnabled(mCameraDevice->GetCameraHALInterface().GetHDRMode()); - } - - if (mCameraDevice->GetCameraHALInterface().GetCameraSupportsSoftPrivacy()) - { - mAVStreamMgmtServerPtr->SetSoftRecordingPrivacyModeEnabled( - mCameraDevice->GetCameraHALInterface().GetSoftRecordingPrivacyModeEnabled()); - mAVStreamMgmtServerPtr->SetSoftLivestreamPrivacyModeEnabled( - mCameraDevice->GetCameraHALInterface().GetSoftLivestreamPrivacyModeEnabled()); - } - - if (mCameraDevice->GetCameraHALInterface().HasHardPrivacySwitch()) - { - mAVStreamMgmtServerPtr->SetHardPrivacyModeOn(mCameraDevice->GetCameraHALInterface().GetHardPrivacyMode()); - } - - if (mCameraDevice->GetCameraHALInterface().GetCameraSupportsNightVision()) - { - mAVStreamMgmtServerPtr->SetNightVision(mCameraDevice->GetCameraHALInterface().GetNightVision()); - } - - mAVStreamMgmtServerPtr->SetViewport(mCameraDevice->GetCameraHALInterface().GetViewport()); - - if (mCameraDevice->GetCameraHALInterface().HasSpeaker()) - { - mAVStreamMgmtServerPtr->SetSpeakerMuted(mCameraDevice->GetCameraHALInterface().GetSpeakerMuted()); - mAVStreamMgmtServerPtr->SetSpeakerVolumeLevel(mCameraDevice->GetCameraHALInterface().GetSpeakerVolume()); - mAVStreamMgmtServerPtr->SetSpeakerMaxLevel(mCameraDevice->GetCameraHALInterface().GetSpeakerMaxLevel()); - mAVStreamMgmtServerPtr->SetSpeakerMinLevel(mCameraDevice->GetCameraHALInterface().GetSpeakerMinLevel()); - } - - if (mCameraDevice->GetCameraHALInterface().HasMicrophone()) - { - mAVStreamMgmtServerPtr->SetMicrophoneMuted(mCameraDevice->GetCameraHALInterface().GetMicrophoneMuted()); - mAVStreamMgmtServerPtr->SetMicrophoneVolumeLevel(mCameraDevice->GetCameraHALInterface().GetMicrophoneVolume()); - mAVStreamMgmtServerPtr->SetMicrophoneMaxLevel(mCameraDevice->GetCameraHALInterface().GetMicrophoneMaxLevel()); - mAVStreamMgmtServerPtr->SetMicrophoneMinLevel(mCameraDevice->GetCameraHALInterface().GetMicrophoneMinLevel()); - } - - // Video and Snapshot features are already enabled. - if (mCameraDevice->GetCameraHALInterface().HasLocalStorage()) - { - mAVStreamMgmtServerPtr->SetLocalVideoRecordingEnabled( - mCameraDevice->GetCameraHALInterface().GetLocalVideoRecordingEnabled()); - mAVStreamMgmtServerPtr->SetLocalSnapshotRecordingEnabled( - mCameraDevice->GetCameraHALInterface().GetLocalSnapshotRecordingEnabled()); - } - - if (mCameraDevice->GetCameraHALInterface().HasStatusLight()) + mAVStreamMgmtServer.Create(mCameraDevice->GetCameraAVStreamMgmtDelegate(), mEndpoint, avsmFeatures, avsmOptionalAttrs, + maxConcurrentVideoEncoders, maxEncodedPixelRate, sensorParams, nightVisionUsesInfrared, minViewport, + rateDistortionTradeOffPoints, maxContentBufferSize, micCapabilities, spkrCapabilities, + twowayTalkSupport, snapshotCapabilities, maxNetworkBandwidth, supportedStreamUsages, + streamUsagePriorities); + + CHIP_ERROR err = CodegenDataModelProvider::Instance().Registry().Register(mAVStreamMgmtServer.Registration()); + if (err != CHIP_NO_ERROR) { - mAVStreamMgmtServerPtr->SetStatusLightEnabled(mCameraDevice->GetCameraHALInterface().GetStatusLightEnabled()); + ChipLogError(Camera, "Failed to register CameraAVStreamManagementServer on endpoint %u: %" CHIP_ERROR_FORMAT, mEndpoint, + err.Format()); } - if (mCameraDevice->GetCameraHALInterface().GetCameraSupportsImageControl()) + err = InitializeCameraAVStreamMgmt(); + if (err != CHIP_NO_ERROR) { - mAVStreamMgmtServerPtr->SetImageRotation(mCameraDevice->GetCameraHALInterface().GetImageRotation()); - mAVStreamMgmtServerPtr->SetImageFlipVertical(mCameraDevice->GetCameraHALInterface().GetImageFlipVertical()); - mAVStreamMgmtServerPtr->SetImageFlipHorizontal(mCameraDevice->GetCameraHALInterface().GetImageFlipHorizontal()); + ChipLogError(Camera, "Failed to initialize CameraAVStreamManagementServer on endpoint %u: %" CHIP_ERROR_FORMAT, mEndpoint, + err.Format()); } - - mAVStreamMgmtServerPtr->Init(); } void CameraApp::InitCameraDeviceClusters() { // Initialize Cluster Servers - mWebRTCTransportProviderPtr->Init(); - mCameraDevice->GetWebRTCProviderController().SetWebRTCTransportProvider(std::move(mWebRTCTransportProviderPtr)); + mWebRTCTransportProviderServer.Create(mEndpoint, mCameraDevice->GetWebRTCProviderDelegate()); + CHIP_ERROR err = CodegenDataModelProvider::Instance().Registry().Register(mWebRTCTransportProviderServer.Registration()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Camera, "Failed to register WebRTCTransportProvider on endpoint %u: %" CHIP_ERROR_FORMAT, mEndpoint, + err.Format()); + } + + CreateAndInitializeCameraAVStreamMgmt(); - mChimeServerPtr->Init(); + // Set the WebRTCTransportProvider server in the manager + mCameraDevice->SetWebRTCTransportProvider(&mWebRTCTransportProviderServer.Cluster()); - mAVSettingsUserLevelMgmtServerPtr->Init(); + TEMPORARY_RETURN_IGNORED mChimeServerPtr->Init(); - InitializeCameraAVStreamMgmt(); + TEMPORARY_RETURN_IGNORED mAVSettingsUserLevelMgmtServer.Cluster().Init(); - mZoneMgmtServerPtr->Init(); + TEMPORARY_RETURN_IGNORED mZoneMgmtServerPtr->Init(); } void CameraApp::ShutdownCameraDeviceClusters() { ChipLogDetail(Camera, "CameraAppShutdown: Shutting down Camera device clusters"); - mAVSettingsUserLevelMgmtServerPtr->Shutdown(); - mWebRTCTransportProviderPtr->Shutdown(); + mAVSettingsUserLevelMgmtServer.Cluster().Shutdown(/* ClusterShutdownType::kClusterShutdown */); + + CHIP_ERROR err = CodegenDataModelProvider::Instance().Registry().Unregister(&mWebRTCTransportProviderServer.Cluster()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Camera, "WebRTCTransportProvider unregister error: %" CHIP_ERROR_FORMAT, err.Format()); + } + mWebRTCTransportProviderServer.Destroy(); + + err = CodegenDataModelProvider::Instance().Registry().Unregister(&mAVStreamMgmtServer.Cluster()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Camera, "CameraAVStreamMgmt Server unregister error: %" CHIP_ERROR_FORMAT, err.Format()); + } + mAVStreamMgmtServer.Destroy(); } static constexpr EndpointId kCameraEndpointId = 1; diff --git a/examples/camera-app/linux/BUILD.gn b/examples/camera-app/linux/BUILD.gn index 1afa4b65fd2..a62f88b8472 100644 --- a/examples/camera-app/linux/BUILD.gn +++ b/examples/camera-app/linux/BUILD.gn @@ -49,6 +49,7 @@ config("config") { "${chip_root}/examples/camera-app/camera-common/include/camera-avstream-controller", "${chip_root}/examples/camera-app/camera-common/include/webrtc-provider-controller", "${chip_root}/examples/camera-app/camera-common/include/transport", + "${chip_root}/examples/all-clusters-app/all-clusters-common/include", "${chip_root}/third_party/libdatachannel/repo/include", ] } diff --git a/examples/camera-app/linux/include/camera-device.h b/examples/camera-app/linux/include/camera-device.h index c4e5e78471b..c1ec5d02aa8 100644 --- a/examples/camera-app/linux/include/camera-device.h +++ b/examples/camera-app/linux/include/camera-device.h @@ -87,17 +87,16 @@ class CameraDevice : public CameraDeviceInterface, public CameraDeviceInterface: public: chip::app::Clusters::ChimeDelegate & GetChimeDelegate() override; chip::app::Clusters::WebRTCTransportProvider::Delegate & GetWebRTCProviderDelegate() override; - chip::app::Clusters::WebRTCTransportProvider::WebRTCTransportProviderController & GetWebRTCProviderController() override; - chip::app::Clusters::CameraAvStreamManagement::CameraAVStreamMgmtDelegate & GetCameraAVStreamMgmtDelegate() override; + void + SetWebRTCTransportProvider(chip::app::Clusters::WebRTCTransportProvider::WebRTCTransportProviderCluster * provider) override; + chip::app::Clusters::CameraAvStreamManagement::CameraAVStreamManagementDelegate & GetCameraAVStreamMgmtDelegate() override; chip::app::Clusters::CameraAvStreamManagement::CameraAVStreamController & GetCameraAVStreamMgmtController() override; - chip::app::Clusters::CameraAvSettingsUserLevelManagement::Delegate & GetCameraAVSettingsUserLevelMgmtDelegate() override; + chip::app::Clusters::CameraAvSettingsUserLevelManagementDelegate & GetCameraAVSettingsUserLevelMgmtDelegate() override; chip::app::Clusters::PushAvStreamTransportDelegate & GetPushAVTransportDelegate() override; chip::app::Clusters::ZoneManagement::Delegate & GetZoneManagementDelegate() override; MediaController & GetMediaController() override; - void HandlePushAvZoneTrigger(uint16_t zoneId) override; - CameraDevice(); ~CameraDevice(); @@ -126,7 +125,7 @@ class CameraDevice : public CameraDeviceInterface, public CameraDeviceInterface: // Allocate snapshot stream CameraError AllocateSnapshotStream( - const chip::app::Clusters::CameraAvStreamManagement::CameraAVStreamMgmtDelegate::SnapshotStreamAllocateArgs & args, + const chip::app::Clusters::CameraAvStreamManagement::CameraAVStreamManagementDelegate::SnapshotStreamAllocateArgs & args, uint16_t & outStreamID) override; // Start snapshot stream @@ -298,7 +297,7 @@ class CameraDevice : public CameraDeviceInterface, public CameraDeviceInterface: CameraError UpdateZoneTrigger(const chip::app::Clusters::ZoneManagement::ZoneTriggerControlStruct & zoneTrigger) override; - CameraError RemoveZoneTrigger(uint16_t zoneID) override; + CameraError RemoveZoneTrigger(uint16_t zoneId) override; CameraError SetPan(int16_t aPan) override; CameraError SetTilt(int16_t aTilt) override; @@ -313,14 +312,20 @@ class CameraDevice : public CameraDeviceInterface, public CameraDeviceInterface: void SetVideoDevicePath(const std::string & path) { mVideoDevicePath = path; } - void HandleSimulatedZoneTriggeredEvent(uint16_t zoneID); + void HandleSimulatedZoneTriggeredEvent(uint16_t zoneId); - void HandleSimulatedZoneStoppedEvent(uint16_t zoneID); + void HandleSimulatedZoneStoppedEvent(uint16_t zoneId); // Audio playback pipeline methods CameraError StartAudioPlaybackStream(); CameraError StopAudioPlaybackStream(); + // Timestamp handling for video and audio streams + std::map mVideoStreamStartEpochs; + std::map mVideoStreamFirstPts; + std::map mAudioStreamStartEpochs; + std::map mAudioStreamFirstPts; + private: int videoDeviceFd = -1; std::string mVideoDevicePath = kDefaultVideoDevicePath; diff --git a/examples/camera-app/linux/include/clusters/camera-avsettingsuserlevel-mgmt/camera-avsettingsuserlevel-manager.h b/examples/camera-app/linux/include/clusters/camera-avsettingsuserlevel-mgmt/camera-avsettingsuserlevel-manager.h index 2444c3fb1ff..e80b758d1b9 100644 --- a/examples/camera-app/linux/include/clusters/camera-avsettingsuserlevel-mgmt/camera-avsettingsuserlevel-manager.h +++ b/examples/camera-app/linux/include/clusters/camera-avsettingsuserlevel-mgmt/camera-avsettingsuserlevel-manager.h @@ -19,7 +19,7 @@ #pragma once #include "camera-device-interface.h" -#include +#include #include namespace chip { @@ -30,7 +30,7 @@ namespace CameraAvSettingsUserLevelManagement { /** * The application delegate to define the options & implement commands. */ -class CameraAVSettingsUserLevelManager : public Delegate +class CameraAVSettingsUserLevelManager : public CameraAvSettingsUserLevelManagementDelegate { public: CameraAVSettingsUserLevelManager() = default; @@ -41,7 +41,7 @@ class CameraAVSettingsUserLevelManager : public Delegate bool CanChangeMPTZ() override; CHIP_ERROR LoadMPTZPresets(std::vector & mptzPresetHelpers) override; - CHIP_ERROR LoadDPTZStreams(std::vector & dptzStreams) override; + CHIP_ERROR LoadDPTZStreams(std::vector & dptzStreams) override; CHIP_ERROR PersistentAttributesLoadedCallback() override; /** diff --git a/examples/camera-app/linux/include/clusters/camera-avstream-mgmt/camera-av-stream-manager.h b/examples/camera-app/linux/include/clusters/camera-avstream-mgmt/camera-av-stream-manager.h index 325267afdea..116fb79d99b 100644 --- a/examples/camera-app/linux/include/clusters/camera-avstream-mgmt/camera-av-stream-manager.h +++ b/examples/camera-app/linux/include/clusters/camera-avstream-mgmt/camera-av-stream-manager.h @@ -20,7 +20,7 @@ #include "camera-avstream-controller.h" #include "camera-device-interface.h" -#include +#include #include #include @@ -32,7 +32,7 @@ namespace CameraAvStreamManagement { /** * The application delegate to define the options & implement commands. */ -class CameraAVStreamManager : public CameraAVStreamMgmtDelegate, public CameraAVStreamController +class CameraAVStreamManager : public CameraAVStreamManagementDelegate, public CameraAVStreamController { public: Protocols::InteractionModel::Status VideoStreamAllocate(const VideoStreamStruct & allocateArgs, @@ -67,8 +67,8 @@ class CameraAVStreamManager : public CameraAVStreamMgmtDelegate, public CameraAV ImageSnapshot & outImageSnapshot) override; CHIP_ERROR - ValidateStreamUsage(StreamUsageEnum streamUsage, Optional> & videoStreamId, - Optional> & audioStreamId) override; + ValidateStreamUsage(StreamUsageEnum streamUsage, Optional> & videoStreams, + Optional> & audioStreams) override; CHIP_ERROR ValidateVideoStreamID(uint16_t videoStreamId) override; @@ -76,6 +76,12 @@ class CameraAVStreamManager : public CameraAVStreamMgmtDelegate, public CameraAV CHIP_ERROR ValidateAudioStreamID(uint16_t audioStreamId) override; + CHIP_ERROR + ValidateVideoStreams(const std::vector & videoStreams) override; + + CHIP_ERROR + ValidateAudioStreams(const std::vector & audioStreams) override; + CHIP_ERROR IsHardPrivacyModeActive(bool & isActive) override; CHIP_ERROR IsSoftRecordingPrivacyModeActive(bool & isActive) override; @@ -90,9 +96,11 @@ class CameraAVStreamManager : public CameraAVStreamMgmtDelegate, public CameraAV CHIP_ERROR PersistentAttributesLoadedCallback() override; - CHIP_ERROR OnTransportAcquireAudioVideoStreams(uint16_t audioStreamID, uint16_t videoStreamID) override; + CHIP_ERROR OnTransportAcquireAudioVideoStreams(const std::vector & audioStreams, + const std::vector & videoStreams) override; - CHIP_ERROR OnTransportReleaseAudioVideoStreams(uint16_t audioStreamID, uint16_t videoStreamID) override; + CHIP_ERROR OnTransportReleaseAudioVideoStreams(const std::vector & audioStreams, + const std::vector & videoStreams) override; const std::vector & GetAllocatedVideoStreams() const override; diff --git a/examples/camera-app/linux/include/clusters/chime/chime-manager.h b/examples/camera-app/linux/include/clusters/chime/chime-manager.h index 2ba199c7212..45b7e95111a 100644 --- a/examples/camera-app/linux/include/clusters/chime/chime-manager.h +++ b/examples/camera-app/linux/include/clusters/chime/chime-manager.h @@ -33,7 +33,7 @@ class ChimeManager : public ChimeDelegate CHIP_ERROR GetChimeSoundByIndex(uint8_t chimeIndex, uint8_t & chimeID, chip::MutableCharSpan & name) override; CHIP_ERROR GetChimeIDByIndex(uint8_t chimeIndex, uint8_t & chimeID) override; - chip::Protocols::InteractionModel::Status PlayChimeSound() override; + chip::Protocols::InteractionModel::Status PlayChimeSound(uint8_t chimeID) override; private: using ChimeSoundStructType = chip::app::Clusters::Chime::Structs::ChimeSoundStruct::Type; diff --git a/examples/camera-app/linux/include/clusters/push-av-stream-transport/push-av-stream-manager.h b/examples/camera-app/linux/include/clusters/push-av-stream-transport/push-av-stream-manager.h index 5c31dba88b9..4eec7fa368c 100644 --- a/examples/camera-app/linux/include/clusters/push-av-stream-transport/push-av-stream-manager.h +++ b/examples/camera-app/linux/include/clusters/push-av-stream-transport/push-av-stream-manager.h @@ -18,19 +18,16 @@ #pragma once #include -#include -#include +#include +#include #include -#include #include #include #include #include #include -#include #include #include -#include #include namespace chip { @@ -38,15 +35,6 @@ namespace app { namespace Clusters { namespace PushAvStreamTransport { -static constexpr int kMaxSessionDuration = 5; // in minutes -static constexpr int kSessionMonitorInterval = 1; // in seconds - -// Helper function to combine FabricIndex and sessionGroup into a single key -inline uint32_t CreateSessionKey(FabricIndex fabricIdx, uint8_t sessionGroup) -{ - return (static_cast(fabricIdx) << 8) | sessionGroup; -} - struct PushAvStream { uint16_t id; @@ -55,13 +43,6 @@ struct PushAvStream PushAvStreamTransportStatusEnum connectionStatus; }; -struct SessionInfo -{ - uint64_t sessionNumber = 0; - std::chrono::system_clock::time_point sessionStartedTimestamp; - std::unordered_set activeConnectionIDs; -}; - /** * The application delegate to define the options & implement commands. */ @@ -100,6 +81,8 @@ class PushAvStreamTransportManager : public PushAvStreamTransportDelegate bool ValidateSegmentDuration(uint16_t segmentDuration, const Optional> & videoStreamId) override; + bool ValidateMaxPreRollLength(uint16_t maxPreRollLength, const DataModel::Nullable & videoStreamId) override; + Protocols::InteractionModel::Status ValidateBandwidthLimit(StreamUsageEnum streamUsage, const Optional> & videoStreamId, const Optional> & audioStreamId) override; @@ -130,14 +113,12 @@ class PushAvStreamTransportManager : public PushAvStreamTransportDelegate CHIP_ERROR IsSoftLivestreamPrivacyModeActive(bool & isActive) override; + bool GetCMAFSessionNumber(const uint16_t connectionID, uint64_t & sessionNumber) override; + void HandleZoneTrigger(uint16_t zoneId); void RecordingStreamPrivacyModeChanged(bool privacyModeEnabled); - uint64_t OnTriggerActivated(uint8_t fabricIdx, uint8_t sessionGroup, uint16_t connectionID); - - void OnTriggerDeactivated(uint8_t fabricIdx, uint8_t sessionGroup, uint16_t connectionID); - private: MediaController * mMediaController = nullptr; CameraDeviceInterface * mCameraDevice = nullptr; @@ -146,13 +127,8 @@ class PushAvStreamTransportManager : public PushAvStreamTransportDelegate AudioStreamStruct mAudioStreamParams; VideoStreamStruct mVideoStreamParams; - std::atomic mStopMonitoring{ false }; - std::mutex mSessionMapMutex; - std::thread mSessionMonitorThread; - std::unordered_map> mTransportMap; // map for the transport objects std::unordered_map mTransportOptionsMap; // map for the transport options - std::unordered_map mSessionMap; // map for the session info uint32_t mTotalUsedBandwidthbps = 0; // Tracks the total bandwidth used by all active transports std::vector mBufferRootCert; @@ -163,6 +139,13 @@ class PushAvStreamTransportManager : public PushAvStreamTransportDelegate CHIP_ERROR IsAnyPrivacyModeActive(bool & isActive); + /** + * @brief Checks if the specified CMAF interface type is supported. + * @param cmafInterface The CMAF interface enum to validate. + * @return true if the interface is supported, false otherwise. + */ + bool IsCMAFInterfaceSupported(CMAFInterfaceEnum cmafInterface) const; + /** * @brief Calculates the total bandwidth in bps for the given video and audio stream IDs. * @param videoStreamId Optional nullable video stream ID. @@ -171,10 +154,6 @@ class PushAvStreamTransportManager : public PushAvStreamTransportDelegate */ void GetBandwidthForStreams(const Optional> & videoStreamId, const Optional> & audioStreamId, uint32_t & outBandwidthbps); - - void StartSessionMonitor(); - void StopSessionMonitor(); - void SessionMonitor(); }; } // namespace PushAvStreamTransport diff --git a/examples/camera-app/linux/include/clusters/webrtc-provider/webrtc-provider-manager.h b/examples/camera-app/linux/include/clusters/webrtc-provider/webrtc-provider-manager.h index b064f9ac993..ef00809e12d 100644 --- a/examples/camera-app/linux/include/clusters/webrtc-provider/webrtc-provider-manager.h +++ b/examples/camera-app/linux/include/clusters/webrtc-provider/webrtc-provider-manager.h @@ -22,8 +22,9 @@ #include "webrtc-abstract.h" #include #include -#include +#include #include +#include #include #include @@ -39,7 +40,7 @@ using ICECandidateStruct = chip::app::Clusters::Globals::Structs::ICECandi using StreamUsageEnum = chip::app::Clusters::Globals::StreamUsageEnum; using WebRTCEndReasonEnum = chip::app::Clusters::Globals::WebRTCEndReasonEnum; -class WebRTCProviderManager : public Delegate, public WebRTCTransportProviderController +class WebRTCProviderManager : public Delegate { public: WebRTCProviderManager() : @@ -54,25 +55,21 @@ class WebRTCProviderManager : public Delegate, public WebRTCTransportProviderCon void SetMediaController(MediaController * mediaController); - void SetWebRTCTransportProvider(std::unique_ptr webRTCTransportProvider) override; + void SetWebRTCTransportProvider(WebRTCTransportProviderCluster * webRTCTransportProvider); CHIP_ERROR HandleSolicitOffer(const OfferRequestArgs & args, WebRTCSessionStruct & outSession, bool & outDeferredOffer) override; - CHIP_ERROR - HandleProvideOffer(const ProvideOfferRequestArgs & args, WebRTCSessionStruct & outSession) override; + CHIP_ERROR HandleProvideOffer(const ProvideOfferRequestArgs & args, WebRTCSessionStruct & outSession) override; CHIP_ERROR HandleProvideAnswer(uint16_t sessionId, const std::string & sdpAnswer) override; CHIP_ERROR HandleProvideICECandidates(uint16_t sessionId, const std::vector & candidates) override; - CHIP_ERROR HandleEndSession(uint16_t sessionId, WebRTCEndReasonEnum reasonCode, - chip::app::DataModel::Nullable videoStreamID, - chip::app::DataModel::Nullable audioStreamID) override; + CHIP_ERROR HandleEndSession(uint16_t sessionId, WebRTCEndReasonEnum reasonCode) override; - CHIP_ERROR ValidateStreamUsage(StreamUsageEnum streamUsage, - chip::Optional> & videoStreamId, - chip::Optional> & audioStreamId) override; + CHIP_ERROR ValidateStreamUsage(StreamUsageEnum streamUsage, chip::Optional> & videoStreams, + chip::Optional> & audioStreams) override; void SetCameraDevice(CameraDeviceInterface * aCameraDevice); @@ -80,6 +77,10 @@ class WebRTCProviderManager : public Delegate, public WebRTCTransportProviderCon CHIP_ERROR ValidateAudioStreamID(uint16_t audioStreamId) override; + CHIP_ERROR ValidateVideoStreams(const std::vector & videoStreams) override; + + CHIP_ERROR ValidateAudioStreams(const std::vector & audioStreams) override; + CHIP_ERROR IsStreamUsageSupported(StreamUsageEnum streamUsage) override; CHIP_ERROR IsHardPrivacyModeActive(bool & isActive) override; @@ -138,6 +139,16 @@ class WebRTCProviderManager : public Delegate, public WebRTCTransportProviderCon void OnLocalDescription(const std::string & sdp, SDPType type, const uint16_t sessionId); void OnConnectionStateChanged(bool connected, const uint16_t sessionId); + void CleanupSession(uint16_t sessionId); + + void StartConnectionTimer(uint16_t sessionId); + + void CancelConnectionTimer(uint16_t sessionId); + + void HandleConnectionTimeout(uint16_t sessionId); + + static void OnConnectionTimeoutCallback(chip::System::Layer * systemLayer, void * context); + WebrtcTransport * GetTransport(uint16_t sessionId); chip::Callback::Callback mOnConnectedCallback; @@ -149,13 +160,22 @@ class WebRTCProviderManager : public Delegate, public WebRTCTransportProviderCon MediaController * mMediaController = nullptr; - std::unique_ptr mWebRTCTransportProvider = nullptr; + WebRTCTransportProviderCluster * mWebRTCTransportProvider = nullptr; // Handle to the Camera Device interface. For accessing other // clusters, if required. CameraDeviceInterface * mCameraDevice = nullptr; bool mSoftLiveStreamPrivacyEnabled = false; + + struct ConnectionTimeoutContext + { + WebRTCProviderManager * manager; + uint16_t sessionId; + }; + + // Map to track active connection timeout timers for cancellation + std::unordered_map mConnectionTimerContexts; }; } // namespace WebRTCTransportProvider diff --git a/examples/camera-app/linux/include/media-controller/default-media-controller.h b/examples/camera-app/linux/include/media-controller/default-media-controller.h index 9826cce01ad..9cb5681839c 100644 --- a/examples/camera-app/linux/include/media-controller/default-media-controller.h +++ b/examples/camera-app/linux/include/media-controller/default-media-controller.h @@ -33,14 +33,15 @@ class DefaultMediaController : public MediaController DefaultMediaController() {} virtual ~DefaultMediaController() {} // Transports register themselves with the media-controller for receiving - // media from stream sources. - void RegisterTransport(Transport * transport, uint16_t videoStreamID, uint16_t audioStreamID) override; + // media from stream sources. Supports multiple video and audio streams per transport. + void RegisterTransport(Transport * transport, const std::vector & videoStreams, + const std::vector & audioStreams) override; // Transports must first unregister from the media-controller when they are // getting destroyed. void UnregisterTransport(Transport * transport) override; // DistributeVideo and DistributeAudio are called when data is ready to be sent out - void DistributeVideo(const uint8_t * data, size_t size, uint16_t videoStreamID) override; - void DistributeAudio(const uint8_t * data, size_t size, uint16_t audioStreamID) override; + void DistributeVideo(const uint8_t * data, size_t size, uint16_t videoStreamID, int64_t timestamp) override; + void DistributeAudio(const uint8_t * data, size_t size, uint16_t audioStreamID, int64_t timestamp) override; // Sets the desired preroll buffer length in milliseconds for the given transport void SetPreRollLength(Transport * transport, uint16_t preRollBufferLength) override; void SetCameraDevice(Camera::CameraDevice * device); diff --git a/examples/camera-app/linux/include/pushav-clip-recorder.h b/examples/camera-app/linux/include/pushav-clip-recorder.h index e6cac0a1c42..848f4d31aa8 100644 --- a/examples/camera-app/linux/include/pushav-clip-recorder.h +++ b/examples/camera-app/linux/include/pushav-clip-recorder.h @@ -18,11 +18,12 @@ #pragma once #include "pushav-uploader.h" -#include +#include #include #include #include +#include #include #include #include @@ -41,15 +42,31 @@ extern "C" { #include } -namespace chip { -namespace app { -namespace Clusters { -namespace PushAvStreamTransport { -class PushAvStreamTransportManager; // Forward declaration -} // namespace PushAvStreamTransport -} // namespace Clusters -} // namespace app -} // namespace chip +// #define TEST_UPLOAD_MPD_AFTER_EVERY_SEGMENT + +/** + * @enum ClipFinalizationReason + * + * Enumerates the reasons why a clip recording is finalized. + */ +enum class ClipFinalizationReason : uint8_t +{ + kErrorOccurred = 0, ///< Clip finalized due to an error + kSegmentUploadCheck = 1, ///< Normal packet processing - check for segment upload + kCleanupUpload = 2, ///< Cleanup time - skip finalization logic, just upload segments +}; + +/** + * @enum RecorderStatus + * + * Status codes for recorder operations. + */ +enum class RecorderStatus : uint8_t +{ + kSuccess = 0, ///< Operation completed successfully + kWarning = 1, ///< Operation completed with warnings + kFail = 2, ///< Operation failed +}; /** * @struct BufferData @@ -76,24 +93,25 @@ class PushAVClipRecorder */ struct ClipInfoStruct { - bool mHasVideo; ///< Video recording enabled flag - bool mHasAudio; ///< Audio recording enabled flag - uint64_t mSessionNumber; ///< Session number for unique clip identification - uint8_t mSessionGroup; ///< Session group for grouping multiple transports - uint32_t mMaxClipDurationS; ///< Maximum clip duration in seconds - uint16_t mInitialDurationS; ///< Initial clip duration in seconds - uint16_t mAugmentationDurationS; ///< Duration increment on motion detect - uint16_t mChunkDurationMs; ///< Chunk duration milliseconds - uint16_t mSegmentDurationMs; ///< Segment duration in milliseconds - uint16_t mBlindDurationS; ///< Duration without recording after motion stop - uint16_t mPreRollLengthMs; ///< Pre-roll length in milliseconds - uint16_t mElapsedTimeS; ///< Elapsed time since recording start in seconds - std::string mOutputPath; ///< Base output directory path - std::string mTrackName; ///< Track name for segmented files - AVRational mInputTimeBase; ///< Input time base - std::string mUrl; ///< URL for uploading clips; - int mTriggerType; ///< Recording trigger type - std::chrono::steady_clock::time_point activationTime; ///< Time when the recording started + bool mHasVideo; ///< Video recording enabled flag + bool mHasAudio; ///< Audio recording enabled flag + int64_t mClipStartPTS; ///< Clip start presentation timestamp + uint64_t mSessionNumber; ///< Session number for unique clip identification + uint32_t mMaxClipDurationS; ///< Maximum clip duration in seconds + uint16_t mInitialDurationS; ///< Initial clip duration in seconds + uint16_t mAugmentationDurationS; ///< Duration increment on motion detect + uint16_t mChunkDurationMs; ///< Chunk duration milliseconds + uint16_t mSegmentDurationMs; ///< Segment duration in milliseconds + uint16_t mBlindDurationS; ///< Duration without recording after motion stop + uint16_t mPreRollLengthMs; ///< Pre-roll length in milliseconds + uint16_t mElapsedTimeS; ///< Elapsed time since recording start in seconds + std::string mOutputPath; ///< Base output directory path + std::string mTrackName; ///< Track name for segmented files + std::string mUrl; ///< URL for uploading clips; + int mTriggerType; ///< Recording trigger type + std::chrono::steady_clock::time_point mActivationTime; ///< Time when the recording started + uint16_t mMotionDetectedDurationS; ///< Current motion detected duration + uint16_t mPreviousMotionDetectedDurationS; ///< Previous duration before augmentation }; /** @@ -102,16 +120,15 @@ class PushAVClipRecorder */ struct AudioInfoStruct { - uint64_t mChannelLayout; ///< Audio channel layout - int mChannels; ///< Number of audio channels - AVCodecID mAudioCodecId; ///< Audio codec identifier - int mSampleRate; ///< Sampling rate in Hz - int mBitRate; ///< Audio bitrate in bps - int64_t mAudioPts; ///< Audio presentation timestamp - int64_t mAudioDts; ///< Audio decoding timestamp - int mAudioStreamIndex; ///< Audio stream index - int mAudioFrameDuration; ///< Audio frame duration in samples - AVRational mAudioTimeBase; ///< Audio time base + uint64_t mChannelLayout; ///< Audio channel layout + int mChannels; ///< Number of audio channels + AVCodecID mAudioCodecId; ///< Audio codec identifier + int mSampleRate; ///< Sampling rate in Hz + int mBitRate; ///< Audio bitrate in bps + int mAudioInputStreamId; ///< Input stream ID from camera + int mAudioOutputStreamId; ///< Output stream ID for ffmpeg recording + AVRational mAudioTimeBase; ///< Audio time base + std::string mAudioStreamName; ///< Audio stream name }; /** @@ -120,47 +137,88 @@ class PushAVClipRecorder */ struct VideoInfoStruct { - AVCodecID mVideoCodecId; ///< Video codec identifier - int64_t mVideoPts; ///< Video presentation timestamp - int64_t mVideoDts; ///< Video decoding timestamp - int mWidth; ///< Video frame width - int mHeight; ///< Video frame height - int mFrameRate; ///< Video frame rate (fps) - int mVideoFrameDuration; ///< Video frame duration (μs) - AVRational mVideoTimeBase; ///< Video time base - int mVideoStreamIndex; ///< Video stream index - uint32_t mBitRate; ///< Video bitrate in bps + AVCodecID mVideoCodecId; ///< Video codec identifier + int mWidth; ///< Video frame width + int mHeight; ///< Video frame height + int mFrameRate; ///< Video frame rate (fps) + int mVideoInputStreamId; ///< Input stream ID from camera + int mVideoOutputStreamId; ///< Output stream ID for ffmpeg recording + uint32_t mBitRate; ///< Video bitrate in bps + AVRational mVideoTimeBase; ///< Video time base + std::string mVideoStreamName; ///< Video stream name }; /// @name Construction/Destruction /// @{ + /** + * @brief Constructs a PushAVClipRecorder instance + * @param aClipInfo Reference to clip configuration structure + * @param aAudioInfo Reference to audio stream configuration structure + * @param aVideoInfo Reference to video stream configuration structure + * @param aUploader Pointer to the uploader instance for file uploads + */ PushAVClipRecorder(ClipInfoStruct & aClipInfo, AudioInfoStruct & aAudioInfo, VideoInfoStruct & aVideoInfo, PushAVUploader * aUploader); + + /** + * @brief Destroys the PushAVClipRecorder instance + * + * Ensures proper cleanup of all resources including stopping the recording thread, + * cleaning up FFmpeg contexts, and releasing memory allocations. + */ ~PushAVClipRecorder(); /// @} /// @name Recording Control /// @{ + /** + * @brief Starts the clip recording process + * + * Initializes the recording worker thread and begins processing media packets. + * Sets up the output format context and starts the DASH/CMAF segmentation. + */ void Start(); + + /** + * @brief Stops the clip recording process + * + * Signals the worker thread to stop, finalizes the current clip, + * and cleans up all recording resources. Waits for the worker thread + * to complete before returning. + */ void Stop(); /// @} /** * @brief Enqueues media data for processing - * @param data Raw media data pointer + * @param data Raw media data pointer containing encoded audio/video data * @param size Data size in bytes - * @param isVideo True for video data, false for audio + * @param timestampMs Timestamp in milliseconds + * @param isVideo True for video data, false for audio data */ - void PushPacket(const uint8_t * data, size_t size, bool isVideo); + void PushPacket(const uint8_t * data, size_t size, int64_t timestampMs, bool isVideo); + /** + * @brief Sets the callback function to be called when recording stops + * @param cb The callback function to execute on recording stop + */ void SetOnStopCallback(std::function cb) { mOnStopCallback = std::move(cb); } - // Set the cluster server reference for direct API calls + /** + * @brief Sets the PushAV stream transport server reference for direct API calls + * @param server Pointer to the PushAV stream transport server instance + */ void SetPushAvStreamTransportServer(chip::app::Clusters::PushAvStreamTransportServer * server) { mPushAvStreamTransportServer = server; } + /** + * @brief Sets connection information for the recording session + * @param connectionID The unique connection identifier + * @param triggerType The type of transport trigger that initiated the recording + * @param reasonType The optional reason for trigger activation + */ void SetConnectionInfo(uint16_t connectionID, chip::app::Clusters::PushAvStreamTransport::TransportTriggerTypeEnum triggerType, chip::Optional reasonType) { @@ -171,13 +229,24 @@ class PushAVClipRecorder std::atomic mDeinitializeRecorder{ false }; ///< Deinitialization flag ClipInfoStruct mClipInfo; ///< Clip configuration parameters - void SetRecorderStatus(bool status); ///< Sets the recorder status - bool GetRecorderStatus(); ///< Gets the recorder status + + /** + * @brief Sets the recorder status + * @param status The recorder status to set (true for active, false for inactive) + */ + void SetRecorderStatus(bool status); + + /** + * @brief Gets the current recorder status + * @return true if recorder is active, false otherwise + */ + bool GetRecorderStatus(); + + /** + * @brief Sets the fabric index for the recording session + * @param fabricIndex The fabric index to associate with this recorder + */ void SetFabricIndex(chip::FabricIndex fabricIndex) { mFabricIndex = fabricIndex; } - void SetPushAvStreamTransportManager(chip::app::Clusters::PushAvStreamTransport::PushAvStreamTransportManager * manager) - { - mPushAvStreamTransportManager = manager; - } private: long unsigned int kMaxQueueSize = 500; ///< Maximum queue size for media packets @@ -203,23 +272,27 @@ class PushAVClipRecorder std::queue mAudioQueue; std::queue mVideoQueue; - int mUploadSegmentID; int64_t mCurrentClipStartPts = AV_NOPTS_VALUE; - int64_t mFoundFirstIFramePts = -1; int64_t currentPts = AV_NOPTS_VALUE; + int64_t mLastVideoPts = 0; + int64_t mLastAudioPts = 0; bool mMetadataSet = false; - bool mUploadedInitSegment = false; bool mUploadMPD = false; + bool firstSegmentReady = false; + + std::vector mUploadSegmentID; + std::vector mUploadedInitSegment; + std::vector mStreamIdNameMap; PushAVUploader * mUploader; // Cluster server reference for direct API calls - uint16_t mConnectionID = 0; - chip::FabricIndex mFabricIndex = 0; - chip::app::Clusters::PushAvStreamTransportServer * mPushAvStreamTransportServer = nullptr; - chip::app::Clusters::PushAvStreamTransport::PushAvStreamTransportManager * mPushAvStreamTransportManager = nullptr; + uint16_t mConnectionID = 0; + chip::FabricIndex mFabricIndex = 0; + chip::app::Clusters::PushAvStreamTransportServer * mPushAvStreamTransportServer = nullptr; chip::app::Clusters::PushAvStreamTransport::TransportTriggerTypeEnum mTriggerType; chip ::Optional mReasonType; + std::filesystem::path mUploadFileBasePath; /// @name Internal Methods /// @{ @@ -231,17 +304,53 @@ class PushAVClipRecorder */ bool EnsureDirectoryExists(const std::string & path); - bool CheckAndUploadFile(std::string path); + /** + * @brief Checks if a file exists and adds it to the upload queue. + * @param path The file path to check and upload + * @return true if the file was successfully added to the upload queue, false otherwise + */ + bool CheckAndUploadFile(std::string filename); + /** + * @brief Checks if a file is ready for upload (exists and not being written to). + * @param path The file path to check. + * @return true if the file is ready for upload, false otherwise. + */ + bool IsFileReadyForUpload(const std::filesystem::path & path) const; + + /** + * @brief Updates MPD parameters including startNumber and stream paths. + * + * This function reads an MPD file, finds the startNumber attribute and stream paths, + * and replaces them with appropriate values for the current streams. + * + * @param mpdPath Path to the MPD file to update + */ + void UpdateMPDParams(const std::string & mpdPath); + + /** + * @brief Determines if H.264 data contains an I-frame (IDR frame). + * @param data Pointer to the H.264 NALU data. + * @param length Length of the data in bytes. + * @return true if the data contains an I-frame, false otherwise. + */ bool IsH264IFrame(const uint8_t * data, unsigned int length); - AVPacket * CreatePacket(const uint8_t * data, int size, bool isVideo); + /** + * @brief Creates an AVPacket from raw media data with timestamp conversion + * @param data Raw media data pointer + * @param size Data size in bytes + * @param timestampMs Timestamp in milliseconds + * @param isVideo True for video data, false for audio data + * @return Pointer to created AVPacket, or nullptr on failure + */ + AVPacket * CreatePacket(const uint8_t * data, int size, int64_t timestampMs, bool isVideo); /** * @brief Processes queued packets and writes them to the output file. - * @return Zero if processing was successful, negative otherwise, positive for warnings. + * @return RecorderStatus::kSuccess if processing was successful, RecorderStatus::kFail otherwise. */ - int ProcessBuffersAndWrite(); + RecorderStatus ProcessBuffersAndWrite(); /** * @brief Configures the output format context for DASH/CMAF VoD. @@ -249,21 +358,24 @@ class PushAVClipRecorder * @param output_prefix Base path for output files. * @param init_seg_pattern Pattern for initialization segments. * @param media_seg_pattern Pattern for media segments. + * @return RecorderStatus::kSuccess on success, RecorderStatus::kFail otherwise. */ - int SetupOutput(const std::string & outputPrefix, const std::string & initSegPattern, const std::string & mediaSegPattern); + RecorderStatus SetupOutput(const std::string & outputPrefix, const std::string & initSegPattern, + const std::string & mediaSegPattern); /** * @brief Starts the clip recording process. - * @return 0 on success, error code otherwise. + * @return RecorderStatus::kSuccess on success, RecorderStatus::kFail otherwise. */ - int StartClipRecording(); + RecorderStatus StartClipRecording(); /** * @brief Adds a video or audio stream to the output context. * * @param type The type of stream to add (AVMEDIA_TYPE_VIDEO or AVMEDIA_TYPE_AUDIO). + * @return RecorderStatus::kSuccess on success, RecorderStatus::kFail otherwise. */ - int AddStreamToOutput(AVMediaType type); + RecorderStatus AddStreamToOutput(AVMediaType type); /** * @brief Cleans up the output context and associated resources. @@ -271,10 +383,22 @@ class PushAVClipRecorder void CleanupOutput(); /** - * @brief Finalizes the current clip and prepares for a new one. + * @brief Finalizes the current clip and manages segment uploads. + * + * This function handles the complex logic of clip finalization and segment upload management. + * It coordinates between multiple streams and ensures proper synchronization of uploads. + * + * Key responsibilities: + * - Calculates clip duration and determines if finalization is needed + * - Manages upload of MPD manifest, initialization segments, and media segments + * - Handles different finalization reasons (error, segment check, cleanup) + * - Coordinates upload timing between multiple streams * - * @param reason Zero for normal clip finalization or Positive number for abrupt finalization + * @param reason The reason for clip finalization + * - kErrorOccurred: Finalize due to error condition + * - kSegmentUploadCheck: Normal processing, check for segment uploads + * - kCleanupUpload: Cleanup time, skip finalization logic */ - void FinalizeCurrentClip(int reason); + void FinalizeCurrentClip(ClipFinalizationReason reason); /// @} }; diff --git a/examples/camera-app/linux/include/pushav-prerollbuffer.h b/examples/camera-app/linux/include/pushav-prerollbuffer.h index 1d827c5abf6..b1b59095522 100644 --- a/examples/camera-app/linux/include/pushav-prerollbuffer.h +++ b/examples/camera-app/linux/include/pushav-prerollbuffer.h @@ -47,7 +47,7 @@ class PreRollBuffer { public: PreRollBuffer(); - void PushFrameToBuffer(const std::string & streamKey, const uint8_t * data, size_t size); + void PushFrameToBuffer(const std::string & streamKey, const uint8_t * data, size_t size, int64_t timestampMs); void RegisterTransportToBuffer(BufferSink * sink, const std::unordered_set & streamKeys); void DeregisterTransportFromBuffer(BufferSink * sink); void SetMaxTotalBytes(size_t size); diff --git a/examples/camera-app/linux/include/pushav-transport/pushav-transport.h b/examples/camera-app/linux/include/pushav-transport/pushav-transport.h index 63d8b35c07f..aecb7a091fe 100644 --- a/examples/camera-app/linux/include/pushav-transport/pushav-transport.h +++ b/examples/camera-app/linux/include/pushav-transport/pushav-transport.h @@ -29,39 +29,31 @@ #include #include #include +#include #include -#include #include #include #include #include #include -namespace chip { -namespace app { -namespace Clusters { -namespace PushAvStreamTransport { -class PushAvStreamTransportManager; // Forward declaration -} // namespace PushAvStreamTransport -} // namespace Clusters -} // namespace app -} // namespace chip - -static constexpr int kInvalidZoneId = -1; -static constexpr int kDefaultSensitivity = 5; +static constexpr int kInvalidZoneId = -1; // Invalid zone id value for trigger detection +static constexpr int kDefaultSensitivity = 5; // Default motion sensitivity level +static constexpr int kMaxSessionDurationMinutes = 5; // Maximum session duration in minutes class PushAVTransport : public Transport { public: PushAVTransport(const chip::app::Clusters::PushAvStreamTransport::TransportOptionsStruct & transportOptions, const uint16_t connectionID, AudioStreamStruct & audioStreamParams, VideoStreamStruct & videoStreamParams); + ~PushAVTransport() override; // Send video data for a given stream ID - void SendVideo(const chip::ByteSpan & data, int64_t timestamp, uint16_t videoStreamID) override; + void SendVideo(const chip::ByteSpan & data, int64_t timestampMs, uint16_t videoStreamID) override; // Send audio data for a given stream ID - void SendAudio(const chip::ByteSpan & data, int64_t timestamp, uint16_t audioStreamID) override; + void SendAudio(const chip::ByteSpan & data, int64_t timestampMs, uint16_t audioStreamID) override; // Send synchronized audio/video data for given audio and video stream IDs void SendAudioVideo(const chip::ByteSpan & data, uint16_t videoStreamID, uint16_t audioStreamID) override; @@ -72,8 +64,11 @@ class PushAVTransport : public Transport // Indicates that the transport is ready to send audio data bool CanSendAudio() override; - // Dummy implementation to indicate whether the transport is streaming or not - bool IsStreaming(); + // Update send flags based on current streaming state + void UpdateSendFlags(); + + // Indicates whether the transport is streaming or not + bool IsStreaming() const; bool GetBusyStatus(); @@ -90,10 +85,11 @@ class PushAVTransport : public Transport return (mTransportStatus == chip::app::Clusters::PushAvStreamTransport::TransportStatusEnum::kInactive); } // 0:Active 1:Inactive - void ConfigureRecorderSettings(const chip::app::Clusters::PushAvStreamTransport::TransportOptionsStruct & transportOptions, - AudioStreamStruct & audioStreamParams, VideoStreamStruct & videoStreamParams); + CHIP_ERROR + ConfigureRecorderSettings(const chip::app::Clusters::PushAvStreamTransport::TransportOptionsStruct & transportOptions, + AudioStreamStruct & audioStreamParams, VideoStreamStruct & videoStreamParams); - void ModifyPushTransport(const chip::app::Clusters::PushAvStreamTransport::TransportOptionsStorage & transportOptions); + CHIP_ERROR ModifyPushTransport(const chip::app::Clusters::PushAvStreamTransport::TransportOptionsStorage & transportOptions); bool HandleTriggerDetected(); @@ -126,27 +122,32 @@ class PushAVTransport : public Transport mPushAvStreamTransportServer = server; } - void SetPushAvStreamTransportManager(chip::app::Clusters::PushAvStreamTransport::PushAvStreamTransportManager * manager) - { - mPushAvStreamTransportManager = manager; - } - void ConfigureRecorderTimeSetting( const chip::app::Clusters::PushAvStreamTransport::Structs::TransportMotionTriggerTimeControlStruct::DecodableType & timeControl); void SetFabricIndex(chip::FabricIndex accessingFabricIndex) { mFabricIndex = accessingFabricIndex; } - void StartNewSession(uint64_t newSessionID); + uint64_t GetSessionNumber() const { return mSessionNumber; } private: - bool mHasAugmented = false; - bool mStreaming = false; - std::unique_ptr mRecorder = nullptr; - std::unique_ptr mUploader = nullptr; - chip::FabricIndex mFabricIndex = 0; - chip::app::Clusters::PushAvStreamTransportServer * mPushAvStreamTransportServer = nullptr; - chip::app::Clusters::PushAvStreamTransport::PushAvStreamTransportManager * mPushAvStreamTransportManager = nullptr; + void CheckAndUpdateSession(); + void GeneratePushTransportBeginEvent(); + void StartRecordingAndStreaming(); + bool ValidateZoneAndSensitivity( + const std::vector, uint8_t>> & zoneSensitivityList, int zoneId, + int sensitivity); + + bool mHasAugmented = false; + bool mStreaming = false; + uint64_t mSessionNumber = 1; + std::unique_ptr mRecorder = nullptr; + std::unique_ptr mUploader = nullptr; + chip::FabricIndex mFabricIndex = 0; + chip::app::Clusters::PushAvStreamTransportServer * mPushAvStreamTransportServer = nullptr; + chip::Optional mActivationReason = + chip::Optional(); + std::chrono::system_clock::time_point mSessionStartedTimestamp; std::chrono::steady_clock::time_point mBlindStartTime; PushAVClipRecorder::ClipInfoStruct mClipInfo; PushAVClipRecorder::AudioInfoStruct mAudioInfo; @@ -168,5 +169,7 @@ class PushAVTransport : public Transport chip::app::Clusters::PushAvStreamTransport::TransportStatusEnum mTransportStatus; chip::app::Clusters::PushAvStreamTransport::TransportTriggerTypeEnum mTransportTriggerType; uint16_t mConnectionID; - uint32_t mCurrentlyUsedBandwidthbps = 0; + uint32_t mCurrentlyUsedBandwidthbps = 0; + bool mCurrentActivationByManualTrigger = false; + bool mPreviousActivationByManualTrigger = false; }; diff --git a/examples/camera-app/linux/include/uploader/pushav-uploader.h b/examples/camera-app/linux/include/uploader/pushav-uploader.h index b468fd42cd0..51d37895d10 100644 --- a/examples/camera-app/linux/include/uploader/pushav-uploader.h +++ b/examples/camera-app/linux/include/uploader/pushav-uploader.h @@ -19,11 +19,14 @@ #pragma once #include +#include #include +#include #include #include #include #include +#include typedef struct UploadDataInfo { @@ -55,7 +58,7 @@ class PushAVUploader void Start(); void Stop(); - void AddUploadData(std::string & filename, std::string & url); + void AddUploadData(const std::string & filename, const std::string & url); size_t GetUploadQueueSize() { std::lock_guard lock(mQueueMutex); @@ -64,9 +67,7 @@ class PushAVUploader void setCertificateBuffer(const PushAVCertBuffer & certBuffer) { mCertBuffer = certBuffer; } void setCertificatePath(const PushAVCertPath & certPath) { mCertPath = certPath; } - - void setMPDPath(const std::pair & path) { mMPDPath = path; } - std::pair getMPDPath() const { return mMPDPath; } + void setStreamIdNameMap(const std::vector & streamIdNameMap) { mStreamIdNameMap = streamIdNameMap; } private: void ProcessQueue(); @@ -77,5 +78,5 @@ class PushAVUploader std::mutex mQueueMutex; std::atomic mIsRunning; std::thread mUploaderThread; - std::pair mMPDPath; + std::vector mStreamIdNameMap; }; diff --git a/examples/camera-app/linux/include/webrtc-abstract.h b/examples/camera-app/linux/include/webrtc-abstract.h index e7725dc2296..1b72a574158 100644 --- a/examples/camera-app/linux/include/webrtc-abstract.h +++ b/examples/camera-app/linux/include/webrtc-abstract.h @@ -49,6 +49,13 @@ struct ICECandidateInfo int mlineIndex; }; +struct ICEServerInfo +{ + std::vector urls; + std::string username; + std::string credential; +}; + using OnLocalDescriptionCallback = std::function; using OnICECandidateCallback = std::function; using OnConnectionStateCallback = std::function; @@ -83,4 +90,4 @@ class WebRTCPeerConnection virtual int GetPayloadType(const std::string & sdp, SDPType type, const std::string & codec) { return -1; }; }; -std::shared_ptr CreateWebRTCPeerConnection(); +std::shared_ptr CreateWebRTCPeerConnection(const std::vector & iceServers = {}); diff --git a/examples/camera-app/linux/include/webrtc-transport.h b/examples/camera-app/linux/include/webrtc-transport.h index 388d7d9fe78..69ae1759597 100644 --- a/examples/camera-app/linux/include/webrtc-transport.h +++ b/examples/camera-app/linux/include/webrtc-transport.h @@ -23,7 +23,9 @@ #include #include +#include #include +#include using OnTransportLocalDescriptionCallback = std::function; using OnTransportConnectionStateCallback = std::function; @@ -53,8 +55,8 @@ class WebrtcTransport : public Transport struct RequestArgs { uint16_t sessionId; - uint16_t videoStreamId; - uint16_t audioStreamId; + std::vector videoStreams; + std::vector audioStreams; chip::NodeId peerNodeId; chip::FabricIndex fabricIndex; chip::EndpointId originatingEndpointId; @@ -99,6 +101,9 @@ class WebrtcTransport : public Transport // Adds audio track to the peerconnection with opus codec with default payload type as 111 void AddAudioTrack(const std::string & audioMid = "audio", int payloadType = 111); + // Set ICE servers to use when creating the underlying PeerConnection. Call this before Start(). + void SetICEServers(const std::vector & servers); + std::shared_ptr GetPeerConnection() { return mPeerConnection; } std::string GetLocalDescription() { return mLocalSdp; } @@ -143,4 +148,7 @@ class WebrtcTransport : public Transport RequestArgs mRequestArgs; OnTransportLocalDescriptionCallback mOnLocalDescription = nullptr; OnTransportConnectionStateCallback mOnConnectionState = nullptr; + std::vector mICEServers; + + std::mutex mTrackStatusLock; }; diff --git a/examples/camera-app/linux/main.cpp b/examples/camera-app/linux/main.cpp index 9dec4d26850..ad3795c7571 100644 --- a/examples/camera-app/linux/main.cpp +++ b/examples/camera-app/linux/main.cpp @@ -18,6 +18,8 @@ #include "CameraAppCommandDelegate.h" #include "camera-app.h" #include "camera-device.h" +#include "tls-certificate-management-instance.h" +#include "tls-client-management-instance.h" #include #include @@ -57,7 +59,7 @@ void ApplicationInit() if ((!appPipePath.empty()) && (sChipNamedPipeCommands.Start(appPipePath, &sCameraAppCommandDelegate) != CHIP_NO_ERROR)) { ChipLogError(NotSpecified, "Failed to start CHIP NamedPipeCommands"); - sChipNamedPipeCommands.Stop(); + TEMPORARY_RETURN_IGNORED sChipNamedPipeCommands.Stop(); } gCameraDevice.Init(); @@ -70,13 +72,18 @@ void ApplicationShutdown() { CameraAppShutdown(); - sChipNamedPipeCommands.Stop(); + TEMPORARY_RETURN_IGNORED sChipNamedPipeCommands.Stop(); } int main(int argc, char * argv[]) { VerifyOrDie(ChipLinuxAppInit(argc, argv) == 0); + // Initialize TLS Client and Certificate Management delegates before server starts + // This must be called before ChipLinuxAppMainLoop() which initializes the server + InitializeTlsClientManagement(); + InitializeTlsCertificateManagement(); + ChipLinuxAppMainLoop(); return 0; diff --git a/examples/camera-app/linux/src/CameraAppCommandDelegate.cpp b/examples/camera-app/linux/src/CameraAppCommandDelegate.cpp index 02cfbf63c04..cf27c9068e3 100644 --- a/examples/camera-app/linux/src/CameraAppCommandDelegate.cpp +++ b/examples/camera-app/linux/src/CameraAppCommandDelegate.cpp @@ -83,7 +83,7 @@ void CameraAppCommandHandler::OnZoneTriggeredHandler(uint16_t zoneId) void CameraAppCommandHandler::OnSetHardPrivacyModeOnHandler(bool value) { - mCameraDevice->GetCameraAVStreamMgmtController().SetHardPrivacyModeOn(value); + TEMPORARY_RETURN_IGNORED mCameraDevice->GetCameraAVStreamMgmtController().SetHardPrivacyModeOn(value); } void CameraAppCommandDelegate::SetCameraDevice(Camera::CameraDevice * aCameraDevice) @@ -101,5 +101,6 @@ void CameraAppCommandDelegate::OnEventCommandReceived(const char * json) } handler->SetCameraDevice(mCameraDevice); - chip::DeviceLayer::PlatformMgr().ScheduleWork(CameraAppCommandHandler::HandleCommand, reinterpret_cast(handler)); + TEMPORARY_RETURN_IGNORED chip::DeviceLayer::PlatformMgr().ScheduleWork(CameraAppCommandHandler::HandleCommand, + reinterpret_cast(handler)); } diff --git a/examples/camera-app/linux/src/camera-device.cpp b/examples/camera-app/linux/src/camera-device.cpp index 502714a61bf..d89abef3e72 100644 --- a/examples/camera-app/linux/src/camera-device.cpp +++ b/examples/camera-app/linux/src/camera-device.cpp @@ -90,40 +90,38 @@ GstFlowReturn OnNewVideoSampleFromAppSink(GstAppSink * appsink, gpointer user_da GstMapInfo map; if (gst_buffer_map(buffer, &map, GST_MAP_READ)) { - // Check if SFrame encryption is enabled for this stream - auto & mediaController = self->GetMediaController(); - Transport * transport = mediaController.GetTransportForVideoStream(videoStreamID); - - if (transport != nullptr && transport->sFrameConfig.HasValue()) + GstClockTime rawPts = GST_BUFFER_PTS(buffer); + if (rawPts == GST_CLOCK_TIME_NONE) { - auto & sframeConfig = transport->sFrameConfig.Value(); - ChipLogProgress(Camera, "SFrame encryption enabled for video stream %u: cipherSuite=0x%04X, keyLen=%u", videoStreamID, - sframeConfig.cipherSuite, static_cast(sframeConfig.baseKey.size())); - - // TODO: Implement SFrame encryption (occurs AFTER H.264 encoding, BEFORE RTP packetization) - // Current state: map.data contains H.264 encoded frames from GStreamer - // - // SFrame encryption steps: - // 1. Take the H.264 compressed payload (map.data, map.size) - // 2. Select encryption algorithm based on cipherSuite: - // - 0x0001: AES-128-GCM-SHA256 (16 byte key) - // - 0x0002: AES-256-GCM-SHA512 (32 byte key) - // 3. Encrypt the H.264 payload using sframeConfig.baseKey - // 4. Build SFrame header containing: - // - Key ID (kid) from sframeConfig.kid - // - Frame counter (incremented per frame) - // 5. Prepend SFrame header to encrypted payload: - // Result: [SFrame Header | Encrypted(H.264 Payload)] - // 6. This will later be packed into RTP as: - // [RTP Header | SFrame Header | Encrypted(H.264 Payload)] - // SFUs can inspect RTP headers but payload remains encrypted + rawPts = GST_BUFFER_DTS(buffer); + if (rawPts == GST_CLOCK_TIME_NONE) + { + rawPts = 0; + } + } + auto firstPtsIt = self->mVideoStreamFirstPts.find(videoStreamID); + if (firstPtsIt == self->mVideoStreamFirstPts.end()) + { + self->mVideoStreamFirstPts[videoStreamID] = rawPts; + } + GstClockTime offsetNs = 0; + int64_t startEpoch = self->mVideoStreamStartEpochs[videoStreamID]; + int64_t ts = 0; + if (rawPts >= self->mVideoStreamFirstPts[videoStreamID]) + { + offsetNs = rawPts - self->mVideoStreamFirstPts[videoStreamID]; + ts = startEpoch + (offsetNs / 1000000); // Convert ns to ms + // Forward raw H.264 encoded frames to media controller with timestamp + // The PreRollBuffer will distribute to ALL transports registered for this videoStreamID + // Each transport will handle its own SFrame encryption (if configured) during RTP packetization + self->GetMediaController().DistributeVideo(reinterpret_cast(map.data), map.size, videoStreamID, ts); + } + else + { + ChipLogError(Camera, + "Dropping video frame with PTS %" G_GUINT64_FORMAT " <= first PTS %" G_GUINT64_FORMAT " for stream %u", + rawPts, self->mVideoStreamFirstPts[videoStreamID], videoStreamID); } - - // If SFrame is enabled above, this should be: [SFrame Header | Encrypted(H.264)] - // If SFrame is disabled, this is raw H.264 encoded frames - - // Forward H.264 RTP data to media controller with the correct videoStreamID - self->GetMediaController().DistributeVideo(reinterpret_cast(map.data), map.size, videoStreamID); gst_buffer_unmap(buffer, &map); } @@ -164,40 +162,38 @@ static GstFlowReturn OnNewAudioSampleFromAppSink(GstAppSink * appsink, gpointer GstMapInfo map; if (gst_buffer_map(buffer, &map, GST_MAP_READ)) { - // Check if SFrame encryption is enabled for this stream - auto & mediaController = self->GetMediaController(); - Transport * transport = mediaController.GetTransportForAudioStream(audioStreamID); - - if (transport != nullptr && transport->sFrameConfig.HasValue()) + GstClockTime rawPts = GST_BUFFER_PTS(buffer); + if (rawPts == GST_CLOCK_TIME_NONE) { - auto & sframeConfig = transport->sFrameConfig.Value(); - ChipLogProgress(Camera, "SFrame encryption enabled for audio stream %u: cipherSuite=0x%04X, keyLen=%u", audioStreamID, - sframeConfig.cipherSuite, static_cast(sframeConfig.baseKey.size())); - - // TODO: Implement SFrame encryption (occurs AFTER Opus encoding, BEFORE RTP packetization) - // Current state: map.data contains Opus encoded frames from GStreamer - // - // SFrame encryption steps: - // 1. Take the Opus compressed payload (map.data, map.size) - // 2. Select encryption algorithm based on cipherSuite: - // - 0x0001: AES-128-GCM-SHA256 (16 byte key) - // - 0x0002: AES-256-GCM-SHA512 (32 byte key) - // 3. Encrypt the Opus payload using sframeConfig.baseKey - // 4. Build SFrame header containing: - // - Key ID (kid) from sframeConfig.kid - // - Frame counter (incremented per frame) - // 5. Prepend SFrame header to encrypted payload: - // Result: [SFrame Header | Encrypted(Opus Payload)] - // 6. This will later be packed into RTP as: - // [RTP Header | SFrame Header | Encrypted(Opus Payload)] - // SFUs can inspect RTP headers but payload remains encrypted + rawPts = GST_BUFFER_DTS(buffer); + if (rawPts == GST_CLOCK_TIME_NONE) + { + rawPts = 0; + } + } + auto firstPtsIt = self->mAudioStreamFirstPts.find(audioStreamID); + if (firstPtsIt == self->mAudioStreamFirstPts.end()) + { + self->mAudioStreamFirstPts[audioStreamID] = rawPts; + } + GstClockTime offsetNs = 0; + int64_t startEpoch = self->mAudioStreamStartEpochs[audioStreamID]; + int64_t ts = 0; + if (rawPts >= self->mAudioStreamFirstPts[audioStreamID]) + { + offsetNs = rawPts - self->mAudioStreamFirstPts[audioStreamID]; + ts = startEpoch + (offsetNs / 1000000); // Convert ns to ms + // Forward raw Opus encoded frames to media controller with timestamp + // The PreRollBuffer will distribute to ALL transports registered for this audioStreamID + // Each transport will handle its own SFrame encryption (if configured) during RTP packetization + self->GetMediaController().DistributeAudio(reinterpret_cast(map.data), map.size, audioStreamID, ts); + } + else + { + ChipLogError(Camera, + "Dropping audio frame with PTS %" G_GUINT64_FORMAT " <= first PTS %" G_GUINT64_FORMAT " for stream %u", + rawPts, self->mAudioStreamFirstPts[audioStreamID], audioStreamID); } - - // If SFrame is enabled above, this should be: [SFrame Header | Encrypted(Opus)] - // If SFrame is disabled, this is raw Opus encoded frames - - // Send raw Opus frames to the media controller - self->GetMediaController().DistributeAudio(reinterpret_cast(map.data), map.size, audioStreamID); gst_buffer_unmap(buffer, &map); } @@ -967,6 +963,10 @@ CameraError CameraDevice::StartVideoStream(const VideoStreamStruct & allocatedSt return CameraError::ERROR_VIDEO_STREAM_START_FAILED; } + mVideoStreamFirstPts.erase(streamID); + auto now = std::chrono::steady_clock::now().time_since_epoch(); + mVideoStreamStartEpochs[streamID] = std::chrono::duration_cast(now).count(); + // Store in stream context it->videoContext = videoPipeline; @@ -1066,6 +1066,10 @@ CameraError CameraDevice::StartAudioStream(uint16_t streamID) return CameraError::ERROR_AUDIO_STREAM_START_FAILED; } + mAudioStreamFirstPts.erase(streamID); + auto now = std::chrono::steady_clock::now().time_since_epoch(); + mAudioStreamStartEpochs[streamID] = std::chrono::duration_cast(now).count(); + // Store in stream context it->audioContext = audioPipeline; @@ -1174,7 +1178,7 @@ CameraError CameraDevice::StopAudioPlaybackStream() } // Allocate snapshot stream -CameraError CameraDevice::AllocateSnapshotStream(const CameraAVStreamMgmtDelegate::SnapshotStreamAllocateArgs & args, +CameraError CameraDevice::AllocateSnapshotStream(const CameraAVStreamManagementDelegate::SnapshotStreamAllocateArgs & args, uint16_t & outStreamID) { @@ -1631,20 +1635,22 @@ CameraError CameraDevice::UpdateZoneTrigger(const ZoneTriggerControlStruct & zon return CameraError::SUCCESS; } -CameraError CameraDevice::RemoveZoneTrigger(const uint16_t zoneID) +CameraError CameraDevice::RemoveZoneTrigger(const uint16_t zoneId) { return CameraError::SUCCESS; } -void CameraDevice::HandleSimulatedZoneTriggeredEvent(uint16_t zoneID) +void CameraDevice::HandleSimulatedZoneTriggeredEvent(uint16_t zoneId) { - mZoneManager.OnZoneTriggeredEvent(zoneID, ZoneEventTriggeredReasonEnum::kMotion); + mZoneManager.OnZoneTriggeredEvent(zoneId, ZoneEventTriggeredReasonEnum::kMotion); + mPushAVTransportManager.HandleZoneTrigger(zoneId); } -void CameraDevice::HandleSimulatedZoneStoppedEvent(uint16_t zoneID) +void CameraDevice::HandleSimulatedZoneStoppedEvent(uint16_t zoneId) { - mZoneManager.OnZoneStoppedEvent(zoneID, ZoneEventStoppedReasonEnum::kActionStopped); + mZoneManager.OnZoneStoppedEvent(zoneId, ZoneEventStoppedReasonEnum::kActionStopped); + // Note: PushAVTransportManager doesn't need zone stopped event currently } void CameraDevice::InitializeVideoStreams() @@ -1748,8 +1754,8 @@ void CameraDevice::InitializeSnapshotStreams() streamId); } -bool CameraDevice::AddSnapshotStream(const CameraAVStreamMgmtDelegate::SnapshotStreamAllocateArgs & snapshotStreamAllocateArgs, - uint16_t & outStreamID) +bool CameraDevice::AddSnapshotStream( + const CameraAVStreamManagementDelegate::SnapshotStreamAllocateArgs & snapshotStreamAllocateArgs, uint16_t & outStreamID) { constexpr uint16_t kMaxSnapshotStreams = std::numeric_limits::max(); @@ -1834,9 +1840,9 @@ WebRTCTransportProvider::Delegate & CameraDevice::GetWebRTCProviderDelegate() return mWebRTCProviderManager; } -WebRTCTransportProvider::WebRTCTransportProviderController & CameraDevice::GetWebRTCProviderController() +void CameraDevice::SetWebRTCTransportProvider(WebRTCTransportProvider::WebRTCTransportProviderCluster * provider) { - return mWebRTCProviderManager; + mWebRTCProviderManager.SetWebRTCTransportProvider(provider); } PushAvStreamTransportDelegate & CameraDevice::GetPushAVTransportDelegate() @@ -1844,7 +1850,7 @@ PushAvStreamTransportDelegate & CameraDevice::GetPushAVTransportDelegate() return mPushAVTransportManager; } -CameraAVStreamMgmtDelegate & CameraDevice::GetCameraAVStreamMgmtDelegate() +CameraAVStreamManagementDelegate & CameraDevice::GetCameraAVStreamMgmtDelegate() { return mCameraAVStreamManager; } @@ -1854,7 +1860,7 @@ CameraAVStreamController & CameraDevice::GetCameraAVStreamMgmtController() return mCameraAVStreamManager; } -CameraAvSettingsUserLevelManagement::Delegate & CameraDevice::GetCameraAVSettingsUserLevelMgmtDelegate() +CameraAvSettingsUserLevelManagementDelegate & CameraDevice::GetCameraAVSettingsUserLevelMgmtDelegate() { return mCameraAVSettingsUserLevelManager; } @@ -1869,11 +1875,6 @@ MediaController & CameraDevice::GetMediaController() return mMediaController; } -void CameraDevice::HandlePushAvZoneTrigger(uint16_t zoneId) -{ - mPushAVTransportManager.HandleZoneTrigger(zoneId); -} - size_t CameraDevice::GetPreRollBufferSize() { return kMaxContentBufferSizeBytes; diff --git a/examples/camera-app/linux/src/clusters/camera-avsettingsuserlevel-mgmt/camera-avsettingsuserlevel-manager.cpp b/examples/camera-app/linux/src/clusters/camera-avsettingsuserlevel-mgmt/camera-avsettingsuserlevel-manager.cpp index 543ef87ac34..20de7e8457f 100644 --- a/examples/camera-app/linux/src/clusters/camera-avsettingsuserlevel-mgmt/camera-avsettingsuserlevel-manager.cpp +++ b/examples/camera-app/linux/src/clusters/camera-avsettingsuserlevel-mgmt/camera-avsettingsuserlevel-manager.cpp @@ -16,8 +16,7 @@ * limitations under the License. */ -#include -#include +#include #include #include #include @@ -73,7 +72,7 @@ Status CameraAVSettingsUserLevelManager::MPTZSetPosition(Optional aPan, // For the purposes of the Camera App, run a timer equivalent to a typical physical elapsed time for PTZ. An actual HAL will // invoke OnPhysicalMoveCompleted method once it has determined via its own means that the move is completed. // - DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(2), onTimerExpiry, this); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(2), onTimerExpiry, this); return Status::Success; } @@ -91,7 +90,7 @@ Status CameraAVSettingsUserLevelManager::MPTZRelativeMove(Optional aPan // For the purposes of the Camera App, run a timer equivalent to a typical physical elapsed time for PTZ. AAn actual HAL will // invoke OnPhysicalMoveCompleted method once it has determined via its own means that the move is completed. // - DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(2), onTimerExpiry, this); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(2), onTimerExpiry, this); return Status::Success; } @@ -109,7 +108,7 @@ Status CameraAVSettingsUserLevelManager::MPTZMoveToPreset(uint8_t aPreset, Optio // For the purposes of the Camera App, run a timer equivalent to a typical physical elapsed time for PTZ. AAn actual HAL will // invoke OnPhysicalMoveCompleted method once it has determined via its own means that the move is completed. // - DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(2), onTimerExpiry, this); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(2), onTimerExpiry, this); return Status::Success; } @@ -296,7 +295,7 @@ CHIP_ERROR CameraAVSettingsUserLevelManager::LoadMPTZPresets(std::vector & dptzStreams) +CHIP_ERROR CameraAVSettingsUserLevelManager::LoadDPTZStreams(std::vector & dptzStreams) { dptzStreams.clear(); return CHIP_NO_ERROR; diff --git a/examples/camera-app/linux/src/clusters/camera-avstream-mgmt/camera-av-stream-manager.cpp b/examples/camera-app/linux/src/clusters/camera-avstream-mgmt/camera-av-stream-manager.cpp index 59cbd6723e9..89fdfd5c403 100644 --- a/examples/camera-app/linux/src/clusters/camera-avstream-mgmt/camera-av-stream-manager.cpp +++ b/examples/camera-app/linux/src/clusters/camera-avstream-mgmt/camera-av-stream-manager.cpp @@ -49,22 +49,21 @@ void CameraAVStreamManager::SetCameraDeviceHAL(CameraDeviceInterface * aCameraDe mCameraDeviceHAL = aCameraDeviceHAL; } -CHIP_ERROR CameraAVStreamManager::ValidateStreamUsage(StreamUsageEnum streamUsage, - Optional> & videoStreamId, - Optional> & audioStreamId) +CHIP_ERROR CameraAVStreamManager::ValidateStreamUsage(StreamUsageEnum streamUsage, Optional> & videoStreams, + Optional> & audioStreams) { // The server ensures that at least one stream Id has a value, and that there are streams allocated - // If a stream id(s) are provided, it's sufficient to have verified that the provide usage is supported by the camera. - // If they're Null, look for a stream ID that matches the usage. A match does not need to be exact. + // If stream id(s) are provided, it's sufficient to have verified that the provided usage is supported by the camera. + // If the vector is empty, look for a stream ID that matches the usage. A match does not need to be exact. bool exactlyMatchedVideoStream = false; bool looselyMatchedVideoStream = false; - uint16_t looseVideoStreamID; + uint16_t looseVideoStreamID = 0; bool exactlyMatchedAudioStream = false; bool looselyMatchedAudioStream = false; - uint16_t looseAudioStreamID; + uint16_t looseAudioStreamID = 0; // Is the requested stream usage supported by the camera? - auto myStreamUsages = GetCameraAVStreamMgmtServer()->GetSupportedStreamUsages(); + auto myStreamUsages = GetCameraAVStreamManagementCluster()->GetSupportedStreamUsages(); auto it = std::find(myStreamUsages.begin(), myStreamUsages.end(), streamUsage); if (it == myStreamUsages.end()) { @@ -72,19 +71,19 @@ CHIP_ERROR CameraAVStreamManager::ValidateStreamUsage(StreamUsageEnum streamUsag return CHIP_ERROR_NOT_FOUND; } - if (videoStreamId.HasValue()) + if (videoStreams.HasValue()) { - const std::vector & allocatedVideoStreams = GetCameraAVStreamMgmtServer()->GetAllocatedVideoStreams(); + const std::vector & allocatedVideoStreams = + GetCameraAVStreamManagementCluster()->GetAllocatedVideoStreams(); - // If no Video ID is provided, match to an allocated ID. Exact is preferred if found. We know the stream requested is in - // supported streams. - if (videoStreamId.Value().IsNull()) + // If video streams vector is empty, auto-select a video stream. Exact usage match is preferred. + if (videoStreams.Value().empty()) { for (const auto & stream : allocatedVideoStreams) { if (stream.streamUsage == streamUsage) { - videoStreamId.Emplace(stream.videoStreamID); + videoStreams.Value().push_back(stream.videoStreamID); exactlyMatchedVideoStream = true; break; } @@ -95,25 +94,25 @@ CHIP_ERROR CameraAVStreamManager::ValidateStreamUsage(StreamUsageEnum streamUsag } else { - // We've been provided with a stream ID, and we know the stream usage is supported by the camera, classify as an exact + // We've been provided with stream ID(s), and we know the stream usage is supported by the camera, classify as an exact // match exactlyMatchedVideoStream = true; } } - if (audioStreamId.HasValue()) + if (audioStreams.HasValue()) { - const std::vector & allocatedAudioStreams = GetCameraAVStreamMgmtServer()->GetAllocatedAudioStreams(); + const std::vector & allocatedAudioStreams = + GetCameraAVStreamManagementCluster()->GetAllocatedAudioStreams(); - // If no Audio ID is provided, match to an allocated ID. Exact is preferred if found. We know the stream requested is in - // supported streams. - if (audioStreamId.Value().IsNull()) + // If audio streams vector is empty, auto-select an audio stream. Exact usage match is preferred. + if (audioStreams.Value().empty()) { for (const auto & stream : allocatedAudioStreams) { if (stream.streamUsage == streamUsage) { - audioStreamId.Emplace(stream.audioStreamID); + audioStreams.Value().push_back(stream.audioStreamID); exactlyMatchedAudioStream = true; break; } @@ -124,22 +123,21 @@ CHIP_ERROR CameraAVStreamManager::ValidateStreamUsage(StreamUsageEnum streamUsag } else { - // We've been provided with a stream ID, and we know the stream usage is supported by the camera, classify as an exact + // We've been provided with stream ID(s), and we know the stream usage is supported by the camera, classify as an exact // match exactlyMatchedAudioStream = true; } } // If we have a loose match and no exact match, update the provided stream IDs with the loose match values - // if (looselyMatchedAudioStream && !exactlyMatchedAudioStream) { - audioStreamId.Emplace(looseAudioStreamID); + audioStreams.Value().push_back(looseAudioStreamID); } if (looselyMatchedVideoStream && !exactlyMatchedVideoStream) { - videoStreamId.Emplace(looseVideoStreamID); + videoStreams.Value().push_back(looseVideoStreamID); } return CHIP_NO_ERROR; @@ -148,13 +146,13 @@ CHIP_ERROR CameraAVStreamManager::ValidateStreamUsage(StreamUsageEnum streamUsag const std::vector & CameraAVStreamManager::GetAllocatedVideoStreams() const { - return GetCameraAVStreamMgmtServer()->GetAllocatedVideoStreams(); + return GetCameraAVStreamManagementCluster()->GetAllocatedVideoStreams(); } const std::vector & CameraAVStreamManager::GetAllocatedAudioStreams() const { - return GetCameraAVStreamMgmtServer()->GetAllocatedAudioStreams(); + return GetCameraAVStreamManagementCluster()->GetAllocatedAudioStreams(); } void CameraAVStreamManager::GetBandwidthForStreams(const Optional> & videoStreamId, @@ -166,7 +164,7 @@ void CameraAVStreamManager::GetBandwidthForStreams(const OptionalGetAllocatedVideoStreams(); + auto & allocatedVideoStreams = GetCameraAVStreamManagementCluster()->GetAllocatedVideoStreams(); for (const chip::app::Clusters::CameraAvStreamManagement::Structs::VideoStreamStruct::Type & stream : allocatedVideoStreams) { if (stream.videoStreamID == vStreamId) @@ -180,7 +178,7 @@ void CameraAVStreamManager::GetBandwidthForStreams(const OptionalGetAllocatedAudioStreams(); + auto & allocatedAudioStreams = GetCameraAVStreamManagementCluster()->GetAllocatedAudioStreams(); for (const chip::app::Clusters::CameraAvStreamManagement::Structs::AudioStreamStruct::Type & stream : allocatedAudioStreams) { if (stream.audioStreamID == aStreamId) @@ -196,7 +194,7 @@ void CameraAVStreamManager::GetBandwidthForStreams(const Optional & allocatedVideoStreams = GetCameraAVStreamMgmtServer()->GetAllocatedVideoStreams(); + const std::vector & allocatedVideoStreams = GetCameraAVStreamManagementCluster()->GetAllocatedVideoStreams(); // Check if the videoStreamId exists in allocated streams for (const auto & stream : allocatedVideoStreams) @@ -214,7 +212,7 @@ CHIP_ERROR CameraAVStreamManager::ValidateVideoStreamID(uint16_t videoStreamId) CHIP_ERROR CameraAVStreamManager::ValidateAudioStreamID(uint16_t audioStreamId) { - const std::vector & allocatedAudioStreams = GetCameraAVStreamMgmtServer()->GetAllocatedAudioStreams(); + const std::vector & allocatedAudioStreams = GetCameraAVStreamManagementCluster()->GetAllocatedAudioStreams(); // Check if the audioStreamId exists in allocated streams for (const auto & stream : allocatedAudioStreams) @@ -230,41 +228,95 @@ CHIP_ERROR CameraAVStreamManager::ValidateAudioStreamID(uint16_t audioStreamId) return CHIP_ERROR_INVALID_ARGUMENT; } +CHIP_ERROR CameraAVStreamManager::ValidateVideoStreams(const std::vector & videoStreams) +{ + const std::vector & allocatedVideoStreams = GetCameraAVStreamManagementCluster()->GetAllocatedVideoStreams(); + + // Check if each videoStreamId exists in allocated streams + for (uint16_t videoStreamId : videoStreams) + { + bool found = false; + for (const auto & stream : allocatedVideoStreams) + { + if (stream.videoStreamID == videoStreamId) + { + ChipLogProgress(Camera, "Video stream ID %u is valid and allocated", videoStreamId); + found = true; + break; + } + } + if (!found) + { + ChipLogError(Camera, "Video stream ID %u not found in allocated video streams", videoStreamId); + return CHIP_ERROR_INVALID_ARGUMENT; + } + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR CameraAVStreamManager::ValidateAudioStreams(const std::vector & audioStreams) +{ + const std::vector & allocatedAudioStreams = GetCameraAVStreamManagementCluster()->GetAllocatedAudioStreams(); + + // Check if each audioStreamId exists in allocated streams + for (uint16_t audioStreamId : audioStreams) + { + bool found = false; + for (const auto & stream : allocatedAudioStreams) + { + if (stream.audioStreamID == audioStreamId) + { + ChipLogProgress(Camera, "Audio stream ID %u is valid and allocated", audioStreamId); + found = true; + break; + } + } + if (!found) + { + ChipLogError(Camera, "Audio stream ID %u not found in allocated audio streams", audioStreamId); + return CHIP_ERROR_INVALID_ARGUMENT; + } + } + + return CHIP_NO_ERROR; +} + CHIP_ERROR CameraAVStreamManager::IsHardPrivacyModeActive(bool & isActive) { // Check privacy mode attributes - isActive = GetCameraAVStreamMgmtServer()->GetHardPrivacyModeOn(); + isActive = GetCameraAVStreamManagementCluster()->GetHardPrivacyModeOn(); return CHIP_NO_ERROR; } CHIP_ERROR CameraAVStreamManager::IsSoftRecordingPrivacyModeActive(bool & isActive) { // Check privacy mode attributes - isActive = GetCameraAVStreamMgmtServer()->GetSoftRecordingPrivacyModeEnabled(); + isActive = GetCameraAVStreamManagementCluster()->GetSoftRecordingPrivacyModeEnabled(); return CHIP_NO_ERROR; } CHIP_ERROR CameraAVStreamManager::IsSoftLivestreamPrivacyModeActive(bool & isActive) { // Check privacy mode attributes - isActive = GetCameraAVStreamMgmtServer()->GetSoftLivestreamPrivacyModeEnabled(); + isActive = GetCameraAVStreamManagementCluster()->GetSoftLivestreamPrivacyModeEnabled(); return CHIP_NO_ERROR; } CHIP_ERROR CameraAVStreamManager::SetHardPrivacyModeOn(bool hardPrivacyMode) { - return GetCameraAVStreamMgmtServer()->SetHardPrivacyModeOn(hardPrivacyMode); + return GetCameraAVStreamManagementCluster()->SetHardPrivacyModeOn(hardPrivacyMode); } bool CameraAVStreamManager::HasAllocatedVideoStreams() { - const std::vector & allocatedVideoStreams = GetCameraAVStreamMgmtServer()->GetAllocatedVideoStreams(); + const std::vector & allocatedVideoStreams = GetCameraAVStreamManagementCluster()->GetAllocatedVideoStreams(); return !allocatedVideoStreams.empty(); } bool CameraAVStreamManager::HasAllocatedAudioStreams() { - const std::vector & allocatedAudioStreams = GetCameraAVStreamMgmtServer()->GetAllocatedAudioStreams(); + const std::vector & allocatedAudioStreams = GetCameraAVStreamManagementCluster()->GetAllocatedAudioStreams(); return !allocatedAudioStreams.empty(); } @@ -290,7 +342,7 @@ Protocols::InteractionModel::Status CameraAVStreamManager::VideoStreamAllocate(c } // Try to reuse an allocated stream - std::optional reusableStreamId = GetCameraAVStreamMgmtServer()->GetReusableVideoStreamId(allocateArgs); + std::optional reusableStreamId = GetCameraAVStreamManagementCluster()->GetReusableVideoStreamId(allocateArgs); if (reusableStreamId.has_value()) { @@ -308,7 +360,8 @@ Protocols::InteractionModel::Status CameraAVStreamManager::VideoStreamAllocate(c uint32_t candidateEncodedPixelRate = allocateArgs.maxFrameRate * allocateArgs.maxResolution.height * allocateArgs.maxResolution.width; bool encoderRequired = true; - if (!GetCameraAVStreamMgmtServer()->IsResourceAvailableForStreamAllocation(candidateEncodedPixelRate, encoderRequired)) + if (!GetCameraAVStreamManagementCluster()->IsResourceAvailableForStreamAllocation(candidateEncodedPixelRate, + encoderRequired)) { return Status::ResourceExhausted; } @@ -322,7 +375,8 @@ Protocols::InteractionModel::Status CameraAVStreamManager::VideoStreamAllocate(c mCameraDeviceHAL->GetCameraAVSettingsUserLevelMgmtDelegate().VideoStreamAllocated(outStreamID); // Set the current frame rate attribute from HAL - GetCameraAVStreamMgmtServer()->SetCurrentFrameRate(mCameraDeviceHAL->GetCameraHALInterface().GetCurrentFrameRate()); + TEMPORARY_RETURN_IGNORED GetCameraAVStreamManagementCluster()->SetCurrentFrameRate( + mCameraDeviceHAL->GetCameraHALInterface().GetCurrentFrameRate()); return Status::Success; } @@ -341,7 +395,8 @@ void CameraAVStreamManager::OnVideoStreamAllocated(const VideoStreamStruct & all mCameraDeviceHAL->GetCameraHALInterface().StartVideoStream(allocatedStream); // Set the current frame rate attribute from HAL once stream has started - GetCameraAVStreamMgmtServer()->SetCurrentFrameRate(mCameraDeviceHAL->GetCameraHALInterface().GetCurrentFrameRate()); + TEMPORARY_RETURN_IGNORED GetCameraAVStreamManagementCluster()->SetCurrentFrameRate( + mCameraDeviceHAL->GetCameraHALInterface().GetCurrentFrameRate()); break; case StreamAllocationAction::kModification: @@ -486,7 +541,7 @@ Protocols::InteractionModel::Status CameraAVStreamManager::SnapshotStreamAllocat } // Try to reuse an allocated stream. - std::optional reusableStreamId = GetCameraAVStreamMgmtServer()->GetReusableSnapshotStreamId(allocateArgs); + std::optional reusableStreamId = GetCameraAVStreamManagementCluster()->GetReusableSnapshotStreamId(allocateArgs); if (reusableStreamId.has_value()) { @@ -508,7 +563,7 @@ Protocols::InteractionModel::Status CameraAVStreamManager::SnapshotStreamAllocat } } - if (!GetCameraAVStreamMgmtServer()->IsResourceAvailableForStreamAllocation(candidateEncodedPixelRate, encoderRequired)) + if (!GetCameraAVStreamManagementCluster()->IsResourceAvailableForStreamAllocation(candidateEncodedPixelRate, encoderRequired)) { return Status::ResourceExhausted; } @@ -600,7 +655,8 @@ Protocols::InteractionModel::Status CameraAVStreamManager::SnapshotStreamDealloc void CameraAVStreamManager::OnStreamUsagePrioritiesChanged() { ChipLogProgress(Camera, "Stream usage priorities changed"); - mCameraDeviceHAL->GetCameraHALInterface().SetStreamUsagePriorities(GetCameraAVStreamMgmtServer()->GetStreamUsagePriorities()); + mCameraDeviceHAL->GetCameraHALInterface().SetStreamUsagePriorities( + GetCameraAVStreamManagementCluster()->GetStreamUsagePriorities()); } void CameraAVStreamManager::OnAttributeChanged(AttributeId attributeId) @@ -611,25 +667,25 @@ void CameraAVStreamManager::OnAttributeChanged(AttributeId attributeId) { case HDRModeEnabled::Id: { - mCameraDeviceHAL->GetCameraHALInterface().SetHDRMode(GetCameraAVStreamMgmtServer()->GetHDRModeEnabled()); + mCameraDeviceHAL->GetCameraHALInterface().SetHDRMode(GetCameraAVStreamManagementCluster()->GetHDRModeEnabled()); break; } case SoftRecordingPrivacyModeEnabled::Id: { mCameraDeviceHAL->GetCameraHALInterface().SetSoftRecordingPrivacyModeEnabled( - GetCameraAVStreamMgmtServer()->GetSoftRecordingPrivacyModeEnabled()); + GetCameraAVStreamManagementCluster()->GetSoftRecordingPrivacyModeEnabled()); break; } case SoftLivestreamPrivacyModeEnabled::Id: { mCameraDeviceHAL->GetCameraHALInterface().SetSoftLivestreamPrivacyModeEnabled( - GetCameraAVStreamMgmtServer()->GetSoftLivestreamPrivacyModeEnabled()); + GetCameraAVStreamManagementCluster()->GetSoftLivestreamPrivacyModeEnabled()); break; } case HardPrivacyModeOn::Id: { - mCameraDeviceHAL->GetCameraHALInterface().SetHardPrivacyMode(GetCameraAVStreamMgmtServer()->GetHardPrivacyModeOn()); + mCameraDeviceHAL->GetCameraHALInterface().SetHardPrivacyMode(GetCameraAVStreamManagementCluster()->GetHardPrivacyModeOn()); break; } case NightVision::Id: { - mCameraDeviceHAL->GetCameraHALInterface().SetNightVision(GetCameraAVStreamMgmtServer()->GetNightVision()); + mCameraDeviceHAL->GetCameraHALInterface().SetNightVision(GetCameraAVStreamManagementCluster()->GetNightVision()); break; } case NightVisionIllum::Id: { @@ -637,59 +693,63 @@ void CameraAVStreamManager::OnAttributeChanged(AttributeId attributeId) } case Viewport::Id: { // Update the device default - mCameraDeviceHAL->GetCameraHALInterface().SetViewport(GetCameraAVStreamMgmtServer()->GetViewport()); + mCameraDeviceHAL->GetCameraHALInterface().SetViewport(GetCameraAVStreamManagementCluster()->GetViewport()); // Update the per stream viewports on the camera for (VideoStream & stream : mCameraDeviceHAL->GetCameraHALInterface().GetAvailableVideoStreams()) { - mCameraDeviceHAL->GetCameraHALInterface().SetViewport(stream, GetCameraAVStreamMgmtServer()->GetViewport()); + mCameraDeviceHAL->GetCameraHALInterface().SetViewport(stream, GetCameraAVStreamManagementCluster()->GetViewport()); } // Inform DPTZ (the server) that the camera default viewport has changed mCameraDeviceHAL->GetCameraAVSettingsUserLevelMgmtDelegate().DefaultViewportUpdated( - GetCameraAVStreamMgmtServer()->GetViewport()); + GetCameraAVStreamManagementCluster()->GetViewport()); break; } case SpeakerMuted::Id: { - mCameraDeviceHAL->GetCameraHALInterface().SetSpeakerMuted(GetCameraAVStreamMgmtServer()->GetSpeakerMuted()); + mCameraDeviceHAL->GetCameraHALInterface().SetSpeakerMuted(GetCameraAVStreamManagementCluster()->GetSpeakerMuted()); break; } case SpeakerVolumeLevel::Id: { - mCameraDeviceHAL->GetCameraHALInterface().SetSpeakerVolume(GetCameraAVStreamMgmtServer()->GetSpeakerVolumeLevel()); + mCameraDeviceHAL->GetCameraHALInterface().SetSpeakerVolume(GetCameraAVStreamManagementCluster()->GetSpeakerVolumeLevel()); break; } case MicrophoneMuted::Id: { - mCameraDeviceHAL->GetCameraHALInterface().SetMicrophoneMuted(GetCameraAVStreamMgmtServer()->GetMicrophoneMuted()); + mCameraDeviceHAL->GetCameraHALInterface().SetMicrophoneMuted(GetCameraAVStreamManagementCluster()->GetMicrophoneMuted()); break; } case MicrophoneVolumeLevel::Id: { - mCameraDeviceHAL->GetCameraHALInterface().SetMicrophoneVolume(GetCameraAVStreamMgmtServer()->GetMicrophoneVolumeLevel()); + mCameraDeviceHAL->GetCameraHALInterface().SetMicrophoneVolume( + GetCameraAVStreamManagementCluster()->GetMicrophoneVolumeLevel()); break; } case LocalVideoRecordingEnabled::Id: { mCameraDeviceHAL->GetCameraHALInterface().SetLocalVideoRecordingEnabled( - GetCameraAVStreamMgmtServer()->GetLocalVideoRecordingEnabled()); + GetCameraAVStreamManagementCluster()->GetLocalVideoRecordingEnabled()); break; } case LocalSnapshotRecordingEnabled::Id: { mCameraDeviceHAL->GetCameraHALInterface().SetLocalSnapshotRecordingEnabled( - GetCameraAVStreamMgmtServer()->GetLocalSnapshotRecordingEnabled()); + GetCameraAVStreamManagementCluster()->GetLocalSnapshotRecordingEnabled()); break; } case StatusLightEnabled::Id: { - mCameraDeviceHAL->GetCameraHALInterface().SetStatusLightEnabled(GetCameraAVStreamMgmtServer()->GetStatusLightEnabled()); + mCameraDeviceHAL->GetCameraHALInterface().SetStatusLightEnabled( + GetCameraAVStreamManagementCluster()->GetStatusLightEnabled()); break; } case ImageRotation::Id: { - mCameraDeviceHAL->GetCameraHALInterface().SetImageRotation(GetCameraAVStreamMgmtServer()->GetImageRotation()); + mCameraDeviceHAL->GetCameraHALInterface().SetImageRotation(GetCameraAVStreamManagementCluster()->GetImageRotation()); break; } case ImageFlipHorizontal::Id: { - mCameraDeviceHAL->GetCameraHALInterface().SetImageFlipHorizontal(GetCameraAVStreamMgmtServer()->GetImageFlipHorizontal()); + mCameraDeviceHAL->GetCameraHALInterface().SetImageFlipHorizontal( + GetCameraAVStreamManagementCluster()->GetImageFlipHorizontal()); break; } case ImageFlipVertical::Id: { - mCameraDeviceHAL->GetCameraHALInterface().SetImageFlipVertical(GetCameraAVStreamMgmtServer()->GetImageFlipVertical()); + mCameraDeviceHAL->GetCameraHALInterface().SetImageFlipVertical( + GetCameraAVStreamManagementCluster()->GetImageFlipVertical()); break; } default: @@ -714,7 +774,7 @@ Protocols::InteractionModel::Status CameraAVStreamManager::CaptureSnapshot(const CHIP_ERROR CameraAVStreamManager::AllocatedVideoStreamsLoaded() { - const std::vector & persistedStreams = GetCameraAVStreamMgmtServer()->GetAllocatedVideoStreams(); + const std::vector & persistedStreams = GetCameraAVStreamManagementCluster()->GetAllocatedVideoStreams(); auto & halStreams = mCameraDeviceHAL->GetCameraHALInterface().GetAvailableVideoStreams(); for (auto & halStream : halStreams) @@ -741,7 +801,7 @@ CameraAVStreamManager::AllocatedVideoStreamsLoaded() CHIP_ERROR CameraAVStreamManager::AllocatedAudioStreamsLoaded() { - const std::vector & persistedStreams = GetCameraAVStreamMgmtServer()->GetAllocatedAudioStreams(); + const std::vector & persistedStreams = GetCameraAVStreamManagementCluster()->GetAllocatedAudioStreams(); auto & halStreams = mCameraDeviceHAL->GetCameraHALInterface().GetAvailableAudioStreams(); for (auto & halStream : halStreams) @@ -773,7 +833,8 @@ CameraAVStreamManager::AllocatedAudioStreamsLoaded() CHIP_ERROR CameraAVStreamManager::AllocatedSnapshotStreamsLoaded() { - const std::vector & persistedStreams = GetCameraAVStreamMgmtServer()->GetAllocatedSnapshotStreams(); + const std::vector & persistedStreams = + GetCameraAVStreamManagementCluster()->GetAllocatedSnapshotStreams(); auto & halStreams = mCameraDeviceHAL->GetCameraHALInterface().GetAvailableSnapshotStreams(); std::set halStreamIds; @@ -817,7 +878,7 @@ CameraAVStreamManager::AllocatedSnapshotStreamsLoaded() persistedStream.snapshotStreamID); // Convert SnapshotStreamStruct to SnapshotStreamAllocateArgs - CameraAVStreamMgmtDelegate::SnapshotStreamAllocateArgs snapshotStreamArgs; + CameraAVStreamManagementDelegate::SnapshotStreamAllocateArgs snapshotStreamArgs; snapshotStreamArgs.imageCodec = persistedStream.imageCodec; snapshotStreamArgs.maxFrameRate = persistedStream.frameRate; @@ -879,98 +940,122 @@ CameraAVStreamManager::PersistentAttributesLoadedCallback() } CHIP_ERROR -CameraAVStreamManager::OnTransportAcquireAudioVideoStreams(uint16_t audioStreamID, uint16_t videoStreamID) +CameraAVStreamManager::OnTransportAcquireAudioVideoStreams(const std::vector & audioStreams, + const std::vector & videoStreams) { - // Update the available audio stream in the HAL - for (AudioStream & stream : mCameraDeviceHAL->GetCameraHALInterface().GetAvailableAudioStreams()) + // Update the available audio streams in the HAL + for (uint16_t audioStreamID : audioStreams) { - if (stream.audioStreamParams.audioStreamID == audioStreamID && stream.isAllocated) + for (AudioStream & stream : mCameraDeviceHAL->GetCameraHALInterface().GetAvailableAudioStreams()) { - if (stream.audioStreamParams.referenceCount < UINT8_MAX) - { - stream.audioStreamParams.referenceCount++; - } - else + if (stream.audioStreamParams.audioStreamID == audioStreamID && stream.isAllocated) { - ChipLogError(Camera, "Attempted to increment audio stream %u ref count beyond max limit", audioStreamID); + if (stream.audioStreamParams.referenceCount < UINT8_MAX) + { + stream.audioStreamParams.referenceCount++; + } + else + { + ChipLogError(Camera, "Attempted to increment audio stream %u ref count beyond max limit", audioStreamID); + } + break; } } + + // Update the counts in the SDK allocated stream attributes + if (GetCameraAVStreamManagementCluster()->UpdateAudioStreamRefCount(audioStreamID, /* shouldIncrement = */ true) != + CHIP_NO_ERROR) + { + ChipLogError(Camera, "Failed to increment audio stream %u ref count in SDK", audioStreamID); + } } - // Update the available video stream in the HAL - for (VideoStream & stream : mCameraDeviceHAL->GetCameraHALInterface().GetAvailableVideoStreams()) + // Update the available video streams in the HAL + for (uint16_t videoStreamID : videoStreams) { - if (stream.videoStreamParams.videoStreamID == videoStreamID && stream.isAllocated) + for (VideoStream & stream : mCameraDeviceHAL->GetCameraHALInterface().GetAvailableVideoStreams()) { - if (stream.videoStreamParams.referenceCount < UINT8_MAX) + if (stream.videoStreamParams.videoStreamID == videoStreamID && stream.isAllocated) { - stream.videoStreamParams.referenceCount++; - } - else - { - ChipLogError(Camera, "Attempted to increment video stream %u ref count beyond max limit", videoStreamID); + if (stream.videoStreamParams.referenceCount < UINT8_MAX) + { + stream.videoStreamParams.referenceCount++; + } + else + { + ChipLogError(Camera, "Attempted to increment video stream %u ref count beyond max limit", videoStreamID); + } + break; } } - } - - // Update the counts in the SDK allocated stream attributes - if (GetCameraAVStreamMgmtServer()->UpdateAudioStreamRefCount(audioStreamID, /* shouldIncrement = */ true) != CHIP_NO_ERROR) - { - ChipLogError(Camera, "Failed to increment audio stream %u ref count in SDK", audioStreamID); - } - if (GetCameraAVStreamMgmtServer()->UpdateVideoStreamRefCount(videoStreamID, /* shouldIncrement = */ true) != CHIP_NO_ERROR) - { - ChipLogError(Camera, "Failed to increment video stream %u ref count in SDK", videoStreamID); + // Update the counts in the SDK allocated stream attributes + if (GetCameraAVStreamManagementCluster()->UpdateVideoStreamRefCount(videoStreamID, /* shouldIncrement = */ true) != + CHIP_NO_ERROR) + { + ChipLogError(Camera, "Failed to increment video stream %u ref count in SDK", videoStreamID); + } } return CHIP_NO_ERROR; } CHIP_ERROR -CameraAVStreamManager::OnTransportReleaseAudioVideoStreams(uint16_t audioStreamID, uint16_t videoStreamID) +CameraAVStreamManager::OnTransportReleaseAudioVideoStreams(const std::vector & audioStreams, + const std::vector & videoStreams) { - // Update the available audio stream in the HAL - for (AudioStream & stream : mCameraDeviceHAL->GetCameraHALInterface().GetAvailableAudioStreams()) + // Update the available audio streams in the HAL + for (uint16_t audioStreamID : audioStreams) { - if (stream.audioStreamParams.audioStreamID == audioStreamID && stream.isAllocated) + for (AudioStream & stream : mCameraDeviceHAL->GetCameraHALInterface().GetAvailableAudioStreams()) { - if (stream.audioStreamParams.referenceCount > 0) + if (stream.audioStreamParams.audioStreamID == audioStreamID && stream.isAllocated) { - stream.audioStreamParams.referenceCount--; - } - else - { - ChipLogError(Camera, "Attempted to decrement audio stream %u ref count when it was already 0", audioStreamID); + if (stream.audioStreamParams.referenceCount > 0) + { + stream.audioStreamParams.referenceCount--; + } + else + { + ChipLogError(Camera, "Attempted to decrement audio stream %u ref count when it was already 0", audioStreamID); + } + break; } } + + // Update the counts in the SDK allocated stream attributes + if (GetCameraAVStreamManagementCluster()->UpdateAudioStreamRefCount(audioStreamID, /* shouldIncrement = */ false) != + CHIP_NO_ERROR) + { + ChipLogError(Camera, "Failed to decrement audio stream %u ref count in SDK", audioStreamID); + } } - // Update the available video stream in the HAL - for (VideoStream & stream : mCameraDeviceHAL->GetCameraHALInterface().GetAvailableVideoStreams()) + // Update the available video streams in the HAL + for (uint16_t videoStreamID : videoStreams) { - if (stream.videoStreamParams.videoStreamID == videoStreamID && stream.isAllocated) + for (VideoStream & stream : mCameraDeviceHAL->GetCameraHALInterface().GetAvailableVideoStreams()) { - if (stream.videoStreamParams.referenceCount > 0) + if (stream.videoStreamParams.videoStreamID == videoStreamID && stream.isAllocated) { - stream.videoStreamParams.referenceCount--; - } - else - { - ChipLogError(Camera, "Attempted to decrement video stream %u ref count when it was already 0", videoStreamID); + if (stream.videoStreamParams.referenceCount > 0) + { + stream.videoStreamParams.referenceCount--; + } + else + { + ChipLogError(Camera, "Attempted to decrement video stream %u ref count when it was already 0", videoStreamID); + } + break; } } - } - // Update the counts in the SDK allocated stream attributes - if (GetCameraAVStreamMgmtServer()->UpdateAudioStreamRefCount(audioStreamID, /* shouldIncrement = */ false) != CHIP_NO_ERROR) - { - ChipLogError(Camera, "Failed to decrement audio stream %u ref count in SDK", audioStreamID); - } - - if (GetCameraAVStreamMgmtServer()->UpdateVideoStreamRefCount(videoStreamID, /* shouldIncrement = */ false) != CHIP_NO_ERROR) - { - ChipLogError(Camera, "Failed to decrement video stream %u ref count in SDK", videoStreamID); + // Update the counts in the SDK allocated stream attributes + if (GetCameraAVStreamManagementCluster()->UpdateVideoStreamRefCount(videoStreamID, /* shouldIncrement = */ false) != + CHIP_NO_ERROR) + { + ChipLogError(Camera, "Failed to decrement video stream %u ref count in SDK", videoStreamID); + } } return CHIP_NO_ERROR; diff --git a/examples/camera-app/linux/src/clusters/chime/chime-manager.cpp b/examples/camera-app/linux/src/clusters/chime/chime-manager.cpp index 2766bc92977..5b2510bb080 100644 --- a/examples/camera-app/linux/src/clusters/chime/chime-manager.cpp +++ b/examples/camera-app/linux/src/clusters/chime/chime-manager.cpp @@ -49,7 +49,7 @@ CHIP_ERROR ChimeManager::GetChimeIDByIndex(uint8_t chimeIndex, uint8_t & chimeID return CHIP_NO_ERROR; } -Protocols::InteractionModel::Status ChimeManager::PlayChimeSound() +Protocols::InteractionModel::Status ChimeManager::PlayChimeSound(uint8_t chimeID) { // check if we are enabled if (!mChimeServer->GetEnabled()) @@ -57,10 +57,7 @@ Protocols::InteractionModel::Status ChimeManager::PlayChimeSound() return Protocols::InteractionModel::Status::Failure; } - // Get the Active Chime ID - auto selectedChime = mChimeServer->GetSelectedChime(); - // Play chime sound - ChipLogDetail(Camera, "Playing Chime with sound ID: %u", unsigned(selectedChime)); + ChipLogDetail(Camera, "Playing Chime with sound ID: %u", unsigned(chimeID)); return Protocols::InteractionModel::Status::Success; } diff --git a/examples/camera-app/linux/src/clusters/push-av-stream-transport/push-av-stream-manager.cpp b/examples/camera-app/linux/src/clusters/push-av-stream-transport/push-av-stream-manager.cpp index 38ca867f8b4..70fbe379db2 100644 --- a/examples/camera-app/linux/src/clusters/push-av-stream-transport/push-av-stream-manager.cpp +++ b/examples/camera-app/linux/src/clusters/push-av-stream-transport/push-av-stream-manager.cpp @@ -18,7 +18,6 @@ #include "push-av-stream-manager.h" -#include #include #include #include @@ -37,7 +36,6 @@ PushAvStreamTransportManager::~PushAvStreamTransportManager() { // Unregister all transports from Media Controller before deleting them. This will ensure that any ongoing streams are // stopped. - StopSessionMonitor(); if (mMediaController != nullptr) { for (auto & kv : mTransportMap) @@ -52,7 +50,6 @@ PushAvStreamTransportManager::~PushAvStreamTransportManager() void PushAvStreamTransportManager::Init() { ChipLogProgress(Zcl, "Push AV Stream Transport Initialized"); - StartSessionMonitor(); return; } @@ -80,14 +77,36 @@ PushAvStreamTransportManager::AllocatePushTransport(const TransportOptionsStruct ChipLogError(Camera, "CameraDeviceInterface not initialized for AllocatePushTransport"); return Status::Failure; } + + if (transportOptions.containerOptions.CMAFContainerOptions.HasValue()) + { + const auto cmafInterface = transportOptions.containerOptions.CMAFContainerOptions.Value().CMAFInterface; + + if (!IsCMAFInterfaceSupported(cmafInterface)) + { + ChipLogError(Camera, "PushAvStreamTransportManager, Unsupported CMAF interface type: %u", + static_cast(cmafInterface)); + return Status::Failure; + } + + ChipLogDetail(Camera, "PushAvStreamTransportManager, CMAF interface selected: %u", static_cast(cmafInterface)); + } + mTransportOptionsMap[connectionID] = transportOptions; ChipLogProgress(Camera, "PushAvStreamTransportManager, Create PushAV Transport for Connection: [%u]", connectionID); - mTransportMap[connectionID] = - std::make_unique(transportOptions, connectionID, mAudioStreamParams, mVideoStreamParams); + auto transport = std::make_unique(transportOptions, connectionID, mAudioStreamParams, mVideoStreamParams); + + CHIP_ERROR err = transport->ConfigureRecorderSettings(transportOptions, mAudioStreamParams, mVideoStreamParams); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Camera, "PushAvStreamTransportManager, failed to configure recorder settings for Connection: [%u], error: %s", + connectionID, ErrorStr(err)); + return Status::Failure; + } + mTransportMap[connectionID] = std::move(transport); mTransportMap[connectionID]->SetPushAvStreamTransportServer(mPushAvStreamTransportServer); - mTransportMap[connectionID]->SetPushAvStreamTransportManager(this); mTransportMap[connectionID]->SetFabricIndex(accessingFabricIndex); if (mMediaController == nullptr) @@ -97,27 +116,24 @@ PushAvStreamTransportManager::AllocatePushTransport(const TransportOptionsStruct return Status::NotFound; } - /* - Initialize video, audio stream ids with default invalid value (UINT16_MAX = 65535) - This is necessary because the MediaController API expects these values to be set. - If any of video/audio stream id is absent in the transport options,UINT16_MAX max is used as default value. - */ - uint16_t videoStreamID = -1; - uint16_t audioStreamID = -1; + std::vector videoStreams; + std::vector audioStreams; if (transportOptions.videoStreamID.HasValue() && !transportOptions.videoStreamID.Value().IsNull()) { - videoStreamID = transportOptions.videoStreamID.Value().Value(); + videoStreams.push_back(transportOptions.videoStreamID.Value().Value()); } if (transportOptions.audioStreamID.HasValue() && !transportOptions.audioStreamID.Value().IsNull()) { - audioStreamID = transportOptions.audioStreamID.Value().Value(); + audioStreams.push_back(transportOptions.audioStreamID.Value().Value()); } - ChipLogProgress( - Camera, "PushAvStreamTransportManager, RegisterTransport for connectionID: [%u], videoStreamID: [%u], audioStreamID: [%u]", - connectionID, videoStreamID, audioStreamID); - mMediaController->RegisterTransport(mTransportMap[connectionID].get(), videoStreamID, audioStreamID); + + ChipLogProgress(Camera, + "PushAvStreamTransportManager, RegisterTransport for connectionID: [%u], videoStreams count: [%u], " + "audioStreams count: [%u]", + connectionID, static_cast(videoStreams.size()), static_cast(audioStreams.size())); + mMediaController->RegisterTransport(mTransportMap[connectionID].get(), videoStreams, audioStreams); mMediaController->SetPreRollLength(mTransportMap[connectionID].get(), mTransportMap[connectionID].get()->GetPreRollLength()); uint32_t newTransportBandwidthbps = 0; @@ -191,6 +207,14 @@ PushAvStreamTransportManager::ModifyPushTransport(const uint16_t connectionID, c return Status::NotFound; } + CHIP_ERROR err = mTransportMap[connectionID].get()->ModifyPushTransport(transportOptions); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Camera, "PushAvStreamTransportManager, failed to modify Connection :[%u], error: %s", connectionID, + ErrorStr(err)); + return Status::Failure; + } + uint32_t newTransportBandwidthbps = 0; GetBandwidthForStreams(transportOptions.videoStreamID, transportOptions.audioStreamID, newTransportBandwidthbps); @@ -205,7 +229,7 @@ PushAvStreamTransportManager::ModifyPushTransport(const uint16_t connectionID, c connectionID, newTransportBandwidthbps, mTotalUsedBandwidthbps); mTransportOptionsMap[connectionID] = transportOptions; - mTransportMap[connectionID].get()->ModifyPushTransport(transportOptions); + ChipLogProgress(Camera, "PushAvStreamTransportManager, success to modify Connection :[%u]", connectionID); return Status::Success; @@ -286,6 +310,27 @@ Protocols::InteractionModel::Status PushAvStreamTransportManager::ManuallyTrigge return Status::Success; } +bool PushAvStreamTransportManager::IsCMAFInterfaceSupported(CMAFInterfaceEnum cmafInterface) const +{ + // CMAF interface 1 and DASH (interface 2) are supported in the current implementation + switch (cmafInterface) + { + case CMAFInterfaceEnum::kInterface1: + return true; + case CMAFInterfaceEnum::kInterface2DASH: + ChipLogDetail(Camera, + "DASH interface enabled - WARNING: This is still provisional and full compliance to CMAF ingest " + "interface-2: DASH may not be available"); + return true; + case CMAFInterfaceEnum::kInterface2HLS: + return false; + case CMAFInterfaceEnum::kUnknownEnumValue: + return false; + default: + return false; + } +} + void PushAvStreamTransportManager::GetBandwidthForStreams(const Optional> & videoStreamId, const Optional> & audioStreamId, uint32_t & outBandwidthbps) @@ -386,6 +431,44 @@ bool PushAvStreamTransportManager::ValidateSegmentDuration(uint16_t segmentDurat return false; } +bool PushAvStreamTransportManager::ValidateMaxPreRollLength(uint16_t maxPreRollLength, + const DataModel::Nullable & videoStreamId) +{ + // If the video stream ID is null, log error and return false + if (videoStreamId.IsNull()) + { + ChipLogError(Camera, "MaxPreRollLength validation requested with null video stream ID"); + return false; + } + + auto & videoStreams = mCameraDevice->GetCameraAVStreamMgmtDelegate().GetAllocatedVideoStreams(); + + if (videoStreams.empty()) + { + ChipLogError(Camera, "Attempt to validate max pre-roll length when no video streams are allocated."); + return false; + } + + for (const VideoStreamStruct & stream : videoStreams) + { + if (stream.videoStreamID == videoStreamId.Value()) + { + // If non-zero, Max pre roll length must be greater than or equal to key frame interval + if (maxPreRollLength >= stream.keyFrameInterval) + { + return true; + } + ChipLogError(Camera, + "Max pre-roll length validation failed for video stream id [%u], max pre-roll length [%u], key frame " + "interval [%u] ", + stream.videoStreamID, maxPreRollLength, stream.keyFrameInterval); + break; + } + } + + return false; +} + Protocols::InteractionModel::Status PushAvStreamTransportManager::SelectVideoStream(StreamUsageEnum streamUsage, uint16_t & videoStreamId) { @@ -703,82 +786,17 @@ CHIP_ERROR PushAvStreamTransportManager::IsAnyPrivacyModeActive(bool & isActive) return CHIP_NO_ERROR; } -uint64_t PushAvStreamTransportManager::OnTriggerActivated(uint8_t fabricIdx, uint8_t sessionGroup, uint16_t connectionID) +bool PushAvStreamTransportManager::GetCMAFSessionNumber(const uint16_t connectionID, uint64_t & sessionNumber) { - std::lock_guard lock(mSessionMapMutex); - auto sessionKey = CreateSessionKey(fabricIdx, sessionGroup); - if (mSessionMap.find(sessionKey) == mSessionMap.end()) - { - mSessionMap[sessionKey] = SessionInfo(); - } - auto & sessionInfo = mSessionMap[sessionKey]; - auto now = std::chrono::system_clock::now(); - if (sessionInfo.activeConnectionIDs.size() == 0) + sessionNumber = 0; + // find the transport for the given connection id and return its session number + auto transportIt = mTransportMap.find(connectionID); + if (transportIt == mTransportMap.end()) { - // This case is a new trigger activation. - sessionInfo.sessionNumber++; - sessionInfo.sessionStartedTimestamp = now; - } - sessionInfo.activeConnectionIDs.insert(connectionID); - return sessionInfo.sessionNumber; -} - -void PushAvStreamTransportManager::OnTriggerDeactivated(uint8_t fabricIdx, uint8_t sessionGroup, uint16_t connectionID) -{ - std::lock_guard lock(mSessionMapMutex); - auto sessionKey = CreateSessionKey(fabricIdx, sessionGroup); - auto & sessionInfo = mSessionMap[sessionKey]; - sessionInfo.activeConnectionIDs.erase(connectionID); -} - -void PushAvStreamTransportManager::StartSessionMonitor() -{ - mStopMonitoring = false; - mSessionMonitorThread = std::thread(&PushAvStreamTransportManager::SessionMonitor, this); -} - -void PushAvStreamTransportManager::StopSessionMonitor() -{ - mStopMonitoring = true; - if (mSessionMonitorThread.joinable()) - { - mSessionMonitorThread.join(); + ChipLogError(Camera, "PushAvStreamTransportManager, failed to find Connection :[%u]", connectionID); + return false; } -} -void PushAvStreamTransportManager::SessionMonitor() -{ - while (!mStopMonitoring) - { - std::vector> sessionsToRestart; - { - std::lock_guard lock(mSessionMapMutex); - for (auto & session : mSessionMap) - { - auto & sessionInfo = session.second; - auto now = std::chrono::system_clock::now(); - auto elapsed = std::chrono::duration_cast(now - sessionInfo.sessionStartedTimestamp).count(); - if (!sessionInfo.activeConnectionIDs.empty() && elapsed >= kMaxSessionDuration) - { - sessionInfo.sessionNumber++; - sessionInfo.sessionStartedTimestamp = now; - for (auto connectionID : sessionInfo.activeConnectionIDs) - { - sessionsToRestart.push_back({ connectionID, sessionInfo.sessionNumber }); - } - } - } - } - - for (auto & [connectionID, newSessionNumber] : sessionsToRestart) - { - auto it = mTransportMap.find(connectionID); - if (it != mTransportMap.end()) - { - it->second->StartNewSession(newSessionNumber); - } - } - - std::this_thread::sleep_for(std::chrono::seconds(kSessionMonitorInterval)); - } + sessionNumber = transportIt->second->GetSessionNumber(); + return true; } diff --git a/examples/camera-app/linux/src/clusters/webrtc-provider/webrtc-provider-manager.cpp b/examples/camera-app/linux/src/clusters/webrtc-provider/webrtc-provider-manager.cpp index c813c53a42e..39d9939220a 100644 --- a/examples/camera-app/linux/src/clusters/webrtc-provider/webrtc-provider-manager.cpp +++ b/examples/camera-app/linux/src/clusters/webrtc-provider/webrtc-provider-manager.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -36,6 +37,106 @@ namespace { // Constants constexpr uint16_t kMaxConcurrentWebRTCSessions = 5; +constexpr uint32_t kConnectionTimeoutSeconds = 30; + +/** + * @brief Validates that an SDP contains the minimum required fields for WebRTC. + * + * This function checks that the SDP has the mandatory session-level fields per RFC 8866 + * plus the necessary ICE and DTLS parameters required by the underlying WebRTC library. + * Without these fields, the library would throw an exception when trying to set the + * remote description. + * + * Required fields (per RFC 8866): + * - Version (v=) + * - Origin (o=) + * - Session name (s=) + * - Connection (c=) + * - Timing (t=) + * - At least one media line (m=) + * + * Required fields (WebRTC-specific): + * - ICE user fragment (a=ice-ufrag:) + * - ICE password (a=ice-pwd:) + * - DTLS fingerprint (a=fingerprint:) + * + * @param sdp The SDP string to validate + * @return true if the SDP contains all required fields, false otherwise + */ +bool ValidateSdpFields(const std::string & sdp) +{ + if (sdp.empty()) + { + ChipLogError(Camera, "ValidateSdpFields: SDP is empty"); + return false; + } + + struct SdpRequirement + { + const char * substring; + const char * description; + }; + + // Define the list of required substrings and their corresponding descriptions for error logging. + // These include mandatory SDP session-level fields per RFC 8866 plus WebRTC-specific requirements. + static const SdpRequirement kRequirements[] = { + { "v=", "version" }, + { "o=", "origin" }, + { "s=", "session name" }, + { "c=", "connection" }, + { "t=", "timing" }, + { "m=", "media line" }, + { "a=ice-ufrag:", "ICE user fragment" }, + { "a=ice-pwd:", "ICE password" }, + { "a=fingerprint:", "DTLS fingerprint" }, + }; + + for (const auto & req : kRequirements) + { + if (sdp.find(req.substring) == std::string::npos) + { + ChipLogError(Camera, "ValidateSdpFields: SDP has no %s (%s): %s", req.description, req.substring, sdp.c_str()); + return false; + } + } + + return true; +} + +/** + * @brief Converts Matter ICE server structures to the internal ICEServerInfo format. + * + * @param matterIceServers The Matter protocol ICE server list + * @param[out] iceServers The converted ICE server info list + * @return CHIP_ERROR CHIP_NO_ERROR on success, or an error from iterator parsing + */ +template +CHIP_ERROR ConvertICEServers(const T & matterIceServers, std::vector & iceServers) +{ + for (const auto & server : matterIceServers) + { + ICEServerInfo info; + auto urlsIter = server.URLs.begin(); + while (urlsIter.Next()) + { + info.urls.emplace_back(urlsIter.GetValue().data(), urlsIter.GetValue().size()); + } + ReturnErrorOnFailure(urlsIter.GetStatus()); + if (server.username.HasValue()) + { + info.username = std::string(server.username.Value().data(), server.username.Value().size()); + } + if (server.credential.HasValue()) + { + info.credential = std::string(server.credential.Value().data(), server.credential.Value().size()); + } + if (!info.urls.empty()) + { + iceServers.push_back(std::move(info)); + } + } + return CHIP_NO_ERROR; +} } // namespace @@ -61,9 +162,9 @@ void WebRTCProviderManager::SetMediaController(MediaController * mediaController mMediaController = mediaController; } -void WebRTCProviderManager::SetWebRTCTransportProvider(std::unique_ptr aWebRTCTransportProvider) +void WebRTCProviderManager::SetWebRTCTransportProvider(WebRTCTransportProviderCluster * webRTCTransportProvider) { - mWebRTCTransportProvider = std::move(aWebRTCTransportProvider); + mWebRTCTransportProvider = webRTCTransportProvider; } CHIP_ERROR WebRTCProviderManager::HandleSolicitOffer(const OfferRequestArgs & args, WebRTCSessionStruct & outSession, @@ -75,37 +176,35 @@ CHIP_ERROR WebRTCProviderManager::HandleSolicitOffer(const OfferRequestArgs & ar outSession.peerEndpointID = args.originatingEndpointId; outSession.streamUsage = args.streamUsage; outSession.fabricIndex = args.fabricIndex; - uint16_t videoStreamID = 0; - uint16_t audioStreamID = 0; - // Resolve or allocate a VIDEO stream - if (args.videoStreamId.HasValue()) + // Extract video and audio streams from args + std::vector videoStreams; + std::vector audioStreams; + + if (args.videoStreams.HasValue()) { - // Stream has been validated and potentially selected by ValidateStreamUsage() - // in the cluster server before invoking this delegate method - const auto & videoStreamIdNullable = args.videoStreamId.Value(); - outSession.videoStreamID = videoStreamIdNullable; - if (!videoStreamIdNullable.IsNull()) - { - videoStreamID = videoStreamIdNullable.Value(); - } + videoStreams = args.videoStreams.Value(); + } + + if (args.audioStreams.HasValue()) + { + audioStreams = args.audioStreams.Value(); + } + + // Set deprecated single-stream fields for backward compatibility + // Use the first stream from the arrays if available + if (!videoStreams.empty()) + { + outSession.videoStreamID.SetNonNull(videoStreams[0]); } else { outSession.videoStreamID.SetNull(); } - // Resolve or allocate an AUDIO stream - if (args.audioStreamId.HasValue()) + if (!audioStreams.empty()) { - // Stream has been validated and potentially selected by ValidateStreamUsage() - // in the cluster server before invoking this delegate method - const auto & audioStreamIdNullable = args.audioStreamId.Value(); - outSession.audioStreamID = audioStreamIdNullable; - if (!audioStreamIdNullable.IsNull()) - { - audioStreamID = audioStreamIdNullable.Value(); - } + outSession.audioStreamID.SetNonNull(audioStreams[0]); } else { @@ -120,8 +219,8 @@ CHIP_ERROR WebRTCProviderManager::HandleSolicitOffer(const OfferRequestArgs & ar requestArgs.fabricIndex = args.fabricIndex; requestArgs.peerNodeId = args.peerNodeId; requestArgs.originatingEndpointId = args.originatingEndpointId; - requestArgs.videoStreamId = videoStreamID; - requestArgs.audioStreamId = audioStreamID; + requestArgs.videoStreams = videoStreams; + requestArgs.audioStreams = audioStreams; requestArgs.peerId = ScopedNodeId(args.peerNodeId, args.fabricIndex); if (transport == nullptr) @@ -145,6 +244,17 @@ CHIP_ERROR WebRTCProviderManager::HandleSolicitOffer(const OfferRequestArgs & ar ChipLogProgress(Camera, "SFrame encryption enabled for session %u", args.sessionId); } + if (args.iceServers.HasValue()) + { + std::vector iceServers; + ReturnErrorOnFailure(ConvertICEServers(args.iceServers.Value(), iceServers)); + transport->SetICEServers(iceServers); + } + else + { + ChipLogProgress(Camera, "No ICE servers provided; ICE negotiation will be limited to host candidates"); + } + // Check resource availability before proceeding // If we cannot allocate resources, send End command with OutOfResources reason if (mWebrtcTransportMap.size() > kMaxConcurrentWebRTCSessions) @@ -167,10 +277,13 @@ CHIP_ERROR WebRTCProviderManager::HandleSolicitOffer(const OfferRequestArgs & ar // Acquire the Video and Audio Streams from the CameraAVStreamManagement // cluster and update the reference counts. - AcquireAudioVideoStreams(args.sessionId); + TEMPORARY_RETURN_IGNORED AcquireAudioVideoStreams(args.sessionId); transport->MoveToState(WebrtcTransport::State::SendingOffer); + // Start a connection timeout timer to clean up stale sessions that never reach Connected state + StartConnectionTimer(args.sessionId); + ChipLogProgress(Camera, "Generate and set the SDP"); if (transport->GetPeerConnection()) transport->GetPeerConnection()->CreateOffer(); @@ -195,7 +308,9 @@ void WebRTCProviderManager::RegisterWebrtcTransport(uint16_t sessionId) } WebrtcTransport::RequestArgs args = transport->GetRequestArgs(); - mMediaController->RegisterTransport(transport, args.videoStreamId, args.audioStreamId); + + // Register all video and audio streams for this transport + mMediaController->RegisterTransport(transport, args.videoStreams, args.audioStreams); } void WebRTCProviderManager::UnregisterWebrtcTransport(uint16_t sessionId) @@ -262,43 +377,46 @@ CHIP_ERROR WebRTCProviderManager::HandleProvideOffer(const ProvideOfferRequestAr { ChipLogProgress(Camera, "HandleProvideOffer called"); + if (!ValidateSdpFields(args.sdp)) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + // Initialize a new WebRTC session from the ProvideOfferRequestArgs outSession.id = args.sessionId; outSession.peerNodeID = args.peerNodeId; outSession.peerEndpointID = args.originatingEndpointId; outSession.streamUsage = args.streamUsage; outSession.fabricIndex = args.fabricIndex; - uint16_t videoStreamID = 0; - uint16_t audioStreamID = 0; - // Resolve or allocate a VIDEO stream - if (args.videoStreamId.HasValue()) + // Extract video and audio streams from args + std::vector videoStreams; + std::vector audioStreams; + + if (args.videoStreams.HasValue()) { - // Stream has been validated and potentially selected by ValidateStreamUsage() - // in the cluster server before invoking this delegate method - const auto & videoStreamIdNullable = args.videoStreamId.Value(); - outSession.videoStreamID = videoStreamIdNullable; - if (!videoStreamIdNullable.IsNull()) - { - videoStreamID = videoStreamIdNullable.Value(); - } + videoStreams = args.videoStreams.Value(); + } + + if (args.audioStreams.HasValue()) + { + audioStreams = args.audioStreams.Value(); + } + + // Set deprecated single-stream fields for backward compatibility + // Use the first stream from the arrays if available + if (!videoStreams.empty()) + { + outSession.videoStreamID.SetNonNull(videoStreams[0]); } else { outSession.videoStreamID.SetNull(); } - // Resolve or allocate an AUDIO stream - if (args.audioStreamId.HasValue()) + if (!audioStreams.empty()) { - // Stream has been validated and potentially selected by ValidateStreamUsage() - // in the cluster server before invoking this delegate method - const auto & audioStreamIdNullable = args.audioStreamId.Value(); - outSession.audioStreamID = audioStreamIdNullable; - if (!audioStreamIdNullable.IsNull()) - { - audioStreamID = audioStreamIdNullable.Value(); - } + outSession.audioStreamID.SetNonNull(audioStreams[0]); } else { @@ -311,8 +429,8 @@ CHIP_ERROR WebRTCProviderManager::HandleProvideOffer(const ProvideOfferRequestAr requestArgs.fabricIndex = args.fabricIndex; requestArgs.peerNodeId = args.peerNodeId; requestArgs.originatingEndpointId = args.originatingEndpointId; - requestArgs.videoStreamId = videoStreamID; - requestArgs.audioStreamId = audioStreamID; + requestArgs.videoStreams = videoStreams; + requestArgs.audioStreams = audioStreams; requestArgs.peerId = ScopedNodeId(args.peerNodeId, args.fabricIndex); WebrtcTransport * transport = GetTransport(args.sessionId); @@ -346,6 +464,17 @@ CHIP_ERROR WebRTCProviderManager::HandleProvideOffer(const ProvideOfferRequestAr ChipLogProgress(Camera, "SFrame encryption enabled for session %u", args.sessionId); } + if (args.iceServers.HasValue()) + { + std::vector iceServers; + ReturnErrorOnFailure(ConvertICEServers(args.iceServers.Value(), iceServers)); + transport->SetICEServers(iceServers); + } + else + { + ChipLogProgress(Camera, "No ICE servers provided; ICE negotiation will be limited to host candidates"); + } + transport->Start(); auto peerConnection = transport->GetPeerConnection(); std::string audioMid = ExtractMidFromSdp(args.sdp, "audio"); @@ -361,10 +490,13 @@ CHIP_ERROR WebRTCProviderManager::HandleProvideOffer(const ProvideOfferRequestAr // Acquire the Video and Audio Streams from the CameraAVStreamManagement // cluster and update the reference counts. - AcquireAudioVideoStreams(args.sessionId); + TEMPORARY_RETURN_IGNORED AcquireAudioVideoStreams(args.sessionId); transport->MoveToState(WebrtcTransport::State::SendingAnswer); + // Start a connection timeout timer to clean up stale sessions that never reach Connected state + StartConnectionTimer(args.sessionId); + if (peerConnection != nullptr) { transport->GetPeerConnection()->SetRemoteDescription(args.sdp, SDPType::Offer); @@ -386,9 +518,8 @@ CHIP_ERROR WebRTCProviderManager::HandleProvideAnswer(uint16_t sessionId, const return CHIP_ERROR_INVALID_ARGUMENT; } - if (sdpAnswer.empty()) + if (!ValidateSdpFields(sdpAnswer)) { - ChipLogError(Camera, "Provided SDP Answer is empty for session ID %u", sessionId); return CHIP_ERROR_INVALID_ARGUMENT; } @@ -455,9 +586,7 @@ CHIP_ERROR WebRTCProviderManager::HandleProvideICECandidates(uint16_t sessionId, return CHIP_NO_ERROR; } -CHIP_ERROR WebRTCProviderManager::HandleEndSession(uint16_t sessionId, WebRTCEndReasonEnum reasonCode, - DataModel::Nullable videoStreamID, - DataModel::Nullable audioStreamID) +CHIP_ERROR WebRTCProviderManager::HandleEndSession(uint16_t sessionId, WebRTCEndReasonEnum reasonCode) { WebrtcTransport * transport = GetTransport(sessionId); if (transport == nullptr) @@ -465,32 +594,16 @@ CHIP_ERROR WebRTCProviderManager::HandleEndSession(uint16_t sessionId, WebRTCEnd ChipLogError(Camera, "Session ID %u does not match the current sessions", sessionId); return CHIP_ERROR_INVALID_ARGUMENT; } - if (transport != nullptr) - { - ChipLogProgress(Camera, "Delete Webrtc Transport for the session: %u", sessionId); - - // Release the Video and Audio Streams from the CameraAVStreamManagement - // cluster and update the reference counts. - // TODO: Lookup the sessionID to get the Video/Audio StreamID - ReleaseAudioVideoStreams(sessionId); - - UnregisterWebrtcTransport(sessionId); - mWebrtcTransportMap.erase(sessionId); - WebrtcTransport::RequestArgs args = transport->GetRequestArgs(); - mSessionIdMap.erase(ScopedNodeId(args.peerNodeId, args.fabricIndex)); - } - if (transport->ClosePeerConnection()) - { - ChipLogProgress(Camera, "Closing peer connection: %u", sessionId); - } + ChipLogProgress(Camera, "EndSession for session: %u, reason: %u", sessionId, static_cast(reasonCode)); + CleanupSession(sessionId); return CHIP_NO_ERROR; } CHIP_ERROR -WebRTCProviderManager::ValidateStreamUsage(StreamUsageEnum streamUsage, Optional> & videoStreamId, - Optional> & audioStreamId) +WebRTCProviderManager::ValidateStreamUsage(StreamUsageEnum streamUsage, Optional> & videoStreams, + Optional> & audioStreams) { if (mCameraDevice == nullptr) { @@ -500,7 +613,10 @@ WebRTCProviderManager::ValidateStreamUsage(StreamUsageEnum streamUsage, Optional auto & avsmController = mCameraDevice->GetCameraAVStreamMgmtController(); - return avsmController.ValidateStreamUsage(streamUsage, videoStreamId, audioStreamId); + // The deprecated single-stream fields (videoStreamId/audioStreamId) have already been + // converted to the array format by the cluster implementation before calling this delegate. + // We only need to validate the array-based streams. + return avsmController.ValidateStreamUsage(streamUsage, videoStreams, audioStreams); } CHIP_ERROR WebRTCProviderManager::ValidateVideoStreamID(uint16_t videoStreamId) @@ -529,6 +645,32 @@ CHIP_ERROR WebRTCProviderManager::ValidateAudioStreamID(uint16_t audioStreamId) return avsmController.ValidateAudioStreamID(audioStreamId); } +CHIP_ERROR WebRTCProviderManager::ValidateVideoStreams(const std::vector & videoStreams) +{ + if (mCameraDevice == nullptr) + { + ChipLogError(Camera, "CameraDeviceInterface not initialized"); + return CHIP_ERROR_INCORRECT_STATE; + } + + auto & avsmController = mCameraDevice->GetCameraAVStreamMgmtController(); + + return avsmController.ValidateVideoStreams(videoStreams); +} + +CHIP_ERROR WebRTCProviderManager::ValidateAudioStreams(const std::vector & audioStreams) +{ + if (mCameraDevice == nullptr) + { + ChipLogError(Camera, "CameraDeviceInterface not initialized"); + return CHIP_ERROR_INCORRECT_STATE; + } + + auto & avsmController = mCameraDevice->GetCameraAVStreamMgmtController(); + + return avsmController.ValidateAudioStreams(audioStreams); +} + CHIP_ERROR WebRTCProviderManager::IsStreamUsageSupported(StreamUsageEnum streamUsage) { if (mCameraDevice == nullptr) @@ -669,7 +811,7 @@ void WebRTCProviderManager::ScheduleOfferSend(uint16_t sessionId) { ChipLogProgress(Camera, "ScheduleOfferSend called."); - DeviceLayer::SystemLayer().ScheduleLambda([this, sessionId]() { + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().ScheduleLambda([this, sessionId]() { WebrtcTransport * transport = GetTransport(sessionId); if (transport == nullptr) { @@ -695,7 +837,7 @@ void WebRTCProviderManager::ScheduleAnswerSend(uint16_t sessionId) { ChipLogProgress(Camera, "ScheduleAnswerSend called."); - DeviceLayer::SystemLayer().ScheduleLambda([this, sessionId]() { + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().ScheduleLambda([this, sessionId]() { WebrtcTransport * transport = GetTransport(sessionId); if (transport == nullptr) { @@ -722,7 +864,7 @@ void WebRTCProviderManager::ScheduleEndSend(uint16_t sessionId) { ChipLogProgress(Camera, "ScheduleEndSend called."); - DeviceLayer::SystemLayer().ScheduleLambda([this, sessionId]() { + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().ScheduleLambda([this, sessionId]() { WebrtcTransport * transport = GetTransport(sessionId); if (transport == nullptr) { @@ -749,7 +891,7 @@ void WebRTCProviderManager::ScheduleICECandidatesSend(uint16_t sessionId) { ChipLogProgress(Camera, "ScheduleICECandidatesSend called."); - DeviceLayer::SystemLayer().ScheduleLambda([this, sessionId]() { + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().ScheduleLambda([this, sessionId]() { WebrtcTransport * transport = GetTransport(sessionId); if (transport == nullptr) { @@ -826,18 +968,7 @@ void WebRTCProviderManager::OnDeviceConnected(void * context, Messaging::Exchang } err = self->SendEndCommand(exchangeMgr, sessionHandle, sessionId, endReason); - // Release the Video and Audio Streams from the CameraAVStreamManagement - // cluster and update the reference counts. - self->ReleaseAudioVideoStreams(sessionId); - self->UnregisterWebrtcTransport(sessionId); - WebrtcTransport::RequestArgs args = transport->GetRequestArgs(); - self->mSessionIdMap.erase(ScopedNodeId(args.peerNodeId, args.fabricIndex)); - - transport->MoveToState(WebrtcTransport::State::Idle); - - // remove from current sessions list - self->mWebRTCTransportProvider->RemoveSession(sessionId); - self->mWebrtcTransportMap.erase(sessionId); + self->CleanupSession(sessionId); break; } default: @@ -858,6 +989,37 @@ void WebRTCProviderManager::OnDeviceConnectionFailure(void * context, const Scop VerifyOrReturn(self != nullptr, ChipLogError(Camera, "OnDeviceConnectionFailure: context is null")); } +void WebRTCProviderManager::CleanupSession(uint16_t sessionId) +{ + WebrtcTransport * transport = GetTransport(sessionId); + if (transport == nullptr) + { + ChipLogProgress(Camera, "Transport not found for session %u; session may have already been cleaned up", sessionId); + return; + } + + // Release the Video and Audio Streams from the CameraAVStreamManagement + // cluster and update the reference counts. + TEMPORARY_RETURN_IGNORED ReleaseAudioVideoStreams(sessionId); + + // Capture args before cleanup in case the transport is invalidated + WebrtcTransport::RequestArgs args = transport->GetRequestArgs(); + + // Unregister the transport from the media controller + UnregisterWebrtcTransport(sessionId); + + // Close the peer connection + transport->ClosePeerConnection(); + + // Remove from session maps + mSessionIdMap.erase(ScopedNodeId(args.peerNodeId, args.fabricIndex)); + + // Finally, remove and destroy the transport + mWebrtcTransportMap.erase(sessionId); + + ChipLogProgress(Camera, "Session %u cleanup completed", sessionId); +} + WebrtcTransport * WebRTCProviderManager::GetTransport(uint16_t sessionId) { WebrtcTransport * transport = nullptr; @@ -967,6 +1129,11 @@ void WebRTCProviderManager::OnConnectionStateChanged(bool connected, const uint1 { ChipLogProgress(Camera, "Connection state changed for session %u: %s", sessionId, connected ? "connected" : "disconnected"); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().ScheduleLambda([this, sessionId]() { + // Cancel any pending connection timeout timer for this session + CancelConnectionTimer(sessionId); + }); + if (connected) { RegisterWebrtcTransport(sessionId); @@ -976,31 +1143,9 @@ void WebRTCProviderManager::OnConnectionStateChanged(bool connected, const uint1 // Schedule cleanup on Matter thread to ensure proper locking when calling RemoveSession. // Safe to capture 'this' by value: WebRTCProviderManager is a member of the global CameraDevice // object which has static storage duration and lives for the entire program lifetime. - DeviceLayer::SystemLayer().ScheduleLambda([this, sessionId]() { - WebrtcTransport * transport = GetTransport(sessionId); - if (transport == nullptr) - { - ChipLogProgress(Camera, - "Transport not found for session %u during disconnect; session may have already been cleaned up", - sessionId); - return; - } - - // Connection was closed/disconnected by the peer - clean up the session + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().ScheduleLambda([this, sessionId]() { ChipLogProgress(Camera, "Peer connection closed for session %u, cleaning up resources", sessionId); - - // Release the Video and Audio Streams from the CameraAVStreamManagement - // cluster and update the reference counts. - ReleaseAudioVideoStreams(sessionId); - - // Capture args before unregistering in case the transport is invalidated - WebrtcTransport::RequestArgs args = transport->GetRequestArgs(); - - // Unregister the transport from the media controller - UnregisterWebrtcTransport(sessionId); - - // Remove from session maps - mSessionIdMap.erase(ScopedNodeId(args.peerNodeId, args.fabricIndex)); + CleanupSession(sessionId); // Remove from current sessions list in the WebRTC Transport Provider // This MUST be called on the Matter thread with the stack lock held @@ -1008,11 +1153,6 @@ void WebRTCProviderManager::OnConnectionStateChanged(bool connected, const uint1 { mWebRTCTransportProvider->RemoveSession(sessionId); } - - // Finally, remove and destroy the transport - mWebrtcTransportMap.erase(sessionId); - - ChipLogProgress(Camera, "Session %u cleanup completed", sessionId); }); } } @@ -1169,8 +1309,9 @@ CHIP_ERROR WebRTCProviderManager::AcquireAudioVideoStreams(uint16_t sessionId) } WebrtcTransport::RequestArgs args = transport->GetRequestArgs(); - return mCameraDevice->GetCameraAVStreamMgmtDelegate().OnTransportAcquireAudioVideoStreams(args.audioStreamId, - args.videoStreamId); + + return mCameraDevice->GetCameraAVStreamMgmtController().OnTransportAcquireAudioVideoStreams(args.audioStreams, + args.videoStreams); } CHIP_ERROR WebRTCProviderManager::ReleaseAudioVideoStreams(uint16_t sessionId) @@ -1183,7 +1324,68 @@ CHIP_ERROR WebRTCProviderManager::ReleaseAudioVideoStreams(uint16_t sessionId) } WebrtcTransport::RequestArgs args = transport->GetRequestArgs(); - // TODO: Use passed in audio/video stream ids corresponding to a sessionId. - return mCameraDevice->GetCameraAVStreamMgmtDelegate().OnTransportReleaseAudioVideoStreams(args.audioStreamId, - args.videoStreamId); + + return mCameraDevice->GetCameraAVStreamMgmtController().OnTransportReleaseAudioVideoStreams(args.audioStreams, + args.videoStreams); +} + +void WebRTCProviderManager::StartConnectionTimer(uint16_t sessionId) +{ + // Cancel any existing timer for this session + CancelConnectionTimer(sessionId); + + auto * ctx = chip::Platform::New(); + ctx->manager = this; + ctx->sessionId = sessionId; + + CHIP_ERROR err = DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds32(kConnectionTimeoutSeconds), + OnConnectionTimeoutCallback, ctx); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Camera, "Failed to start connection timeout timer for session %u: %" CHIP_ERROR_FORMAT, sessionId, + err.Format()); + chip::Platform::Delete(ctx); + } + else + { + // Store the context for potential cancellation + mConnectionTimerContexts[sessionId] = ctx; + } +} + +void WebRTCProviderManager::CancelConnectionTimer(uint16_t sessionId) +{ + auto it = mConnectionTimerContexts.find(sessionId); + if (it != mConnectionTimerContexts.end()) + { + ConnectionTimeoutContext * ctx = it->second; + DeviceLayer::SystemLayer().CancelTimer(OnConnectionTimeoutCallback, ctx); + chip::Platform::Delete(ctx); + mConnectionTimerContexts.erase(it); + ChipLogProgress(Camera, "Cancelled connection timeout timer for session %u", sessionId); + } +} + +void WebRTCProviderManager::OnConnectionTimeoutCallback(chip::System::Layer * systemLayer, void * context) +{ + auto * ctx = static_cast(context); + + // Remove from the map before handling timeout (timer already fired) + ctx->manager->mConnectionTimerContexts.erase(ctx->sessionId); + ctx->manager->HandleConnectionTimeout(ctx->sessionId); + chip::Platform::Delete(ctx); +} + +void WebRTCProviderManager::HandleConnectionTimeout(uint16_t sessionId) +{ + WebrtcTransport * transport = GetTransport(sessionId); + if (transport == nullptr) + { + ChipLogProgress(Camera, "Session: %u was already cleaned up", sessionId); + return; + } + + ChipLogError(Camera, "Connection timeout for session %u after %u seconds, cleaning up stale session", sessionId, + kConnectionTimeoutSeconds); + CleanupSession(sessionId); } diff --git a/examples/camera-app/linux/src/clusters/zone-mgmt/zone-manager.cpp b/examples/camera-app/linux/src/clusters/zone-mgmt/zone-manager.cpp index 30aeb822446..a60598963c8 100644 --- a/examples/camera-app/linux/src/clusters/zone-mgmt/zone-manager.cpp +++ b/examples/camera-app/linux/src/clusters/zone-mgmt/zone-manager.cpp @@ -208,7 +208,8 @@ void ZoneManager::OnZoneTriggerTimeout(chip::System::Layer * systemLayer, void * if (!zoneManager->mTriggerContexts.empty()) { // Start the timer again if there are active triggers - DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(kTimerPeriod), OnZoneTriggerTimeout, zoneManager); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(kTimerPeriod), OnZoneTriggerTimeout, + zoneManager); } } @@ -241,7 +242,8 @@ void ZoneManager::OnZoneTriggeredEvent(uint16_t zoneId, mTriggerContexts.push_back(trigCtxt); // Schedule the periodic timer - DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(kTimerPeriod), OnZoneTriggerTimeout, this); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(kTimerPeriod), OnZoneTriggerTimeout, + this); } else { @@ -270,11 +272,6 @@ void ZoneManager::OnZoneTriggeredEvent(uint16_t zoneId, foundTrigCtxt->triggerCount); } } - - if (mCameraDevice) - { - mCameraDevice->HandlePushAvZoneTrigger(zoneId); - } } void ZoneManager::OnZoneStoppedEvent(uint16_t zoneId, chip::app::Clusters::ZoneManagement::ZoneEventStoppedReasonEnum stopReason) diff --git a/examples/camera-app/linux/src/media-controller/default-media-controller.cpp b/examples/camera-app/linux/src/media-controller/default-media-controller.cpp index 620a1f86816..c48f0cec4a2 100644 --- a/examples/camera-app/linux/src/media-controller/default-media-controller.cpp +++ b/examples/camera-app/linux/src/media-controller/default-media-controller.cpp @@ -38,12 +38,14 @@ void DefaultMediaController::SetCameraDevice(Camera::CameraDevice * device) } } -void DefaultMediaController::RegisterTransport(Transport * transport, uint16_t videoStreamID, uint16_t audioStreamID) +void DefaultMediaController::RegisterTransport(Transport * transport, const std::vector & videoStreams, + const std::vector & audioStreams) { - ChipLogProgress(Camera, "Registering transport: videoStreamID=%u, audioStreamID=%u", videoStreamID, audioStreamID); + ChipLogProgress(Camera, "Registering transport: videoStreams count=%u, audioStreams count=%u", + static_cast(videoStreams.size()), static_cast(audioStreams.size())); std::lock_guard lock(mConnectionsMutex); - mConnections.push_back({ transport, videoStreamID, audioStreamID }); + mConnections.push_back({ transport, videoStreams, audioStreams }); auto * bufferSink = new BufferSink(); bufferSink->transport = transport; @@ -65,8 +67,17 @@ void DefaultMediaController::RegisterTransport(Transport * transport, uint16_t v } std::unordered_set streamKeys; - streamKeys.insert("a" + std::to_string(audioStreamID)); - streamKeys.insert("v" + std::to_string(videoStreamID)); + for (uint16_t audioStream : audioStreams) + { + streamKeys.insert("a" + std::to_string(audioStream)); + ChipLogProgress(Camera, " Registered audioStream=%u", audioStream); + } + + for (uint16_t videoStream : videoStreams) + { + streamKeys.insert("v" + std::to_string(videoStream)); + ChipLogProgress(Camera, " Registered videoStream=%u", videoStream); + } mPreRollBuffer.RegisterTransportToBuffer(bufferSink, streamKeys); mSinkMap[transport] = bufferSink; @@ -89,16 +100,16 @@ void DefaultMediaController::UnregisterTransport(Transport * transport) } } -void DefaultMediaController::DistributeVideo(const uint8_t * data, size_t size, uint16_t videoStreamID) +void DefaultMediaController::DistributeVideo(const uint8_t * data, size_t size, uint16_t videoStreamID, int64_t timestamp) { std::string streamKey = "v" + std::to_string(videoStreamID); - mPreRollBuffer.PushFrameToBuffer(streamKey, data, size); + mPreRollBuffer.PushFrameToBuffer(streamKey, data, size, timestamp); } -void DefaultMediaController::DistributeAudio(const uint8_t * data, size_t size, uint16_t audioStreamID) +void DefaultMediaController::DistributeAudio(const uint8_t * data, size_t size, uint16_t audioStreamID, int64_t timestamp) { std::string streamKey = "a" + std::to_string(audioStreamID); - mPreRollBuffer.PushFrameToBuffer(streamKey, data, size); + mPreRollBuffer.PushFrameToBuffer(streamKey, data, size, timestamp); } void DefaultMediaController::SetPreRollLength(Transport * transport, uint16_t preRollBufferLength) @@ -121,9 +132,12 @@ Transport * DefaultMediaController::GetTransportForVideoStream(uint16_t videoStr std::lock_guard lock(mConnectionsMutex); for (const auto & conn : mConnections) { - if (conn.videoStreamID == videoStreamID) + for (uint16_t id : conn.videoStreams) { - return conn.transport; + if (id == videoStreamID) + { + return conn.transport; + } } } return nullptr; @@ -134,9 +148,12 @@ Transport * DefaultMediaController::GetTransportForAudioStream(uint16_t audioStr std::lock_guard lock(mConnectionsMutex); for (const auto & conn : mConnections) { - if (conn.audioStreamID == audioStreamID) + for (uint16_t id : conn.audioStreams) { - return conn.transport; + if (id == audioStreamID) + { + return conn.transport; + } } } return nullptr; diff --git a/examples/camera-app/linux/src/pushav-clip-recorder.cpp b/examples/camera-app/linux/src/pushav-clip-recorder.cpp index b359a456f84..82820576462 100644 --- a/examples/camera-app/linux/src/pushav-clip-recorder.cpp +++ b/examples/camera-app/linux/src/pushav-clip-recorder.cpp @@ -23,12 +23,12 @@ #include #include #include -#include #include #include constexpr int kSegmentIdOffset = 1000; constexpr int kMPDDefaultStartNumber = 1001; +constexpr int kInitialSegmentId = 1; extern "C" { #include @@ -54,42 +54,40 @@ PushAVClipRecorder::PushAVClipRecorder(ClipInfoStruct & aClipInfo, AudioInfoStru mClipInfo(aClipInfo), mAudioInfo(aAudioInfo), mVideoInfo(aVideoInfo), mUploader(aUploader) { - mFormatContext = nullptr; - mInputFormatContext = nullptr; - mVideoStream = nullptr; - mAudioStream = nullptr; - mAudioEncoderContext = nullptr; - mVideoInfo.mVideoPts = 0; - mVideoInfo.mVideoDts = 0; - mAudioInfo.mAudioPts = 0; - mAudioInfo.mAudioDts = 0; - int streamIndex = 0; - mMetadataSet = false; - mDeinitializeRecorder = false; - mUploadedInitSegment = false; - mUploadMPD = false; - mUploadSegmentID = 0001; - mCurrentClipStartPts = AV_NOPTS_VALUE; - mFoundFirstIFramePts = -1; - currentPts = AV_NOPTS_VALUE; - - mVideoInfo.mVideoStreamIndex = -1; - mAudioInfo.mAudioStreamIndex = -1; - - if (mClipInfo.mHasAudio && mClipInfo.mHasVideo) - { - ChipLogDetail(Camera, "Both audio and video streams are active. Only one stream at a time is supported currently."); - mClipInfo.mHasAudio = false; - } + mFormatContext = nullptr; + mInputFormatContext = nullptr; + mVideoStream = nullptr; + mAudioStream = nullptr; + mAudioEncoderContext = nullptr; + int streamIndex = 0; + mLastVideoPts = 0; + mLastAudioPts = 0; + mClipInfo.mClipStartPTS = 0; + mMetadataSet = false; + mDeinitializeRecorder = false; + mUploadMPD = true; + mCurrentClipStartPts = AV_NOPTS_VALUE; + currentPts = AV_NOPTS_VALUE; + + mVideoInfo.mVideoOutputStreamId = -1; + mAudioInfo.mAudioOutputStreamId = -1; + if (mClipInfo.mHasVideo) { - mVideoInfo.mVideoStreamIndex = streamIndex++; + mUploadSegmentID.push_back(kInitialSegmentId); + mUploadedInitSegment.push_back(false); + mStreamIdNameMap.push_back(mVideoInfo.mVideoStreamName); + mVideoInfo.mVideoOutputStreamId = streamIndex++; } if (mClipInfo.mHasAudio) { - mAudioInfo.mAudioStreamIndex = streamIndex++; + mUploadSegmentID.push_back(kInitialSegmentId); + mUploadedInitSegment.push_back(false); + mStreamIdNameMap.push_back(mAudioInfo.mAudioStreamName); + mAudioInfo.mAudioOutputStreamId = streamIndex++; } SetRecorderStatus(false); // Start off as not running + mUploader->setStreamIdNameMap(mStreamIdNameMap); ChipLogProgress(Camera, "PushAVClipRecorder initialized for Track name: %s, output path: %s", mClipInfo.mTrackName.c_str(), mClipInfo.mOutputPath.c_str()); } @@ -103,14 +101,22 @@ PushAVClipRecorder::~PushAVClipRecorder() { mWorkerThread.join(); } + + std::filesystem::path mpdPath = mUploadFileBasePath / "index.mpd"; + if (IsFileReadyForUpload(mpdPath)) + { + UpdateMPDParams(mpdPath); + ChipLogProgress(Camera, "Uploading final MPD: %s for track: %s, sessionID: %lu, connectionID: %u", mpdPath.c_str(), + mClipInfo.mTrackName.c_str(), mClipInfo.mSessionNumber, mConnectionID); + CheckAndUploadFile(mpdPath.string()); + } } bool PushAVClipRecorder::EnsureDirectoryExists(const std::string & path) { // Base output path std::filesystem::path basePath(path); - std::filesystem::path sessionDir = basePath / ("session_" + std::to_string(mClipInfo.mSessionNumber)); - std::filesystem::path trackDir = sessionDir / mClipInfo.mTrackName; + mUploadFileBasePath = basePath / ("session_" + std::to_string(mClipInfo.mSessionNumber)); // Helper lambda to ensure a directory exists and is writable, creating it with mode 0755 auto ensure = [&](const std::filesystem::path & p) -> bool { @@ -119,7 +125,8 @@ bool PushAVClipRecorder::EnsureDirectoryExists(const std::string & path) { if (!std::filesystem::create_directories(p, ec)) { - ChipLogError(Camera, "Failed to create directory: %s", p.c_str()); + ChipLogError(Camera, "Failed to create directory: %s, error code: %d (%s)", p.c_str(), ec.value(), + ec.message().c_str()); return false; } // Set permissions to file: (owner rwx, group rx) @@ -130,31 +137,34 @@ bool PushAVClipRecorder::EnsureDirectoryExists(const std::string & path) } else if (!std::filesystem::is_directory(p, ec)) { - ChipLogError(Camera, "Path is not a directory: %s", p.c_str()); + ChipLogError(Camera, "Path is not a directory: %s, error code: %d (%s)", p.c_str(), ec.value(), ec.message().c_str()); return false; } auto perms = std::filesystem::status(p, ec).permissions(); if ((perms & std::filesystem::perms::owner_write) == std::filesystem::perms::none) { - ChipLogError(Camera, "Directory is not writable: %s", p.c_str()); + ChipLogError(Camera, "Directory is not writable: %s (permissions: %o)", p.c_str(), static_cast(perms)); return false; } + return true; }; // Ensure base directory exists if (!ensure(basePath)) { + ChipLogError(Camera, "Failed to ensure base directory exists: %s", basePath.c_str()); return false; } // Clean up previous session directory if it exists - std::filesystem::remove_all(sessionDir); + std::filesystem::remove_all(mUploadFileBasePath); // Create session and track directories - if (!ensure(sessionDir) || !ensure(trackDir)) + if (!ensure(mUploadFileBasePath)) { + ChipLogError(Camera, "Failed to ensure session directory exists: %s", mUploadFileBasePath.c_str()); return false; } @@ -229,7 +239,7 @@ bool PushAVClipRecorder::IsH264IFrame(const uint8_t * data, unsigned int length) return ret; } -AVPacket * PushAVClipRecorder::CreatePacket(const uint8_t * data, int size, bool isVideo) +AVPacket * PushAVClipRecorder::CreatePacket(const uint8_t * data, int size, int64_t timestampMs, bool isVideo) { AVPacket * packet = av_packet_alloc(); if (!packet) @@ -237,7 +247,6 @@ AVPacket * PushAVClipRecorder::CreatePacket(const uint8_t * data, int size, bool ChipLogError(Camera, "ERROR: AVPacket allocation failed!"); return nullptr; } - packet->data = static_cast(av_malloc(static_cast(size))); if (!packet->data) { @@ -245,7 +254,6 @@ AVPacket * PushAVClipRecorder::CreatePacket(const uint8_t * data, int size, bool av_packet_free(&packet); return nullptr; } - memcpy(packet->data, data, static_cast(size)); packet->size = size; @@ -253,42 +261,75 @@ AVPacket * PushAVClipRecorder::CreatePacket(const uint8_t * data, int size, bool { if (IsH264IFrame(data, static_cast(size))) { - mFoundFirstIFramePts = mVideoInfo.mVideoPts; - packet->flags = AV_PKT_FLAG_KEY; - ChipLogProgress(Camera, "Found I-frame at PTS: %ld", mVideoInfo.mVideoPts); + if (mClipInfo.mClipStartPTS == 0) + mClipInfo.mClipStartPTS = timestampMs; + packet->flags = AV_PKT_FLAG_KEY; + + ChipLogProgress(Camera, "Found I-frame at timestamp: %ld ms", timestampMs); } - if (mClipInfo.mHasVideo && mFoundFirstIFramePts < 0) + if (mClipInfo.mHasVideo && mClipInfo.mClipStartPTS == 0) { ChipLogError(Camera, "ERROR: First frame is not an I-frame. Dropping packet."); av_packet_free(&packet); return nullptr; } - packet->pts = mVideoInfo.mVideoPts; - packet->dts = mVideoInfo.mVideoDts; - packet->stream_index = mVideoInfo.mVideoStreamIndex; - packet->duration = mVideoInfo.mVideoFrameDuration; - mVideoInfo.mVideoDts += mVideoInfo.mVideoFrameDuration; - mVideoInfo.mVideoPts += mVideoInfo.mVideoFrameDuration; + if (mVideoInfo.mVideoTimeBase.num != 0) + { + mLastVideoPts = timestampMs; + + // Normalize timestamp relative to clip start + int64_t normalizedTimestampMs = timestampMs - mClipInfo.mClipStartPTS; + packet->pts = av_rescale_q(normalizedTimestampMs, (AVRational){ 1, 1000 }, mVideoInfo.mVideoTimeBase); + packet->dts = packet->pts; + } + else + { + ChipLogError(Camera, "ERROR: Invalid video timebase (num=0)"); + av_packet_free(&packet); + return nullptr; + } + + packet->stream_index = mVideoInfo.mVideoOutputStreamId; } else { - if (mClipInfo.mHasVideo && mFoundFirstIFramePts < 0 && mFoundFirstIFramePts <= mAudioInfo.mAudioPts) + if (mClipInfo.mHasVideo && mClipInfo.mClipStartPTS == 0) { - ChipLogError(Camera, "ERROR: frames will be dropped till an Iframe is recived"); av_packet_free(&packet); return nullptr; } - packet->pts = mAudioInfo.mAudioPts; - packet->dts = mAudioInfo.mAudioDts; - packet->stream_index = mAudioInfo.mAudioStreamIndex; - packet->duration = mAudioInfo.mAudioFrameDuration; - mAudioInfo.mAudioDts += mAudioInfo.mAudioFrameDuration; - mAudioInfo.mAudioPts += mAudioInfo.mAudioFrameDuration; + + if (!mClipInfo.mHasVideo && mClipInfo.mClipStartPTS == 0) + { + mClipInfo.mClipStartPTS = timestampMs; + } + if (mAudioInfo.mAudioTimeBase.num != 0) + { + mLastAudioPts = timestampMs; + + // Normalize timestamp relative to clip start + int64_t normalizedTimestampMs = timestampMs - mClipInfo.mClipStartPTS; + packet->pts = av_rescale_q(normalizedTimestampMs, (AVRational){ 1, 1000 }, mAudioInfo.mAudioTimeBase); + packet->dts = packet->pts; + } + else + { + ChipLogError(Camera, "ERROR: Invalid audio timebase (num=0)"); + av_packet_free(&packet); + return nullptr; + } + + packet->stream_index = mAudioInfo.mAudioOutputStreamId; } - return (mClipInfo.mHasVideo && mFoundFirstIFramePts < 0) ? nullptr : packet; + if (packet->pts < 0) + { + return nullptr; + } + + return packet; } void PushAVClipRecorder::Start() @@ -302,7 +343,12 @@ void PushAVClipRecorder::Start() if (!EnsureDirectoryExists(mClipInfo.mOutputPath)) { ChipLogError(Camera, "ERROR: Invalid output directory"); - Stop(); + mDeinitializeRecorder = true; + } + + if (mWorkerThread.joinable()) + { + mWorkerThread.join(); } SetRecorderStatus(true); @@ -315,8 +361,6 @@ void PushAVClipRecorder::Stop() { if (GetRecorderStatus()) { - mPushAvStreamTransportManager->OnTriggerDeactivated(mFabricIndex, mClipInfo.mSessionGroup, mConnectionID); - // Call the cluster server's NotifyTransportStopped method asynchronously to prevent blocking if (mPushAvStreamTransportServer != nullptr) { @@ -362,7 +406,7 @@ void PushAVClipRecorder::Stop() mClipInfo.mTrackName.c_str()); } -void PushAVClipRecorder::PushPacket(const uint8_t * data, size_t size, bool isVideo) +void PushAVClipRecorder::PushPacket(const uint8_t * data, size_t size, int64_t timestampMs, bool isVideo) { if (!GetRecorderStatus()) { @@ -370,7 +414,7 @@ void PushAVClipRecorder::PushPacket(const uint8_t * data, size_t size, bool isVi return; } - AVPacket * packet = CreatePacket(data, static_cast(size), isVideo); + AVPacket * packet = CreatePacket(data, static_cast(size), timestampMs, isVideo); if (!packet) { ChipLogError(Camera, "ERROR: PACKET DROPPED!"); @@ -390,19 +434,19 @@ void PushAVClipRecorder::PushPacket(const uint8_t * data, size_t size, bool isVi mCondition.notify_one(); } -int PushAVClipRecorder::SetupOutput(const std::string & outputPrefix, const std::string & initSegPattern, - const std::string & mediaSegPattern) +RecorderStatus PushAVClipRecorder::SetupOutput(const std::string & outputPrefix, const std::string & initSegPattern, + const std::string & mediaSegPattern) { - const std::string mpdFilename = outputPrefix + ".mpd"; + const std::string mpdFilename = outputPrefix + "/index.mpd"; if (avformat_alloc_output_context2(&mFormatContext, nullptr, nullptr, mpdFilename.c_str()) < 0) { ChipLogError(Camera, "ERROR: Failed to allocate output context"); - Stop(); - return -1; + return RecorderStatus::kFail; } if (!mFormatContext) { ChipLogError(Camera, "ERROR: Output context is null"); + return RecorderStatus::kFail; } double segSeconds = static_cast(mClipInfo.mSegmentDurationMs) / 1000.0; // Set DASH/CMAF options @@ -427,15 +471,15 @@ int PushAVClipRecorder::SetupOutput(const std::string & outputPrefix, const std: av_dict_set_int(&options, "use_timeline", 1, 0); av_dict_set(&options, "strict", "experimental", 0); av_dict_set(&options, "start_number", std::to_string(kSegmentIdOffset).c_str(), 0); - if (mClipInfo.mHasVideo && (AddStreamToOutput(AVMEDIA_TYPE_VIDEO) < 0)) + if (mClipInfo.mHasVideo && (AddStreamToOutput(AVMEDIA_TYPE_VIDEO) == RecorderStatus::kFail)) { ChipLogError(Camera, "ERROR: adding video stream to output"); - return -1; + return RecorderStatus::kFail; } - if (mClipInfo.mHasAudio && (AddStreamToOutput(AVMEDIA_TYPE_AUDIO) < 0)) + if (mClipInfo.mHasAudio && (AddStreamToOutput(AVMEDIA_TYPE_AUDIO) == RecorderStatus::kFail)) { ChipLogError(Camera, "ERROR: adding video stream to output"); - return -1; + return RecorderStatus::kFail; } if (!(mFormatContext->oformat->flags & AVFMT_NOFILE)) @@ -443,28 +487,28 @@ int PushAVClipRecorder::SetupOutput(const std::string & outputPrefix, const std: if (avio_open(&mFormatContext->pb, mpdFilename.c_str(), AVIO_FLAG_WRITE) < 0) { ChipLogError(Camera, "ERROR: Failed to open output file: %s", mpdFilename.c_str()); - Stop(); - return -1; + return RecorderStatus::kFail; } } if (avformat_write_header(mFormatContext, &options) < 0) { ChipLogError(Camera, "Error: writing output header"); - Stop(); - return -1; + return RecorderStatus::kFail; } - return 0; + return RecorderStatus::kSuccess; } -int PushAVClipRecorder::StartClipRecording() +RecorderStatus PushAVClipRecorder::StartClipRecording() { if (!mClipInfo.mHasVideo && !mClipInfo.mHasAudio) { ChipLogError(Camera, "ERROR: No video or audio stream available. Not starting recording"); - return -1; + return RecorderStatus::kFail; } + RecorderStatus result = RecorderStatus::kSuccess; + while (GetRecorderStatus()) { std::unique_lock lock(mQueueMutex); @@ -476,14 +520,19 @@ int PushAVClipRecorder::StartClipRecording() mClipInfo.mSessionNumber, mClipInfo.mTrackName.c_str()); break; // Exit loop } - ProcessBuffersAndWrite(); + if (ProcessBuffersAndWrite() == RecorderStatus::kFail) + { + ChipLogError(Camera, "Error processing buffers and writing"); + result = RecorderStatus::kFail; + Stop(); + } } CleanupOutput(); ChipLogProgress(Camera, "Recorder thread closing"); - return 0; + return result; } -int PushAVClipRecorder::AddStreamToOutput(AVMediaType type) +RecorderStatus PushAVClipRecorder::AddStreamToOutput(AVMediaType type) { if (type == AVMEDIA_TYPE_VIDEO) { @@ -491,8 +540,7 @@ int PushAVClipRecorder::AddStreamToOutput(AVMediaType type) if (avcodec_parameters_copy(mVideoStream->codecpar, mInputFormatContext->streams[0]->codecpar) < 0) { ChipLogError(Camera, "ERROR: Failed to copy codec parameters for media type: %d", type); - Stop(); - return -1; + return RecorderStatus::kFail; } mVideoStream->codecpar->codec_tag = 0; mVideoStream->codecpar->width = mVideoInfo.mWidth; @@ -505,22 +553,19 @@ int PushAVClipRecorder::AddStreamToOutput(AVMediaType type) if (!mAudioStream) { ChipLogError(Camera, "ERROR: Failed to add audio stream"); - Stop(); - return -1; + return RecorderStatus::kFail; } const AVCodec * audioCodec = avcodec_find_encoder(mAudioInfo.mAudioCodecId); if (!audioCodec) { ChipLogError(Camera, "ERROR: Audio encoder not found"); - Stop(); - return -1; + return RecorderStatus::kFail; } mAudioEncoderContext = avcodec_alloc_context3(audioCodec); if (!mAudioEncoderContext) { ChipLogError(Camera, "Error: failed to allocate the encoder context"); - Stop(); - return -1; + return RecorderStatus::kFail; } mAudioEncoderContext->sample_rate = mAudioInfo.mSampleRate; @@ -543,28 +588,26 @@ int PushAVClipRecorder::AddStreamToOutput(AVMediaType type) if (avcodec_open2(mAudioEncoderContext, audioCodec, &opts) < 0) { ChipLogError(Camera, "Error: Cannot open audio encoder for audio stream"); - Stop(); - return -1; + return RecorderStatus::kFail; } if (avcodec_parameters_from_context(mAudioStream->codecpar, mAudioEncoderContext) < 0) { ChipLogError(Camera, "Error: Failed to copy encoder parameters to audio output stream"); - Stop(); - return -1; + return RecorderStatus::kFail; } if (mFormatContext->oformat->flags & AVFMT_GLOBALHEADER) { mAudioEncoderContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } } - return 0; + return RecorderStatus::kSuccess; } -int PushAVClipRecorder::ProcessBuffersAndWrite() +RecorderStatus PushAVClipRecorder::ProcessBuffersAndWrite() { if (mVideoQueue.empty() && mAudioQueue.empty()) { - return -1; + return RecorderStatus::kWarning; } bool useVideo = false; @@ -575,17 +618,16 @@ int PushAVClipRecorder::ProcessBuffersAndWrite() AVPacket * videoPkt = mVideoQueue.front(); AVPacket * audioPkt = mAudioQueue.front(); - if (videoPkt->pts != AV_NOPTS_VALUE && audioPkt->pts != AV_NOPTS_VALUE) + const bool videoHasValidPts = (videoPkt->pts != AV_NOPTS_VALUE); + const bool audioHasValidPts = (audioPkt->pts != AV_NOPTS_VALUE); + + if (videoHasValidPts && audioHasValidPts) { useVideo = (videoPkt->pts <= audioPkt->pts); } - else if (videoPkt->pts != AV_NOPTS_VALUE) - { - useVideo = true; - } - else if (audioPkt->pts != AV_NOPTS_VALUE) + else { - useVideo = false; + useVideo = videoHasValidPts; } pkt = useVideo ? videoPkt : audioPkt; } @@ -594,36 +636,19 @@ int PushAVClipRecorder::ProcessBuffersAndWrite() pkt = mVideoQueue.front(); useVideo = true; } - else if (!mAudioQueue.empty()) + else { pkt = mAudioQueue.front(); useVideo = false; } - else - { - return false; - } - if (!pkt) - { - ChipLogError(Camera, "Error: No valid packet to process"); - return -1; - } if (mMetadataSet == false) { - if (mClipInfo.mHasVideo && !useVideo) - { - return false; - } - - std::string initSegName = - mClipInfo.mTrackName + std::filesystem::path::preferred_separator + mClipInfo.mTrackName + ".init"; - std::string mediaSegName = mClipInfo.mTrackName + std::filesystem::path::preferred_separator + "segment_$Number%04d$.m4s"; - std::string mpdPrefix = "session_" + std::to_string(mClipInfo.mSessionNumber) + std::filesystem::path::preferred_separator + - mClipInfo.mTrackName; - - mInputFormatContext = avformat_alloc_context(); - int64_t avioCtxBufferSize = (static_cast(mVideoInfo.mBitRate) * mClipInfo.mSegmentDurationMs) / (8 * 1000); + std::string initSegName = "#__$RepresentationID$__#.init"; + std::string mediaSegName = "#__$RepresentationID$__#segment_$Number%04d$.m4s"; + mInputFormatContext = avformat_alloc_context(); + int64_t avioCtxBufferSize = + (static_cast(mVideoInfo.mBitRate + mAudioInfo.mBitRate) * mClipInfo.mSegmentDurationMs) / (8 * 1000); uint8_t * mAvioContextBuffer = static_cast(av_malloc(static_cast(avioCtxBufferSize))); struct BufferData data = { 0 }; data.mPtr = static_cast(pkt->data); @@ -637,15 +662,13 @@ int PushAVClipRecorder::ProcessBuffersAndWrite() if (avformat_open_input(&mInputFormatContext, "", nullptr, nullptr) < 0) { ChipLogError(Camera, "Error: Failed to open input format for video"); - Stop(); - return -1; + return RecorderStatus::kFail; } if (avformat_find_stream_info(mInputFormatContext, nullptr) < 0) { ChipLogError(Camera, "Error: Failed to find stream info for video"); - Stop(); - return -1; + return RecorderStatus::kFail; } } else if (mClipInfo.mHasAudio) @@ -655,27 +678,24 @@ int PushAVClipRecorder::ProcessBuffersAndWrite() ChipLogProgress(Camera, "Setting up audio-only stream, skipping input format initialization"); } - if (SetupOutput(mClipInfo.mOutputPath + mpdPrefix, initSegName, mediaSegName) < 0) + if (SetupOutput(mUploadFileBasePath, initSegName, mediaSegName) == RecorderStatus::kFail) { ChipLogError(Camera, "Error: setting up output"); - return -1; + return RecorderStatus::kFail; } if (!mFormatContext) { ChipLogError(Camera, "Error: Output context not initialized. Skipping packet"); - Stop(); - return -1; + return RecorderStatus::kFail; } mMetadataSet = true; } - AVRational outputTimeBase = useVideo ? mVideoInfo.mVideoTimeBase : mAudioInfo.mAudioTimeBase; - if (pkt->pts == AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE) { - ChipLogError(Camera, "Warning packet has no valid timestamps\n"); + ChipLogError(Camera, "Warning packet has no valid timestamps"); av_packet_unref(pkt); - return 0; + return RecorderStatus::kSuccess; } currentPts = (pkt->pts != AV_NOPTS_VALUE) ? pkt->pts : pkt->dts; @@ -684,10 +704,7 @@ int PushAVClipRecorder::ProcessBuffersAndWrite() mCurrentClipStartPts = currentPts; } - pkt->pts = av_rescale_q(pkt->pts, mClipInfo.mInputTimeBase, outputTimeBase); - pkt->dts = av_rescale_q(pkt->dts, mClipInfo.mInputTimeBase, outputTimeBase); - pkt->duration = av_rescale_q(pkt->duration, mClipInfo.mInputTimeBase, outputTimeBase); - pkt->pos = -1; + pkt->pos = -1; if (pkt->pts < 0) { @@ -697,8 +714,8 @@ int PushAVClipRecorder::ProcessBuffersAndWrite() if (av_interleaved_write_frame(mFormatContext, pkt) < 0) { ChipLogError(Camera, "Error writing frame to output file"); - FinalizeCurrentClip(1); - return -1; + FinalizeCurrentClip(ClipFinalizationReason::kErrorOccurred); + return RecorderStatus::kWarning; } av_packet_free(&pkt); @@ -710,9 +727,9 @@ int PushAVClipRecorder::ProcessBuffersAndWrite() { mAudioQueue.pop(); } - FinalizeCurrentClip(0); + FinalizeCurrentClip(ClipFinalizationReason::kSegmentUploadCheck); - return 0; + return RecorderStatus::kSuccess; } void PushAVClipRecorder::CleanupOutput() @@ -740,94 +757,91 @@ void PushAVClipRecorder::CleanupOutput() { avcodec_free_context(&mAudioEncoderContext); } - FinalizeCurrentClip(0); + FinalizeCurrentClip(ClipFinalizationReason::kCleanupUpload); mVideoStream = nullptr; mAudioStream = nullptr; mMetadataSet = false; ChipLogProgress(Camera, "Cleanup completed"); } -std::string RenameSegmentFile(const std::string & originalPath) +void PushAVClipRecorder::UpdateMPDParams(const std::string & mpdPath) { - std::regex segment_regex(R"((.*/segment_)(\d+)(\.m4s))"); - std::smatch match; - - if (std::regex_match(originalPath, match, segment_regex) && match.size() == 4) + std::ifstream inFile(mpdPath); + if (!inFile) { - std::string pathPrefix = match[1].str(); - std::string numberStr = match[2].str(); - std::string pathSuffix = match[3].str(); + ChipLogError(Camera, "ERROR: Failed to open MPD file for reading: %s", mpdPath.c_str()); + return; + } + + // Define the exact pattern to find + const std::string searchPattern = + R"(initialization="#__$RepresentationID$__#.init" media="#__$RepresentationID$__#segment_$Number%04d$.m4s" startNumber=")"; - char * endPtr; - long originalNumber = std::strtol(numberStr.c_str(), &endPtr, 10); + std::vector lines; + std::string line; + size_t streamIndex = 0; + bool foundAndReplaced = false; - // Check for conversion errors: no digits were converted, or extra characters remain. - if (endPtr == numberStr.c_str() || *endPtr != '\0' || originalNumber > INT_MAX || originalNumber < INT_MIN) + // Read file line by line + while (std::getline(inFile, line)) + { + size_t pos = line.find(searchPattern); + while (pos != std::string::npos && streamIndex < mStreamIdNameMap.size()) { - ChipLogDetail(Camera, "Invalid segment number format in path %s, not renaming.", originalPath.c_str()); - return originalPath; - } + const std::string & streamName = mStreamIdNameMap[static_cast(streamIndex)]; - int newNumber = static_cast(originalNumber) + kSegmentIdOffset; + // Find the startNumber value + size_t startNumberStart = line.find("startNumber=\"", pos); + size_t startNumberEnd = line.find("\"", startNumberStart + 13); - if (newNumber > 9999) - { - ChipLogDetail(Camera, "Segment %s (new number %d) exceeds 9999, stopping clip recording", originalPath.c_str(), - newNumber); - return originalPath; - } + std::string replacement; - char newPathBuffer[1024]; - snprintf(newPathBuffer, sizeof(newPathBuffer), "%s%04d%s", pathPrefix.c_str(), newNumber, pathSuffix.c_str()); - std::string newPath = newPathBuffer; + if (startNumberStart != std::string::npos && startNumberEnd != std::string::npos) + { + // Replace the entire pattern + replacement = "initialization=\"" + streamName + "/" + streamName + ".init\" media=\"" + streamName + + "/segment_$Number%04d$.m4s\" startNumber=\"" + std::to_string(kMPDDefaultStartNumber) + "\""; - std::error_code error; - std::filesystem::rename(originalPath.c_str(), newPath.c_str(), error); - if (error.value() == 0) - { - ChipLogDetail(Camera, "Renamed segment %s to %s", originalPath.c_str(), newPath.c_str()); - return newPath; - } - else - { - ChipLogDetail(Camera, "Failed to rename segment %s to %s, error: %d", originalPath.c_str(), newPath.c_str(), - error.value()); - return originalPath; + line.replace(pos, startNumberEnd - pos + 1, replacement); + foundAndReplaced = true; + streamIndex++; + } + + // Look for next occurrence in the same line + pos = line.find(searchPattern, pos + replacement.length()); } + lines.push_back(line); } + inFile.close(); - ChipLogDetail(Camera, "Path %s does not match expected segment format, not renaming.", originalPath.c_str()); - return originalPath; -} - -void UpdateMPDStartNumber(const std::string & mpdPath) -{ - std::ifstream file(mpdPath); - if (!file) + // Write the modified lines back to the file + if (foundAndReplaced) { - ChipLogError(Camera, "ERROR: Failed to open MPD file for reading: %s", mpdPath.c_str()); - return; - } - - std::string content((std::istreambuf_iterator(file)), std::istreambuf_iterator()); - file.close(); - - // Replace startNumber="" with startNumber="kMPDDefaultStartNumber" - std::regex startNumberRegex(R"(startNumber="\d+")"); - int newStartNumber = kMPDDefaultStartNumber; - std::string replacement = "startNumber=\"" + std::to_string(newStartNumber) + "\""; - std::string newContent = std::regex_replace(content, startNumberRegex, replacement); + std::ofstream outFile(mpdPath); + if (!outFile) + { + ChipLogError(Camera, "ERROR: Failed to open MPD file for writing: %s", mpdPath.c_str()); + return; + } - std::ofstream outFile(mpdPath); - if (!outFile) + for (size_t i = 0; i < lines.size(); ++i) + { + outFile << lines[i]; + if (i < lines.size() - 1) // Don't add newline after last line + outFile << "\n"; + } + outFile.close(); + ChipLogProgress(Camera, "Successfully updated stream info in MPD file: %s", mpdPath.c_str()); + } + else { - ChipLogError(Camera, "ERROR: Failed to open MPD file for writing: %s", mpdPath.c_str()); - return; + ChipLogProgress(Camera, "Pattern not found in MPD file, no changes made: %s", mpdPath.c_str()); } - outFile << newContent; - outFile.close(); +} - ChipLogProgress(Camera, "Successfully updated startNumber to 1001 in MPD file: %s", mpdPath.c_str()); +bool PushAVClipRecorder::IsFileReadyForUpload(const std::filesystem::path & path) const +{ + return std::filesystem::exists(path) && !std::filesystem::exists(path.string() + ".tmp"); } /** @@ -836,72 +850,145 @@ void UpdateMPDStartNumber(const std::string & mpdPath) * Writes the trailer of the current clip and initializes a new output file. */ -void PushAVClipRecorder::FinalizeCurrentClip(int reason) +void PushAVClipRecorder::FinalizeCurrentClip(ClipFinalizationReason reason) { int64_t clipLengthInPTS = currentPts - mCurrentClipStartPts; // Final duration has to be (clipDuration + preRollLen) seconds - const int64_t remainingDuration = mClipInfo.mInitialDurationS - mClipInfo.mElapsedTimeS + (mClipInfo.mPreRollLengthMs / 1000); - const int64_t clipDuration = (remainingDuration > 0) ? remainingDuration * AV_TIME_BASE_Q.den : 0; + const int64_t remainingDuration = + mClipInfo.mMotionDetectedDurationS - mClipInfo.mElapsedTimeS + (mClipInfo.mPreRollLengthMs / 1000); + int64_t clipDuration = 0; + + if ((mClipInfo.mTriggerType != 2) && remainingDuration <= 0) + { + ChipLogError(Camera, "Invalid remaining duration: %ld for sessionID: %lu Track name: %s - stopping recording", + remainingDuration, mClipInfo.mSessionNumber, mClipInfo.mTrackName.c_str()); + reason = ClipFinalizationReason::kErrorOccurred; + } + else + { + const auto & timeBase = mClipInfo.mHasVideo ? mVideoInfo.mVideoTimeBase : mAudioInfo.mAudioTimeBase; + if (timeBase.num == 0) + { + ChipLogError(Camera, "Invalid timebase (num=0) for %s stream in sessionID: %lu Track name: %s", + mClipInfo.mHasVideo ? "video" : "audio", mClipInfo.mSessionNumber, mClipInfo.mTrackName.c_str()); + } + else + { + clipDuration = (remainingDuration * timeBase.den) / timeBase.num; + } + } + // Pre-calculate common path components std::filesystem::path basePath = std::filesystem::path(mClipInfo.mOutputPath) / ("session_" + std::to_string(mClipInfo.mSessionNumber)) / mClipInfo.mTrackName; - if (reason || ((clipLengthInPTS >= clipDuration) && (mClipInfo.mTriggerType != 2))) + const char * reasonStr = "Unknown"; + switch (reason) + { + case ClipFinalizationReason::kErrorOccurred: + reasonStr = "Error occurred"; + break; + case ClipFinalizationReason::kSegmentUploadCheck: + reasonStr = "Segment upload check"; + break; + case ClipFinalizationReason::kCleanupUpload: + reasonStr = "Cleanup upload"; + break; + } + + bool shouldFinalize = + (reason == ClipFinalizationReason::kErrorOccurred) || ((clipLengthInPTS >= clipDuration) && (mClipInfo.mTriggerType != 2)); + + if (shouldFinalize) { ChipLogDetail(Camera, "Clip record completed, finalizing clip for sessionID: %lu Track name: %s, Reason: %s", - mClipInfo.mSessionNumber, mClipInfo.mTrackName.c_str(), - (reason == 0) ? "End of clip reached" : "Error occurred"); + mClipInfo.mSessionNumber, mClipInfo.mTrackName.c_str(), reasonStr); Stop(); mCurrentClipStartPts = AV_NOPTS_VALUE; } - // Helper function for safe path formatting using std::filesystem - auto make_segment_path = [&](int number) -> std::filesystem::path { + // Helper function for safe path formatting using std::filesystem + auto make_segment_path = [&](int stream, int number) -> std::filesystem::path { std::ostringstream oss; - oss << "segment_" << std::setw(4) << std::setfill('0') << number << ".m4s"; - return basePath / oss.str(); + oss << "#__" << stream << "__#segment_" << std::setw(4) << std::setfill('0') << number << ".m4s"; + return mUploadFileBasePath / oss.str(); }; - std::filesystem::path segment_path = make_segment_path(mUploadSegmentID); - while (std::filesystem::exists(segment_path) && !std::filesystem::exists(segment_path.string() + ".tmp")) + std::filesystem::path mpdPath = mUploadFileBasePath / "index.mpd"; + + // Wait for the first segment (segment_0001.m4s) for any stream to be created before starting any uploads + if (!firstSegmentReady) { - mUploadMPD = true; - std::string renamed_segment_path = RenameSegmentFile(segment_path.string()); - CheckAndUploadFile(renamed_segment_path); - mUploadSegmentID++; - segment_path = make_segment_path(mUploadSegmentID); + for (size_t i = 0; i < mUploadSegmentID.size(); i++) + { + if (mUploadSegmentID[i] == 1 && IsFileReadyForUpload(make_segment_path(i, 1))) + { + firstSegmentReady = true; + break; + } + } } + if (!firstSegmentReady) + return; - // Handle MPD and init file upload if (mUploadMPD) { - std::filesystem::path mpd_path = basePath; - mpd_path += ".mpd"; - if (std::filesystem::exists(mpd_path) && !std::filesystem::exists(mpd_path.string() + ".tmp")) + if (IsFileReadyForUpload(mpdPath)) { - mUploader->setMPDPath(std::make_pair(mpd_path.string(), mClipInfo.mUrl)); - UpdateMPDStartNumber(mpd_path.string()); - CheckAndUploadFile(mpd_path.string()); + UpdateMPDParams(mpdPath.string()); + CheckAndUploadFile(mpdPath.string()); mUploadMPD = false; // Reset flag after successful upload } + else + { + return; // Wait for MPD to be ready before proceeding + } + } - // Handle init segment upload if needed - if (!mUploadedInitSegment) + for (size_t i = 0; i < mUploadSegmentID.size(); i++) + { + if (!mUploadedInitSegment[i]) { - std::filesystem::path init_path = basePath / (mClipInfo.mTrackName + ".init"); - ChipLogProgress(Camera, "Recorder:Init segment upload ready [%s]", init_path.c_str()); - if (std::filesystem::exists(init_path) && !std::filesystem::exists(init_path.string() + ".tmp")) + const std::filesystem::path init_path = mUploadFileBasePath / ("#__" + std::to_string(i) + "__#" + ".init"); + if (IsFileReadyForUpload(init_path)) { CheckAndUploadFile(init_path.string()); + mUploadedInitSegment[i] = true; + } + else + { + return; // Wait for init segment to be ready before proceeding } - mUploadedInitSegment = true; } } + for (size_t i = 0; i < mUploadSegmentID.size(); i++) + { + std::filesystem::path segment_path = make_segment_path(i, mUploadSegmentID[i]); + while (IsFileReadyForUpload(segment_path)) + { + CheckAndUploadFile(segment_path.string()); + mUploadSegmentID[i]++; + // For testing purpose +#ifdef TEST_UPLOAD_MPD_AFTER_EVERY_SEGMENT + mUploadMPD = true; +#endif + segment_path = make_segment_path(i, mUploadSegmentID[i]); + } + } + + // For testing purpose +#ifdef TEST_UPLOAD_MPD_AFTER_EVERY_SEGMENT + if (IsFileReadyForUpload(mpdPath) && mUploadMPD) + { + UpdateMPDParams(mpdPath.string()); + CheckAndUploadFile(mpdPath.string()); + mUploadMPD = false; + } +#endif } bool PushAVClipRecorder::CheckAndUploadFile(std::string filename) { - ChipLogProgress(Camera, "Recorder:File upload ready [%s] to [%s]", filename.c_str(), mClipInfo.mUrl.c_str()); mUploader->AddUploadData(filename, mClipInfo.mUrl); return true; } diff --git a/examples/camera-app/linux/src/pushav-prerollbuffer.cpp b/examples/camera-app/linux/src/pushav-prerollbuffer.cpp index 854a3ca68c2..9e121c89057 100644 --- a/examples/camera-app/linux/src/pushav-prerollbuffer.cpp +++ b/examples/camera-app/linux/src/pushav-prerollbuffer.cpp @@ -29,7 +29,7 @@ void PreRollBuffer::SetMaxTotalBytes(size_t size) mMaxTotalBytes = size; TrimBuffer(); } -void PreRollBuffer::PushFrameToBuffer(const std::string & streamKey, const uint8_t * data, size_t size) +void PreRollBuffer::PushFrameToBuffer(const std::string & streamKey, const uint8_t * data, size_t size, int64_t timestampMs) { TrimBuffer(); std::lock_guard lock(mBufferMutex); @@ -38,7 +38,7 @@ void PreRollBuffer::PushFrameToBuffer(const std::string & streamKey, const uint8 frame->data = std::make_unique(size); memcpy(frame->data.get(), data, size); frame->size = size; - frame->ptsMs = NowMs(); + frame->ptsMs = timestampMs; auto & queue = mBuffers[streamKey]; // Get or create the queue for this stream key queue.push_back(frame); mContentBufferSize += size; // Track total bytes in buffer for all streams diff --git a/examples/camera-app/linux/src/pushav-transport/pushav-transport.cpp b/examples/camera-app/linux/src/pushav-transport/pushav-transport.cpp index 6612a41d8ba..ff97b019af0 100644 --- a/examples/camera-app/linux/src/pushav-transport/pushav-transport.cpp +++ b/examples/camera-app/linux/src/pushav-transport/pushav-transport.cpp @@ -16,8 +16,10 @@ * limitations under the License. */ -#include +#include +#include #include +#include using namespace chip::app::Clusters::PushAvStreamTransport; @@ -26,9 +28,26 @@ PushAVTransport::PushAVTransport(const TransportOptionsStruct & transportOptions mAudioStreamParams(audioStreamParams), mVideoStreamParams(videoStreamParams) { - ConfigureRecorderSettings(transportOptions, audioStreamParams, videoStreamParams); - mConnectionID = connectionID; - mTransportStatus = TransportStatusEnum::kInactive; + mConnectionID = connectionID; + mTransportStatus = TransportStatusEnum::kInactive; + mBlindStartTime = std::chrono::steady_clock::time_point(); + mCurrentActivationByManualTrigger = false; + mPreviousActivationByManualTrigger = false; + + auto now = std::chrono::system_clock::now(); + std::time_t time_t_now = std::chrono::system_clock::to_time_t(now); + std::tm tm_now; + localtime_r(&time_t_now, &tm_now); + + char datetime_str[32]; + std::strftime(datetime_str, sizeof(datetime_str), "%Y%m%d_%H%M%S", &tm_now); + + // Example folder name: FabricIdx1_ConnectionId2_20251103_225428 + std::string uniqueDirName = + "FabricIdx" + std::to_string(mFabricIndex) + "_ConnectionId" + std::to_string(connectionID) + "_" + datetime_str; + + std::filesystem::path outputPath = std::filesystem::path("/tmp") / uniqueDirName; + mClipInfo.mOutputPath = outputPath.string(); } const char * GetAudioCodecName(int codecId) @@ -53,13 +72,21 @@ const char * GetVideoCodecName(int codecId) } } +void PrintRecorderTimeSetting(const PushAVClipRecorder::ClipInfoStruct & clipInfo) +{ + ChipLogDetail(Camera, "=== PushAVTransport ConfigureRecorderTimeSetting ==="); + ChipLogDetail(Camera, "Initial Duration: %d sec", clipInfo.mInitialDurationS); + ChipLogDetail(Camera, "Augmentation Duration: %d sec", clipInfo.mAugmentationDurationS); + ChipLogDetail(Camera, "Max Clip Duration: %d sec", clipInfo.mMaxClipDurationS); + ChipLogDetail(Camera, "Blind Duration: %d sec", clipInfo.mBlindDurationS); +} + void PrintTransportSettings(PushAVClipRecorder::ClipInfoStruct clipInfo, PushAVClipRecorder::AudioInfoStruct audioInfo, PushAVClipRecorder::VideoInfoStruct videoInfo) { ChipLogProgress(Camera, "=== Clip Configuration ==="); ChipLogProgress(Camera, "Has Audio: %s", clipInfo.mHasAudio ? "true" : "false"); ChipLogProgress(Camera, "Has Video: %s", clipInfo.mHasVideo ? "true" : "false"); - ChipLogProgress(Camera, "Session Group: %d", clipInfo.mSessionGroup); ChipLogProgress(Camera, "Chunk Duration: %d ms", clipInfo.mChunkDurationMs); ChipLogProgress(Camera, "Segment Duration: %d ms", clipInfo.mSegmentDurationMs); ChipLogProgress(Camera, "PreRoll Length: %d ms", clipInfo.mPreRollLengthMs); @@ -67,15 +94,6 @@ void PrintTransportSettings(PushAVClipRecorder::ClipInfoStruct clipInfo, PushAVC ChipLogProgress(Camera, "Trigger Type: %d", clipInfo.mTriggerType); ChipLogProgress(Camera, "Output Path: %s", clipInfo.mOutputPath.c_str()); ChipLogProgress(Camera, "Track Name: %s", clipInfo.mTrackName.c_str()); - ChipLogProgress(Camera, "Input Time Base: %d/%d", clipInfo.mInputTimeBase.num, clipInfo.mInputTimeBase.den); - // Time control parameters are only passed during transport allocation for motion triggers. - if (clipInfo.mTriggerType == 1) - { - ChipLogProgress(Camera, "Initial Duration: %d sec", clipInfo.mInitialDurationS); - ChipLogProgress(Camera, "Augmentation Duration: %d sec", clipInfo.mAugmentationDurationS); - ChipLogProgress(Camera, "Max Clip Duration: %d sec", clipInfo.mMaxClipDurationS); - ChipLogProgress(Camera, "Blind Duration: %d sec", clipInfo.mBlindDurationS); - } ChipLogProgress(Camera, "=== Audio Configuration ==="); ChipLogProgress(Camera, "Codec: %s", GetAudioCodecName(audioInfo.mAudioCodecId)); @@ -83,45 +101,60 @@ void PrintTransportSettings(PushAVClipRecorder::ClipInfoStruct clipInfo, PushAVC ChipLogProgress(Camera, "Sample Rate: %d Hz", audioInfo.mSampleRate); ChipLogProgress(Camera, "Bit Rate: %d bps", audioInfo.mBitRate); ChipLogProgress(Camera, "Audio Time Base: %d/%d", audioInfo.mAudioTimeBase.num, audioInfo.mAudioTimeBase.den); - ChipLogProgress(Camera, "Frame Duration: %d samples", audioInfo.mAudioFrameDuration); + ChipLogProgress(Camera, "Audio Stream Name: %s", audioInfo.mAudioStreamName.c_str()); ChipLogProgress(Camera, "=== Video Configuration ==="); ChipLogProgress(Camera, "Codec: %s", GetVideoCodecName(videoInfo.mVideoCodecId)); ChipLogProgress(Camera, "Resolution: %dx%d", videoInfo.mWidth, videoInfo.mHeight); ChipLogProgress(Camera, "Frame Rate: %d fps", videoInfo.mFrameRate); ChipLogProgress(Camera, "Video Time Base: %d/%d", videoInfo.mVideoTimeBase.num, videoInfo.mVideoTimeBase.den); - ChipLogProgress(Camera, "Frame Duration: %d ticks", videoInfo.mVideoFrameDuration); ChipLogProgress(Camera, "Bit Rate: %d bps", videoInfo.mBitRate); + ChipLogProgress(Camera, "Video Stream Name: %s", videoInfo.mVideoStreamName.c_str()); } void PushAVTransport::ConfigureRecorderTimeSetting( const chip::app::Clusters::PushAvStreamTransport::Structs::TransportMotionTriggerTimeControlStruct::DecodableType & timeControl) { - mClipInfo.mInitialDurationS = timeControl.initialDuration; + mClipInfo.mInitialDurationS = std::min(static_cast(timeControl.initialDuration), timeControl.maxDuration); mClipInfo.mAugmentationDurationS = timeControl.augmentationDuration; mClipInfo.mMaxClipDurationS = timeControl.maxDuration; mClipInfo.mBlindDurationS = timeControl.blindDuration; - mClipInfo.mElapsedTimeS = 0; - ChipLogDetail(Camera, "=== PushAVTransport ConfigureRecorderTimeSetting ==="); - ChipLogDetail(Camera, "Initial Duration: %d sec", mClipInfo.mInitialDurationS); - ChipLogDetail(Camera, "Augmentation Duration: %d sec", mClipInfo.mAugmentationDurationS); - ChipLogDetail(Camera, "Max Clip Duration: %d sec", mClipInfo.mMaxClipDurationS); - ChipLogDetail(Camera, "Blind Duration: %d sec", mClipInfo.mBlindDurationS); - if (mRecorder.get() != nullptr) - { - mRecorder->mClipInfo = mClipInfo; - } + + PrintRecorderTimeSetting(mClipInfo); } -void PushAVTransport::ConfigureRecorderSettings(const TransportOptionsStruct & transportOptions, - AudioStreamStruct & audioStreamParams, VideoStreamStruct & videoStreamParams) +CHIP_ERROR PushAVTransport::ConfigureRecorderSettings(const TransportOptionsStruct & transportOptions, + AudioStreamStruct & audioStreamParams, VideoStreamStruct & videoStreamParams) { - mClipInfo.mHasAudio = transportOptions.audioStreamID.HasValue(); - mClipInfo.mHasVideo = transportOptions.videoStreamID.HasValue(); - if (mClipInfo.mHasAudio && mClipInfo.mHasVideo) + uint8_t audioCodec = static_cast(audioStreamParams.audioCodec); + if (audioCodec == 2) + { + ChipLogError(Camera, "Unknown Audio codec"); + return CHIP_ERROR_INVALID_ARGUMENT; + } + else if (audioCodec != 0) { - mClipInfo.mHasAudio = false; + ChipLogError(Camera, "Unsupported Audio codec"); + return CHIP_ERROR_INVALID_ARGUMENT; } + + int8_t videoCodec = static_cast(videoStreamParams.videoCodec); + if (videoCodec == 4) + { + ChipLogError(Camera, "Unknown Video codec"); + return CHIP_ERROR_INVALID_ARGUMENT; + } + else if (videoCodec != 0) + { + ChipLogError(Camera, "Unsupported Video codec"); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + // Codecs are valid, proceed with configuration + mClipInfo.mHasAudio = (transportOptions.audioStreams.HasValue() || transportOptions.audioStreamID.HasValue()); + mClipInfo.mHasVideo = (transportOptions.videoStreams.HasValue() || transportOptions.videoStreamID.HasValue()); + mSessionStartedTimestamp = std::chrono::system_clock::time_point(); + mClipInfo.mUrl = std::string(transportOptions.url.data(), transportOptions.url.size()); mClipInfo.mTriggerType = static_cast(transportOptions.triggerOptions.triggerType); if (transportOptions.triggerOptions.maxPreRollLen.HasValue()) @@ -132,13 +165,17 @@ void PushAVTransport::ConfigureRecorderSettings(const TransportOptionsStruct & t { mClipInfo.mPreRollLengthMs = 0; // Default pre roll length is zero } + + mClipInfo.mMotionDetectedDurationS = 0; + mClipInfo.mPreviousMotionDetectedDurationS = 0; + mClipInfo.mElapsedTimeS = 0; + if (transportOptions.triggerOptions.motionTimeControl.HasValue()) { ConfigureRecorderTimeSetting(transportOptions.triggerOptions.motionTimeControl.Value()); } if (transportOptions.containerOptions.CMAFContainerOptions.HasValue()) { - mClipInfo.mSessionGroup = transportOptions.containerOptions.CMAFContainerOptions.Value().sessionGroup; mClipInfo.mTrackName = std::string(transportOptions.containerOptions.CMAFContainerOptions.Value().trackName.data(), transportOptions.containerOptions.CMAFContainerOptions.Value().trackName.size()); mClipInfo.mChunkDurationMs = transportOptions.containerOptions.CMAFContainerOptions.Value().chunkDuration; @@ -146,10 +183,8 @@ void PushAVTransport::ConfigureRecorderSettings(const TransportOptionsStruct & t } mTransportTriggerType = transportOptions.triggerOptions.triggerType; - mClipInfo.mOutputPath = "/tmp/"; // CAUTION: If path is not accessible to executable, the program may fail to write and crash. - mClipInfo.mInputTimeBase = { 1, 1000000 }; - uint8_t audioCodec = static_cast(audioStreamParams.audioCodec); + // Configure audio settings if (audioStreamParams.channelCount == 0) { ChipLogError(Camera, "Invalid channel count: 0. Using fallback 1 channel."); @@ -161,53 +196,40 @@ void PushAVTransport::ConfigureRecorderSettings(const TransportOptionsStruct & t { if (audioStreamParams.sampleRate == 0) { + ChipLogError(Camera, "Invalid sample rate: 0. Using fallback 48000 Hz."); audioStreamParams.sampleRate = 48000; // Fallback value for invalid sample rate } - mAudioInfo.mAudioCodecId = AV_CODEC_ID_OPUS; - mAudioInfo.mAudioTimeBase = { 1, static_cast(audioStreamParams.sampleRate) }; - mAudioInfo.mAudioFrameDuration = 20000; // Default OPUS frame duration - } - else if (audioCodec == 2) - { - ChipLogError(Camera, "Unknown Audio codec") - } - else - { - ChipLogError(Camera, "Unsupported Audio codec"); + mAudioInfo.mAudioCodecId = AV_CODEC_ID_OPUS; + mAudioInfo.mAudioTimeBase = { 1, static_cast(audioStreamParams.sampleRate) }; } - if (audioStreamParams.sampleRate == 0) - { - ChipLogError(Camera, "Invalid sample rate: 0. Using fallback 48000 Hz."); - audioStreamParams.sampleRate = 48000; // Fallback value for invalid sample rate - } mAudioInfo.mSampleRate = audioStreamParams.sampleRate; if (audioStreamParams.bitRate == 0) { ChipLogError(Camera, "Invalid audio bit rate: 0. Using fallback 96000 bps."); audioStreamParams.bitRate = 96000; } - mAudioInfo.mBitRate = audioStreamParams.bitRate; - mAudioInfo.mAudioPts = 0; - mAudioInfo.mAudioDts = 0; - mAudioInfo.mAudioStreamIndex = -1; + mAudioInfo.mBitRate = audioStreamParams.bitRate; + if (mClipInfo.mHasAudio) + { + if (transportOptions.audioStreams.HasValue() && !transportOptions.audioStreams.Value().empty()) + { + // Recoder module currently only supports one audio and one video stream + auto audioStreamName = transportOptions.audioStreams.Value().begin()->audioStreamName; + mAudioInfo.mAudioStreamName = std::string(audioStreamName.data(), audioStreamName.size()); + } + else + { + mAudioInfo.mAudioStreamName = "audio"; + } + } - int8_t VideoCodec = static_cast(videoStreamParams.videoCodec); - if (VideoCodec == 0) + // Configure video settings + if (videoCodec == 0) { mVideoInfo.mVideoCodecId = AV_CODEC_ID_H264; mVideoInfo.mVideoTimeBase = { 1, 90000 }; } - else if (VideoCodec == 4) - { - ChipLogError(Camera, "Unknown Video codec") - } - else - { - ChipLogError(Camera, "Unsupported Video codec"); - } - mVideoInfo.mVideoPts = 0; - mVideoInfo.mVideoDts = 0; if (videoStreamParams.maxResolution.width == 0 || videoStreamParams.maxResolution.height == 0) { videoStreamParams.maxResolution.width = 640; @@ -221,25 +243,43 @@ void PushAVTransport::ConfigureRecorderSettings(const TransportOptionsStruct & t videoStreamParams.minFrameRate = 30; } mVideoInfo.mFrameRate = videoStreamParams.minFrameRate; - - mVideoInfo.mVideoFrameDuration = 900000 / mVideoInfo.mFrameRate; - mVideoInfo.mVideoStreamIndex = -1; - mVideoInfo.mBitRate = videoStreamParams.minBitRate; + mVideoInfo.mBitRate = videoStreamParams.minBitRate; + if (mClipInfo.mHasVideo) + { + if (transportOptions.videoStreams.HasValue() && !transportOptions.videoStreams.Value().empty()) + { + // Recoder module currently only supports one audio and one video stream + auto videoStreamName = transportOptions.videoStreams.Value().begin()->videoStreamName; + mVideoInfo.mVideoStreamName = std::string(videoStreamName.data(), videoStreamName.size()); + } + else + { + mVideoInfo.mVideoStreamName = "video"; + } + } PrintTransportSettings(mClipInfo, mAudioInfo, mVideoInfo); - ChipLogProgress(Camera, "PushAvStreamTransportManager, Configure Recorder Settings done !!!"); + UpdateSendFlags(); + ChipLogProgress(Camera, "Transport[%u] Session[%lu] ConfigureRecorderSettings success - Track=%s HasVideo=%s HasAudio=%s", + mConnectionID, mSessionNumber, mClipInfo.mTrackName.c_str(), mClipInfo.mHasVideo ? "true" : "false", + mClipInfo.mHasAudio ? "true" : "false"); + + return CHIP_NO_ERROR; } void PushAVTransport::InitializeRecorder() { if (mRecorder.get() == nullptr) { - mRecorder = std::make_unique(mClipInfo, mAudioInfo, mVideoInfo, mUploader.get()); + mSessionStartedTimestamp = std::chrono::system_clock::time_point(); + mClipInfo.mSessionNumber = mSessionNumber; + mRecorder = std::make_unique(mClipInfo, mAudioInfo, mVideoInfo, mUploader.get()); mRecorder->SetFabricIndex(mFabricIndex); mRecorder->SetPushAvStreamTransportServer(mPushAvStreamTransportServer); - mRecorder->SetPushAvStreamTransportManager(mPushAvStreamTransportManager); mRecorder->SetConnectionInfo(mConnectionID, mTransportTriggerType, chip::Optional()); + ChipLogProgress(Camera, "PushAVTransport, Initialize Recorder done !!! FabricIdx: %u Session Id: %ld", mFabricIndex, + mClipInfo.mSessionNumber); } else { @@ -249,163 +289,221 @@ void PushAVTransport::InitializeRecorder() PushAVTransport::~PushAVTransport() { - // TODO: cleanup the existing recorded files here. mCanSendVideo = false; mCanSendAudio = false; + mRecorder.reset(); mUploader.reset(); -} -bool InBlindPeriod(std::chrono::steady_clock::time_point blindStartTime, uint16_t blindDuration) -{ - if (blindStartTime == std::chrono::steady_clock::time_point()) + std::filesystem::path uniqueDirPath(mClipInfo.mOutputPath); + + if (std::filesystem::exists(uniqueDirPath) && std::filesystem::is_directory(uniqueDirPath)) { - ChipLogProgress(Camera, "PushAVTransport no blind period"); - return false; + std::error_code ec; + std::filesystem::remove_all(uniqueDirPath, ec); + if (ec) + { + ChipLogError(Camera, "Failed to remove directory %s: %s", uniqueDirPath.c_str(), ec.message().c_str()); + } + else + { + ChipLogProgress(Camera, "Successfully removed directory: %s", uniqueDirPath.c_str()); + } } else { - auto now = std::chrono::steady_clock::now(); - auto elapsed = std::chrono::duration_cast(now - blindStartTime).count(); - ChipLogProgress(Camera, "PushAVTransport blind period elapsed: %lld", static_cast(elapsed)); - return ((elapsed >= 0) && (elapsed < blindDuration)); + ChipLogDetail(Camera, "Directory does not exist: %s", uniqueDirPath.c_str()); } } -bool PushAVTransport::HandleTriggerDetected() +bool InBlindPeriod(std::chrono::steady_clock::time_point blindStartTime, uint16_t blindDuration, + std::chrono::steady_clock::time_point now) { - int64_t elapsed = 0; - auto now = std::chrono::steady_clock::now(); - - if (mTransportTriggerType != TransportTriggerTypeEnum::kCommand && InBlindPeriod(mBlindStartTime, mClipInfo.mBlindDurationS)) + if (blindDuration == 0 || blindStartTime == std::chrono::steady_clock::time_point()) { + ChipLogProgress(Camera, "PushAVTransport: No active blind period"); return false; } - if (mClipInfo.activationTime != std::chrono::steady_clock::time_point()) + const auto elapsedSeconds = std::chrono::duration_cast(now - blindStartTime).count(); + ChipLogProgress(Camera, "PushAVTransport blind period, blindDuration: %u seconds", blindDuration); + return ((elapsedSeconds >= 0) && (elapsedSeconds < blindDuration)); +} + +bool PushAVTransport::HandleTriggerDetected() +{ + auto now = std::chrono::steady_clock::now(); + + // Blind duration is considered in case of motion event only + if (!mPreviousActivationByManualTrigger && !mCurrentActivationByManualTrigger && + InBlindPeriod(mBlindStartTime, mClipInfo.mBlindDurationS, now)) { - elapsed = std::chrono::duration_cast(now - mClipInfo.activationTime).count(); + ChipLogError(Camera, + "PushAVTransport command/motion transport trigger received but ignored due to blind period. Clip duration " + "[%d seconds]", + mRecorder->mClipInfo.mMotionDetectedDurationS); + return false; } - ChipLogDetail(Camera, "PushAVTransport HandleTriggerDetected elapsed: %ld", elapsed); - - if (!mRecorder->GetRecorderStatus()) + int64_t elapsedClipDurationS = std::chrono::duration_cast(now - mClipInfo.mActivationTime).count(); + if (mClipInfo.mActivationTime == std::chrono::steady_clock::time_point() || + elapsedClipDurationS >= mClipInfo.mMotionDetectedDurationS) { // Start new recording - ChipLogError(Camera, "PushAVTransport starting new recording"); - mHasAugmented = false; - mClipInfo.activationTime = std::chrono::steady_clock::now(); - mRecorder->mClipInfo.activationTime = mClipInfo.activationTime; - mRecorder->mClipInfo.mSessionNumber = - mPushAvStreamTransportManager->OnTriggerActivated(mFabricIndex, mClipInfo.mSessionGroup, mConnectionID); + ChipLogDetail(Camera, "PushAVTransport starting new recording"); + mHasAugmented = false; + mClipInfo.mActivationTime = now; - mRecorder->Start(); - mStreaming = true; + mPreviousActivationByManualTrigger = mCurrentActivationByManualTrigger; + mClipInfo.mMotionDetectedDurationS = mClipInfo.mInitialDurationS; + mClipInfo.mPreviousMotionDetectedDurationS = 0; + mClipInfo.mElapsedTimeS = 0; } else { - // Extend existing recording - uint16_t previousDuration = mRecorder->mClipInfo.mInitialDurationS - mRecorder->mClipInfo.mAugmentationDurationS; + // Handle augmentation for ongoing recording + ChipLogDetail(Camera, "PushAVTransport HandleTriggerDetected time since last trigger: %ld", elapsedClipDurationS); - if ((elapsed < mRecorder->mClipInfo.mInitialDurationS) && (!mHasAugmented || elapsed >= previousDuration)) + if (!mHasAugmented || (mHasAugmented && (elapsedClipDurationS >= mClipInfo.mPreviousMotionDetectedDurationS))) { - ChipLogError(Camera, "PushAVTransport extending recording %d -> %d", mRecorder->mClipInfo.mInitialDurationS, - static_cast(std::min(static_cast(mRecorder->mClipInfo.mInitialDurationS + - mRecorder->mClipInfo.mAugmentationDurationS), - static_cast(mRecorder->mClipInfo.mMaxClipDurationS)))); - mRecorder->mClipInfo.mInitialDurationS = static_cast(std::min( - static_cast(mRecorder->mClipInfo.mInitialDurationS + mRecorder->mClipInfo.mAugmentationDurationS), - static_cast(mRecorder->mClipInfo.mMaxClipDurationS))); - mHasAugmented = true; - mStreaming = true; + uint16_t newDuration = static_cast( + std::min(static_cast(mClipInfo.mMotionDetectedDurationS + mClipInfo.mAugmentationDurationS), + static_cast(mClipInfo.mMaxClipDurationS))); + + ChipLogDetail(Camera, "PushAVTransport extending recording %d -> %d", mClipInfo.mMotionDetectedDurationS, newDuration); + + // Update tracking variables + mClipInfo.mPreviousMotionDetectedDurationS = mClipInfo.mMotionDetectedDurationS; + mClipInfo.mMotionDetectedDurationS = newDuration; + mHasAugmented = true; + } + } + + // Calculate blind start time based on when the current recording will actually end + // Use the current motion detected duration which represents when this recording session will end + mBlindStartTime = mClipInfo.mActivationTime + std::chrono::seconds(mClipInfo.mMotionDetectedDurationS); + + if (mRecorder.get() != nullptr) + { + mRecorder->mClipInfo.mMotionDetectedDurationS = mClipInfo.mMotionDetectedDurationS; + if (!mRecorder->GetRecorderStatus()) + { + mRecorder->SetConnectionInfo(mConnectionID, mTransportTriggerType, mActivationReason); + // Initiate recording if the recorder is not currently recording + StartRecordingAndStreaming(); } } - mBlindStartTime = mRecorder->mClipInfo.activationTime + std::chrono::seconds(mRecorder->mClipInfo.mInitialDurationS); return true; } -void PushAVTransport::TriggerTransport(TriggerActivationReasonEnum activationReason, int zoneId, int sensitivity) +void PushAVTransport::StartRecordingAndStreaming() { - ChipLogProgress(Camera, "PushAVTransport trigger transport, activation reason: [%u], ZoneId: [%d], Sensitivity: [%d]", - (uint16_t) activationReason, zoneId, sensitivity); - if (mTransportTriggerType == TransportTriggerTypeEnum::kCommand) + mRecorder->mClipInfo.mSessionNumber = mClipInfo.mSessionNumber; + mRecorder->Start(); + mStreaming = true; + UpdateSendFlags(); + if (IsStreaming() && (mTransportTriggerType != TransportTriggerTypeEnum::kCommand)) { - mRecorder->SetConnectionInfo(mConnectionID, mTransportTriggerType, chip::MakeOptional(activationReason)); - if (HandleTriggerDetected()) - { - ChipLogError(Camera, "PushAVTransport command/motion transport trigger received. Clip duration [%d seconds]", - mRecorder->mClipInfo.mInitialDurationS); - // Begin event already generated at cluster server - } - else - { - ChipLogError(Camera, - "PushAVTransport command/motion transport trigger received but ignored due to blind period. Clip duration " - "[%d seconds]", - mRecorder->mClipInfo.mInitialDurationS); - } + ChipLogDetail(Camera, "Ready to stream"); + GeneratePushTransportBeginEvent(); } - else if (mTransportTriggerType == TransportTriggerTypeEnum::kMotion) +} + +void PushAVTransport::GeneratePushTransportBeginEvent() +{ + if (mPushAvStreamTransportServer != nullptr) { - bool zoneFound = false; // Zone found flag - for (auto zone : mZoneSensitivityList) + // mActivationReason is optional - if not set, it defaults to empty value + mPushAvStreamTransportServer->NotifyTransportStarted(mConnectionID, mTransportTriggerType, mActivationReason); + } + else + { + ChipLogError(Camera, "PushAvStreamTransportServer is null or activation reason not set for connection %u", mConnectionID); + } +} + +bool PushAVTransport::ValidateZoneAndSensitivity( + const std::vector, uint8_t>> & zoneSensitivityList, int zoneId, + int sensitivity) +{ + // Validate input parameters + + if (sensitivity < 0 || sensitivity > 10) + { + ChipLogError(Camera, "PushAVTransport invalid sensitivity value: %d (must be 0-10)", sensitivity); + return false; + } + + if (zoneSensitivityList.empty()) + { + ChipLogProgress(Camera, "PushAVTransport zoneSensitivityList NOT set, accepting all zones"); + return true; + } + + // Check for specific zone match + for (const auto & zone : zoneSensitivityList) + { + if (zone.first.IsNull() || (zone.first.Value() == static_cast(zoneId))) { - // A Null ZoneId means all zones - if (zone.first.IsNull()) + if (zone.second <= static_cast(sensitivity)) { - zoneFound = true; + ChipLogDetail(Camera, "PushAVTransport zone %d accepted (sensitivity %d >= threshold %u)", zoneId, sensitivity, + zone.second); + return true; } else { - zoneFound = (zone.first.Value() = zoneId); - } - - if (zoneFound) - { - if (zone.second > sensitivity) - { - ChipLogProgress(Camera, "PushAVTransport motion transport trigger received but ignored due to sensitivity"); - } - else - { - if (HandleTriggerDetected()) - { - ChipLogError(Camera, - "PushAVTransport command/motion transport trigger received. Clip duration [%d seconds]", - mRecorder->mClipInfo.mInitialDurationS); - if (mPushAvStreamTransportServer != nullptr) - { - mPushAvStreamTransportServer->NotifyTransportStarted( - mConnectionID, mTransportTriggerType, - chip::Optional()); - } - else - { - ChipLogError(Camera, "PushAvStreamTransportServer is null for connection %u", mConnectionID); - } - } - else - { - ChipLogError(Camera, - "PushAVTransport command/motion transport trigger received but ignored due to blind period. " - "Clip duration. " - "Clip duration [%d seconds]", - mRecorder->mClipInfo.mInitialDurationS); - } - } - break; + ChipLogProgress(Camera, + "PushAVTransport motion transport trigger ignored - zone %d sensitivity %d exceeds threshold %u", + zoneId, sensitivity, zone.second); + return false; } } - if (!zoneFound) - { - ChipLogProgress(Camera, "PushAVTransport motion transport trigger received but ignored due to unknown zone id"); - } + } + + ChipLogProgress(Camera, "PushAVTransport motion transport trigger ignored - zone %d not found in configuration", zoneId); + return false; +} + +void PushAVTransport::TriggerTransport(TriggerActivationReasonEnum activationReason, int zoneId, int sensitivity) +{ + ChipLogProgress(Camera, "PushAVTransport trigger transport, activation reason: [%u], ZoneId: [%d], Sensitivity: [%d]", + (uint16_t) activationReason, zoneId, sensitivity); + + mCurrentActivationByManualTrigger = (zoneId == kInvalidZoneId) ? true : false; + mActivationReason = chip::MakeOptional(activationReason); + + // Check if trigger should be processed based on transport type + bool shouldProcessTrigger = false; + + if (mTransportTriggerType == TransportTriggerTypeEnum::kCommand) + { + shouldProcessTrigger = true; + } + else if (mTransportTriggerType == TransportTriggerTypeEnum::kMotion) + { + shouldProcessTrigger = + mCurrentActivationByManualTrigger || ValidateZoneAndSensitivity(mZoneSensitivityList, zoneId, sensitivity); } else if (mTransportTriggerType == TransportTriggerTypeEnum::kContinuous) { ChipLogProgress(Camera, "PushAVTransport continuous transport trigger received. No action needed"); return; } + // Process the trigger if conditions are met + if (shouldProcessTrigger) + { + if (HandleTriggerDetected()) + { + // Event generation is handled differently based on trigger type: + // - Command: Begin event already generated at cluster server + // - Motion: GeneratePushTransportBeginEvent() would be called inside `HandleTriggerDetected` API if needed + } + else + { + ChipLogError(Camera, "PushAVTransport trigger detection ignored or failed for connection %u", mConnectionID); + } + } } void PushAVTransport::SetTLSCertPath(std::string rootCert, std::string devCert, std::string devKey) @@ -438,38 +536,25 @@ void PushAVTransport::SetTransportStatus(TransportStatusEnum status) { ChipLogProgress(Camera, "PushAVTransport transport status changed to active"); - mUploader = std::make_unique(); - mUploader->setCertificateBuffer(mCertBuffer); - mUploader->setCertificatePath(mCertPath); - mUploader->Start(); + if (mUploader.get() == nullptr) + { + mUploader = std::make_unique(); + mUploader->setCertificateBuffer(mCertBuffer); + mUploader->setCertificatePath(mCertPath); + mUploader->Start(); + } InitializeRecorder(); - mRecorder->mClipInfo.mElapsedTimeS = 0; if (mTransportTriggerType == TransportTriggerTypeEnum::kContinuous) { - mRecorder->mClipInfo.mSessionNumber = - mPushAvStreamTransportManager->OnTriggerActivated(mFabricIndex, mClipInfo.mSessionGroup, mConnectionID); - mRecorder->Start(); - mStreaming = true; - if (IsStreaming()) - { - ChipLogProgress(Camera, "Ready to stream"); - if (mPushAvStreamTransportServer != nullptr) - { - mPushAvStreamTransportServer->NotifyTransportStarted( - mConnectionID, mTransportTriggerType, - chip::Optional()); - } - else - { - ChipLogError(Camera, "PushAvStreamTransportServer is null for connection %u", mConnectionID); - } - } + mClipInfo.mMotionDetectedDurationS = 0; + mClipInfo.mElapsedTimeS = 0; + StartRecordingAndStreaming(); } else if (mTransportTriggerType == TransportTriggerTypeEnum::kMotion) { - // Check if activationTime is set (non-default) - if (mClipInfo.activationTime == std::chrono::steady_clock::time_point()) + // Check if mActivationTime is set (non-default) + if (mClipInfo.mActivationTime == std::chrono::steady_clock::time_point()) { ChipLogProgress(Camera, "No active trigger to start recording"); } @@ -477,19 +562,19 @@ void PushAVTransport::SetTransportStatus(TransportStatusEnum status) { auto now = std::chrono::steady_clock::now(); auto elapsedSeconds = - std::chrono::duration_cast(now - mRecorder->mClipInfo.activationTime).count(); + std::chrono::duration_cast(now - mRecorder->mClipInfo.mActivationTime).count(); // Check if recording duration has expired - if (elapsedSeconds >= mRecorder->mClipInfo.mInitialDurationS) + if (elapsedSeconds >= mRecorder->mClipInfo.mMotionDetectedDurationS) { ChipLogProgress(Camera, "No active trigger (time expired) to start recording"); } else { - // Calculate remaining duration safely mRecorder->mClipInfo.mElapsedTimeS = static_cast(elapsedSeconds); ChipLogProgress(Camera, "Active trigger is present. Recording will start for [%d seconds]", - mRecorder->mClipInfo.mInitialDurationS); + mRecorder->mClipInfo.mMotionDetectedDurationS); + StartRecordingAndStreaming(); } } } @@ -497,32 +582,32 @@ void PushAVTransport::SetTransportStatus(TransportStatusEnum status) else if (status == TransportStatusEnum::kInactive) { ChipLogProgress(Camera, "PushAVTransport transport status change requested to inactive"); - mStreaming = false; // Stop streaming - mCanSendVideo = false; - mCanSendAudio = false; + mStreaming = false; // Stop streaming + UpdateSendFlags(); mRecorder.reset(); ChipLogProgress(Camera, "Recorder destruction done"); - InitializeRecorder(); + // Clear activationTime for manual triggers when setting status to inactive + if (mCurrentActivationByManualTrigger) + { + mClipInfo.mActivationTime = std::chrono::steady_clock::time_point(); + ChipLogDetail(Camera, "PushAVTransport, cleared mActivationTime for manual trigger"); + } mUploader.reset(); ChipLogProgress(Camera, "Uploader destruction done"); ChipLogProgress(Camera, "PushAVTransport transport status changed to inactive"); } } -bool PushAVTransport::IsStreaming() +void PushAVTransport::UpdateSendFlags() { - if (mStreaming && (mTransportStatus == TransportStatusEnum::kActive)) - { - mCanSendVideo = true; - mCanSendAudio = true; - return true; - } - else - { - mCanSendVideo = false; - mCanSendAudio = false; - return false; - } + bool canSend = mStreaming && (mTransportStatus == TransportStatusEnum::kActive); + mCanSendVideo = canSend && mClipInfo.mHasVideo; + mCanSendAudio = canSend && mClipInfo.mHasAudio; +} + +bool PushAVTransport::IsStreaming() const +{ + return mStreaming && (mTransportStatus == TransportStatusEnum::kActive); } bool PushAVTransport::CanSendPacketsToRecorder() @@ -531,30 +616,34 @@ bool PushAVTransport::CanSendPacketsToRecorder() { return false; } + + CheckAndUpdateSession(); + if (mRecorder->mDeinitializeRecorder.load()) { ChipLogProgress(Camera, "Current clip is completed, Next clip will start on trigger"); mRecorder.reset(); // Redundant cleanup to make sure no dangling pointer left InitializeRecorder(); mStreaming = false; + UpdateSendFlags(); return false; } return true; } -void PushAVTransport::SendVideo(const chip::ByteSpan & data, int64_t timestamp, uint16_t videoStreamID) +void PushAVTransport::SendVideo(const chip::ByteSpan & data, int64_t timestampMs, uint16_t videoStreamID) { if (CanSendPacketsToRecorder()) { - mRecorder->PushPacket(data.data(), data.size(), 1); + mRecorder->PushPacket(data.data(), data.size(), timestampMs, 1); } } -void PushAVTransport::SendAudio(const chip::ByteSpan & data, int64_t timestamp, uint16_t audioStreamID) +void PushAVTransport::SendAudio(const chip::ByteSpan & data, int64_t timestampMs, uint16_t audioStreamID) { if (CanSendPacketsToRecorder()) { - mRecorder->PushPacket(data.data(), data.size(), 0); + mRecorder->PushPacket(data.data(), data.size(), timestampMs, 0); } } @@ -609,9 +698,23 @@ bool PushAVTransport::CanSendAudio() return IsStreaming() && mClipInfo.mHasAudio; } -void PushAVTransport::ModifyPushTransport(const TransportOptionsStorage & transportOptions) +CHIP_ERROR PushAVTransport::ModifyPushTransport(const TransportOptionsStorage & transportOptions) { - ConfigureRecorderSettings(transportOptions, mAudioStreamParams, mVideoStreamParams); + CHIP_ERROR err = ConfigureRecorderSettings(transportOptions, mAudioStreamParams, mVideoStreamParams); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Camera, "Failed to modify push transport settings for connection %u: %s", mConnectionID, chip::ErrorStr(err)); + return err; + } + + if (mRecorder) + { + mStreaming = false; + UpdateSendFlags(); + mRecorder.reset(); + InitializeRecorder(); + } + return CHIP_NO_ERROR; } bool PushAVTransport::GetBusyStatus() @@ -624,20 +727,40 @@ uint16_t PushAVTransport::GetPreRollLength() return mClipInfo.mPreRollLengthMs; } -void PushAVTransport::StartNewSession(uint64_t newSessionID) +void PushAVTransport::CheckAndUpdateSession() { - mClipInfo.mSessionNumber = newSessionID; - ChipLogProgress(Camera, "Session completed, New session started with session number [%ld]", mClipInfo.mSessionNumber); - mStreaming = false; - mCanSendVideo = false; - mCanSendAudio = false; - mRecorder.reset(); + auto now = std::chrono::system_clock::now(); - InitializeRecorder(); - auto now = std::chrono::steady_clock::now(); - auto elapsedSeconds = std::chrono::duration_cast(now - mRecorder->mClipInfo.activationTime).count(); - mRecorder->mClipInfo.mElapsedTimeS = static_cast(elapsedSeconds); + if (mSessionStartedTimestamp == std::chrono::system_clock::time_point()) + { + mSessionStartedTimestamp = now; + mSessionNumber++; + ChipLogProgress(Camera, "Transport[%u] Session[%lu] SESSION_STARTED: First session initialized for Track=%s", mConnectionID, + mSessionNumber, mClipInfo.mTrackName.c_str()); + return; + } - mRecorder->Start(); - mStreaming = true; + auto elapsed = std::chrono::duration_cast(now - mSessionStartedTimestamp).count(); + if (elapsed >= kMaxSessionDurationMinutes) + { + mSessionStartedTimestamp = now; + + ChipLogProgress(Camera, + "Transport[%u] Session[%lu] SESSION_INCREMENTED: Session duration limit reached (%d min). New session " + "started. Track=%s", + mConnectionID, mSessionNumber, kMaxSessionDurationMinutes, mClipInfo.mTrackName.c_str()); + mStreaming = false; + UpdateSendFlags(); + mRecorder.reset(); + + InitializeRecorder(); + auto elapsedSeconds = std::chrono::duration_cast(std::chrono::steady_clock::now() - + mRecorder->mClipInfo.mActivationTime) + .count(); + mRecorder->mClipInfo.mElapsedTimeS = static_cast(elapsedSeconds); + + mRecorder->Start(); + mStreaming = true; + UpdateSendFlags(); + } } diff --git a/examples/camera-app/linux/src/uploader/pushav-uploader.cpp b/examples/camera-app/linux/src/uploader/pushav-uploader.cpp index 154aa1e09a8..0fb9056bf5f 100644 --- a/examples/camera-app/linux/src/uploader/pushav-uploader.cpp +++ b/examples/camera-app/linux/src/uploader/pushav-uploader.cpp @@ -19,8 +19,8 @@ #include "pushav-uploader.h" #include #include +#include #include -#include #include #include #include @@ -33,11 +33,29 @@ PushAVUploader::PushAVUploader() : mIsRunning(false) {} PushAVUploader::~PushAVUploader() { - // Ensure final MPD upload during uploader thread termination to persist media data before shutdown. - if (!mMPDPath.first.empty() && !mMPDPath.second.empty()) + std::pair lastUploadJob; { - ChipLogProgress(Camera, "Uploading final MPD to server before shutdown"); - UploadData(mMPDPath); + std::lock_guard lock(mQueueMutex); + while (mAvData.size() > 1) + { + mAvData.pop(); + } + + if (!mAvData.empty()) + { + lastUploadJob = std::move(mAvData.front()); + mAvData.pop(); + } + } + + if (!lastUploadJob.first.empty() && !lastUploadJob.second.empty()) + { + const std::filesystem::path filePath(lastUploadJob.first); + + if (filePath.extension() == ".mpd") + { + UploadData(lastUploadJob); + } } Stop(); @@ -80,25 +98,6 @@ std::string DerCertToPem(const std::vector & derData) return pem; } -// Helper function to convert vector of bytes to hex string representation -std::string vectorToHexString(const std::vector & vec) -{ - std::ostringstream oss; - for (size_t i = 0; i < vec.size(); ++i) - { - oss << std::hex << std::setw(2) << std::setfill('0') << static_cast(vec[i]); - if ((i + 1) % 16 == 0) - { - oss << "\n"; - } - else if (i != vec.size() - 1) - { - oss << " "; - } - } - return oss.str(); -} - // Helper function to convert ECDSA private key from DER format to PEM format std::string ConvertECDSAPrivateKey_DER_to_PEM(const std::vector & derData) { @@ -225,11 +224,11 @@ void PushAVUploader::Stop() } } -void PushAVUploader::AddUploadData(std::string & filename, std::string & url) +void PushAVUploader::AddUploadData(const std::string & filename, const std::string & url) { ChipLogProgress(Camera, "Added file name %s to queue", filename.c_str()); std::lock_guard lock(mQueueMutex); - auto data = make_pair(filename, url); + auto data = std::make_pair(filename, url); mAvData.push(data); } @@ -258,6 +257,101 @@ size_t PushAvUploadCb(void * ptr, size_t size, size_t nmemb, void * stream) return (size_t) copyChunk; } +std::string ProcessInitUploadPath(std::string path, const std::vector & streamIdNameMap) +{ + auto result = std::move(path); + // Replace stream ID placeholder #__X__# with stream name + const auto startPos = result.find("#__"); + const auto endPos = result.find("__#"); + if (startPos != std::string::npos && endPos != std::string::npos && startPos + 4 == endPos) + { + const int streamId = result[startPos + 3] - '0'; + if (streamId >= 0 && streamId < static_cast(streamIdNameMap.size())) + { + // Path traversal check - reject if stream name contains dangerous characters + if (streamIdNameMap[streamId].find("..") != std::string::npos || + streamIdNameMap[streamId].find('/') != std::string::npos) + { + ChipLogError(Camera, "Invalid stream name '%s' detected, rejecting to prevent path traversal", + streamIdNameMap[streamId].c_str()); + return path; + } + result.replace(startPos, 7, streamIdNameMap[streamId] + "/" + streamIdNameMap[streamId]); + } + else + { + ChipLogError(Camera, "Stream ID %d not found in streamIdNameMap", streamId); + return path; + } + } + ChipLogDetail(Camera, "Processed init upload path to %s", result.c_str()); + return result; +} + +std::string ProcessM4SUploadPath(std::string path, const std::vector & streamIdNameMap) +{ + auto result = std::move(path); + + // Replace stream ID placeholder #__X__# with stream name + const auto startPos = result.find("#__"); + const auto endPos = result.find("__#"); + + if (startPos != std::string::npos && endPos != std::string::npos && startPos + 4 == endPos) + { + const int streamId = result[startPos + 3] - '0'; + + if (streamId >= 0 && streamId < static_cast(streamIdNameMap.size())) + { + // Path traversal check - reject if stream name contains dangerous characters + if (streamIdNameMap[streamId].find("..") != std::string::npos || + streamIdNameMap[streamId].find('/') != std::string::npos) + { + ChipLogError(Camera, "Invalid stream name '%s' detected, rejecting to prevent path traversal", + streamIdNameMap[streamId].c_str()); + return path; + } + result.replace(startPos, 7, streamIdNameMap[streamId] + "/"); + } + else + { + return path; + } + } + + // Update segment number by adding 1000 + const auto segmentPos = result.find("segment_"); + if (segmentPos != std::string::npos) + { + const auto numberStart = segmentPos + 8; + const auto m4sPos = result.find(".m4s", numberStart); + + if (m4sPos != std::string::npos && (m4sPos - numberStart) >= 4 && (m4sPos - numberStart) <= 5) + { + const auto numberStr = result.substr(numberStart, 4); + char * endPtr; + const long originalNumber = std::strtol(numberStr.c_str(), &endPtr, 10); + + if (endPtr == numberStr.c_str() || *endPtr != '\0' || originalNumber > INT_MAX || originalNumber < INT_MIN) + { + ChipLogError(Camera, "Invalid segment number format: %s", numberStr.c_str()); + return path; + } + + auto newNumber = static_cast(originalNumber) + 1000; + if (newNumber > 9999) + { + ChipLogError(Camera, "Segment number overflow: %d", newNumber); + newNumber = 0; + } + const auto newNumberStr = std::string(4 - std::to_string(newNumber).length(), '0') + std::to_string(newNumber); + result.replace(numberStart, 4, newNumberStr); + } + } + + ChipLogDetail(Camera, "Updated M4S upload path to %s", result.c_str()); + return result; +} + void PushAVUploader::UploadData(std::pair data) { CURL * curl = curl_easy_init(); @@ -280,11 +374,18 @@ void PushAVUploader::UploadData(std::pair data) if (!file.read(buffer.data(), static_cast(size))) { ChipLogError(Camera, "Failed to read file into buffer"); + file.close(); return; } file.close(); + PushAvUploadInfo upload; upload.mData = (char *) std::malloc(size); + if (!upload.mData) + { + ChipLogError(Camera, "Failed to allocate memory for upload data"); + return; + } memcpy(upload.mData, buffer.data(), size); upload.mSize = static_cast(size); upload.mBytesRead = 0; @@ -292,46 +393,59 @@ void PushAVUploader::UploadData(std::pair data) // Determine content type based on file extension std::string contentType = "application/*"; // Default fallback - - // Extract file extension from full path - size_t dotPos = data.first.find_last_of('.'); - if (dotPos != std::string::npos) + std::string fullPath = data.first; + // Extract file extension from full path using std::filesystem + std::filesystem::path filePath(data.first); + std::filesystem::path extension = filePath.extension(); + if (extension == ".mpd") { - std::string extension = data.first.substr(dotPos); - if (extension == ".mpd") - { - contentType = "application/dash+xml"; // Manifest file - } - else if (extension == ".m4s") - { - contentType = "video/iso.segment"; // Media segment - } - else if (extension == ".init") - { - contentType = "video/mp4"; // Initialization segment - } + contentType = "application/dash+xml"; // Manifest file + } + else if (extension == ".m4s") + { + contentType = "video/iso.segment"; // Media segment + fullPath = ProcessM4SUploadPath(data.first, mStreamIdNameMap); + } + else if (extension == ".init") + { + contentType = "video/mp4"; // Initialization segment + fullPath = ProcessInitUploadPath(data.first, mStreamIdNameMap); } std::string contentTypeHeader = "Content-Type: " + contentType; headers = curl_slist_append(headers, contentTypeHeader.c_str()); // Extract the filename from the full path - std::string fullPath = data.first; - std::string filename; - if (fullPath.substr(0, 5) == "/tmp/") + std::string filename = ""; + std::string baseUrl = data.second; + std::string fullUrl; + + // Declare all variables that are used after goto cleanup + std::string rootCertPEM; + std::string clientCertPEM; + std::string derKeyToPemstr; + std::error_code ec; + size_t sessionPos; + CURLcode res; + + sessionPos = fullPath.find("/session_"); + if (sessionPos != std::string::npos) { - filename = fullPath.substr(5); + filename = fullPath.substr(sessionPos + 1); } else { - filename = fullPath; + ChipLogError(Camera, + "Invalid file path: %s. Expected to contain " + "'session_//segment_.' pattern. Skipping upload.", + fullPath.c_str()); + goto cleanup; } - std::string baseUrl = data.second; if (baseUrl.back() != '/') { baseUrl += "/"; } - std::string fullUrl = baseUrl + filename; + fullUrl = baseUrl + filename; ChipLogProgress(Camera, "Uploading file: %s to URL: %s", filename.c_str(), fullUrl.c_str()); @@ -347,8 +461,8 @@ void PushAVUploader::UploadData(std::pair data) // TODO: The logic to provide DER-formatted certificates and keys in memory (blob) format to curl is currently unstable. As a // temporary workaround, PEM-format files are being provided as input to curl. - auto rootCertPEM = DerCertToPem(mCertBuffer.mRootCertBuffer); - auto clientCertPEM = DerCertToPem(mCertBuffer.mClientCertBuffer); + rootCertPEM = DerCertToPem(mCertBuffer.mRootCertBuffer); + clientCertPEM = DerCertToPem(mCertBuffer.mClientCertBuffer); if (!mCertBuffer.mIntermediateCertBuffer.empty()) { clientCertPEM.append("\n"); // Add newline separator between certs in PEM format @@ -357,7 +471,7 @@ void PushAVUploader::UploadData(std::pair data) { clientCertPEM.append(DerCertToPem(mCertBuffer.mIntermediateCertBuffer[i]) + "\n"); } - std::string derKeyToPemstr = ConvertECDSAPrivateKey_DER_to_PEM(mCertBuffer.mClientKeyBuffer); + derKeyToPemstr = ConvertECDSAPrivateKey_DER_to_PEM(mCertBuffer.mClientKeyBuffer); SaveCertToFile(rootCertPEM, "/tmp/root.pem"); SaveCertToFile(clientCertPEM, "/tmp/dev.pem"); @@ -386,7 +500,7 @@ void PushAVUploader::UploadData(std::pair data) curl_easy_setopt(curl, CURLOPT_READFUNCTION, PushAvUploadCb); curl_easy_setopt(curl, CURLOPT_READDATA, &upload); - CURLcode res = curl_easy_perform(curl); + res = curl_easy_perform(curl); if (res != CURLE_OK) { @@ -396,6 +510,20 @@ void PushAVUploader::UploadData(std::pair data) { ChipLogDetail(Camera, "CURL uploaded file %s size: %ld", data.first.c_str(), size); } + + if (extension != ".mpd") + { + if (!std::filesystem::remove(data.first, ec)) + { + ChipLogError(Camera, "Failed to delete file: %s, error: %s", data.first.c_str(), ec.message().c_str()); + } + else + { + ChipLogDetail(Camera, "Successfully deleted file: %s", data.first.c_str()); + } + } + +cleanup: if (upload.mData) { std::free(upload.mData); diff --git a/examples/camera-app/linux/src/webrtc-libdatachannel.cpp b/examples/camera-app/linux/src/webrtc-libdatachannel.cpp index 695aa55c1a5..20bd2c4eace 100644 --- a/examples/camera-app/linux/src/webrtc-libdatachannel.cpp +++ b/examples/camera-app/linux/src/webrtc-libdatachannel.cpp @@ -281,10 +281,19 @@ class LibDataChannelTrack : public WebRTCTrack class LibDataChannelPeerConnection : public WebRTCPeerConnection { public: - LibDataChannelPeerConnection() + LibDataChannelPeerConnection(const std::vector & servers = {}) { rtc::Configuration config; - // config.iceServers.emplace_back("stun.l.google.com:19302"); + for (const auto & server : servers) + { + for (const auto & url : server.urls) + { + rtc::IceServer iceServer(url); + iceServer.username = server.username; + iceServer.password = server.credential; + config.iceServers.push_back(iceServer); + } + } mPeerConnection = std::make_shared(config); } @@ -455,7 +464,7 @@ class LibDataChannelPeerConnection : public WebRTCPeerConnection } // namespace -std::shared_ptr CreateWebRTCPeerConnection() +std::shared_ptr CreateWebRTCPeerConnection(const std::vector & iceServers) { - return std::make_shared(); + return std::make_shared(iceServers); } diff --git a/examples/camera-app/linux/src/webrtc-transport.cpp b/examples/camera-app/linux/src/webrtc-transport.cpp index bc60db7c49e..7a21cb64d0c 100644 --- a/examples/camera-app/linux/src/webrtc-transport.cpp +++ b/examples/camera-app/linux/src/webrtc-transport.cpp @@ -41,7 +41,7 @@ SDPType RtcTypeToSDPType(rtc::Description::Type type) WebrtcTransport::WebrtcTransport() { ChipLogProgress(Camera, "WebrtcTransport created"); - mRequestArgs = { 0, 0, 0, 0, 0, 0 }; // Initialize request arguments to zero + mRequestArgs = {}; // Default initialize request arguments } WebrtcTransport::~WebrtcTransport() @@ -62,6 +62,11 @@ void WebrtcTransport::SetRequestArgs(const RequestArgs & args) mRequestArgs = args; } +void WebrtcTransport::SetICEServers(const std::vector & servers) +{ + mICEServers = servers; +} + WebrtcTransport::RequestArgs & WebrtcTransport::GetRequestArgs() { return mRequestArgs; @@ -69,8 +74,34 @@ WebrtcTransport::RequestArgs & WebrtcTransport::GetRequestArgs() void WebrtcTransport::SendVideo(const chip::ByteSpan & data, int64_t timestamp, uint16_t videoStreamID) { + std::lock_guard lock(mTrackStatusLock); if (mLocalVideoTrack) { + // TODO: Implement SFrame encryption HERE (per-transport, during RTP packetization) + // Current state: data contains raw H.264 encoded frames from GStreamer + // + // SFrame encryption should happen here because: + // 1. Each transport may have different sFrameConfig (different keys, cipher suites) + // 2. Multiple transports can share the same video stream + // 3. Encryption must be per-client, not per-stream + // + // Implementation steps: + // if (sFrameConfig.HasValue()) + // { + // auto& config = sFrameConfig.Value(); + // // 1. Encrypt H.264 payload using config.baseKey and config.cipherSuite: + // // - 0x0001: AES-128-GCM-SHA256 (16 byte key) + // // - 0x0002: AES-256-GCM-SHA512 (32 byte key) + // // 2. Build SFrame header with config.kid and frame counter + // // 3. Prepend SFrame header to encrypted payload + // // 4. Pass encrypted data to RTP packetization + // // Result: [RTP Header | SFrame Header | Encrypted(H.264)] + // } + // else + // { + // // No encryption - pass raw H.264 to RTP packetization + // } + mLocalVideoTrack->SendFrame(data, timestamp); } } @@ -78,8 +109,34 @@ void WebrtcTransport::SendVideo(const chip::ByteSpan & data, int64_t timestamp, // Implementation of SendAudio method void WebrtcTransport::SendAudio(const chip::ByteSpan & data, int64_t timestamp, uint16_t audioStreamID) { + std::lock_guard lock(mTrackStatusLock); if (mLocalAudioTrack) { + // TODO: Implement SFrame encryption HERE (per-transport, during RTP packetization) + // Current state: data contains raw Opus encoded frames from GStreamer + // + // SFrame encryption should happen here because: + // 1. Each transport may have different sFrameConfig (different keys, cipher suites) + // 2. Multiple transports can share the same audio stream + // 3. Encryption must be per-client, not per-stream + // + // Implementation steps: + // if (sFrameConfig.HasValue()) + // { + // auto& config = sFrameConfig.Value(); + // // 1. Encrypt Opus payload using config.baseKey and config.cipherSuite: + // // - 0x0001: AES-128-GCM-SHA256 (16 byte key) + // // - 0x0002: AES-256-GCM-SHA512 (32 byte key) + // // 2. Build SFrame header with config.kid and frame counter + // // 3. Prepend SFrame header to encrypted payload + // // 4. Pass encrypted data to RTP packetization + // // Result: [RTP Header | SFrame Header | Encrypted(Opus)] + // } + // else + // { + // // No encryption - pass raw Opus to RTP packetization + // } + mLocalAudioTrack->SendFrame(data, timestamp); } } @@ -143,7 +200,7 @@ void WebrtcTransport::Start() return; } - mPeerConnection = CreateWebRTCPeerConnection(); + mPeerConnection = CreateWebRTCPeerConnection(mICEServers); mPeerConnection->SetCallbacks([this](const std::string & sdp, SDPType type) { this->OnLocalDescription(sdp, type); }, [this](const ICECandidateInfo & candidateInfo) { this->OnICECandidate(candidateInfo); }, @@ -153,6 +210,7 @@ void WebrtcTransport::Start() void WebrtcTransport::Stop() { + std::lock_guard lock(mTrackStatusLock); if (mPeerConnection != nullptr) { mPeerConnection->Close(); @@ -198,6 +256,7 @@ void WebrtcTransport::OnLocalDescription(const std::string & sdp, SDPType type) bool WebrtcTransport::ClosePeerConnection() { + std::lock_guard lock(mTrackStatusLock); if (mPeerConnection == nullptr) { return false; diff --git a/examples/camera-controller/webrtc-manager/WebRTCManager.cpp b/examples/camera-controller/webrtc-manager/WebRTCManager.cpp index bacec668357..f81dd08a468 100644 --- a/examples/camera-controller/webrtc-manager/WebRTCManager.cpp +++ b/examples/camera-controller/webrtc-manager/WebRTCManager.cpp @@ -111,11 +111,11 @@ void WebRTCManager::Init() } } -CHIP_ERROR WebRTCManager::HandleOffer(uint16_t sessionId, const WebRTCRequestorDelegate::OfferArgs & args) +CHIP_ERROR WebRTCManager::HandleOffer(const WebRTCSessionStruct & session, const WebRTCRequestorDelegate::OfferArgs & args) { ChipLogProgress(Camera, "WebRTCManager::HandleOffer"); - mWebRTCProviderClient.HandleOfferReceived(sessionId); + mWebRTCProviderClient.HandleOfferReceived(session.id); if (!mPeerConnection) { @@ -132,7 +132,7 @@ CHIP_ERROR WebRTCManager::HandleOffer(uint16_t sessionId, const WebRTCRequestorD } // Store sessionId for the delayed callback - mPendingSessionId = sessionId; + mPendingSessionId = session.id; // Schedule the ProvideAnswer() call to run with a small delay to ensure the response is sent first DeviceLayer::SystemLayer().StartTimer( @@ -146,11 +146,11 @@ CHIP_ERROR WebRTCManager::HandleOffer(uint16_t sessionId, const WebRTCRequestorD return CHIP_NO_ERROR; } -CHIP_ERROR WebRTCManager::HandleAnswer(uint16_t sessionId, const std::string & sdp) +CHIP_ERROR WebRTCManager::HandleAnswer(const WebRTCSessionStruct & session, const std::string & sdp) { ChipLogProgress(Camera, "WebRTCManager::HandleAnswer"); - mWebRTCProviderClient.HandleAnswerReceived(sessionId); + mWebRTCProviderClient.HandleAnswerReceived(session.id); if (!mPeerConnection) { @@ -162,7 +162,7 @@ CHIP_ERROR WebRTCManager::HandleAnswer(uint16_t sessionId, const std::string & s mPeerConnection->setRemoteDescription(answerDesc); // Store sessionId for the delayed callback - mPendingSessionId = sessionId; + mPendingSessionId = session.id; // Schedule the ProvideICECandidates() call to run with a small delay to ensure the response is sent first DeviceLayer::SystemLayer().StartTimer( @@ -176,7 +176,8 @@ CHIP_ERROR WebRTCManager::HandleAnswer(uint16_t sessionId, const std::string & s return CHIP_NO_ERROR; } -CHIP_ERROR WebRTCManager::HandleICECandidates(uint16_t sessionId, const std::vector & candidates) +CHIP_ERROR WebRTCManager::HandleICECandidates(const WebRTCSessionStruct & session, + const std::vector & candidates) { ChipLogProgress(Camera, "WebRTCManager::HandleICECandidates"); diff --git a/examples/camera-controller/webrtc-manager/WebRTCManager.h b/examples/camera-controller/webrtc-manager/WebRTCManager.h index df74357409d..63a7a244fd3 100644 --- a/examples/camera-controller/webrtc-manager/WebRTCManager.h +++ b/examples/camera-controller/webrtc-manager/WebRTCManager.h @@ -37,6 +37,7 @@ class WebRTCManager { public: using ICECandidateStruct = chip::app::Clusters::Globals::Structs::ICECandidateStruct::Type; + using WebRTCSessionStruct = chip::app::Clusters::Globals::Structs::WebRTCSessionStruct::Type; using StreamUsageEnum = chip::app::Clusters::Globals::StreamUsageEnum; using SessionEstablishedCallback = std::function; @@ -55,11 +56,11 @@ class WebRTCManager */ void SetSessionEstablishedCallback(SessionEstablishedCallback callback) { mSessionEstablishedCallback = callback; } - CHIP_ERROR HandleOffer(uint16_t sessionId, const WebRTCRequestorDelegate::OfferArgs & args); + CHIP_ERROR HandleOffer(const WebRTCSessionStruct & session, const WebRTCRequestorDelegate::OfferArgs & args); - CHIP_ERROR HandleAnswer(uint16_t sessionId, const std::string & sdp); + CHIP_ERROR HandleAnswer(const WebRTCSessionStruct & session, const std::string & sdp); - CHIP_ERROR HandleICECandidates(uint16_t sessionId, const std::vector & candidates); + CHIP_ERROR HandleICECandidates(const WebRTCSessionStruct & session, const std::vector & candidates); CHIP_ERROR Connnect(chip::Controller::DeviceCommissioner & commissioner, chip::NodeId nodeId, chip::EndpointId endpointId); @@ -83,7 +84,7 @@ class WebRTCManager WebRTCManager(); ~WebRTCManager(); - chip::app::LazyRegisteredServerCluster + chip::app::LazyRegisteredServerCluster mWebRTCRegisteredServerCluster; WebRTCProviderClient mWebRTCProviderClient; diff --git a/examples/camera-controller/webrtc-manager/WebRTCProviderClient.cpp b/examples/camera-controller/webrtc-manager/WebRTCProviderClient.cpp index 2320775c596..32b0d3f8782 100644 --- a/examples/camera-controller/webrtc-manager/WebRTCProviderClient.cpp +++ b/examples/camera-controller/webrtc-manager/WebRTCProviderClient.cpp @@ -32,7 +32,7 @@ constexpr uint32_t kDeferredOfferTimeoutSeconds = 30; } // namespace void WebRTCProviderClient::Init(const ScopedNodeId & peerId, EndpointId endpointId, - Clusters::WebRTCTransportRequestor::WebRTCTransportRequestorServer * requestorServer) + Clusters::WebRTCTransportRequestor::WebRTCTransportRequestorCluster * requestorServer) { mPeerId = peerId; mEndpointId = endpointId; @@ -402,7 +402,7 @@ void WebRTCProviderClient::OnSessionEstablishTimeout(chip::System::Layer * syste if (self->mCurrentSessionId != 0) { - self->mRequestorServer->RemoveSession(self->mCurrentSessionId); + self->mRequestorServer->RemoveSession(self->mCurrentSessionId, self->mPeerId.GetNodeId(), self->mPeerId.GetFabricIndex()); self->mCurrentSessionId = 0; } diff --git a/examples/camera-controller/webrtc-manager/WebRTCProviderClient.h b/examples/camera-controller/webrtc-manager/WebRTCProviderClient.h index 23668ef19c0..e649e9bdd68 100644 --- a/examples/camera-controller/webrtc-manager/WebRTCProviderClient.h +++ b/examples/camera-controller/webrtc-manager/WebRTCProviderClient.h @@ -20,7 +20,7 @@ #include #include -#include +#include #include // Forward declaration @@ -50,14 +50,14 @@ class WebRTCProviderClient : public chip::app::CommandSender::Callback /** * @brief Initializes the WebRTCProviderClient with a ScopedNodeId, an EndpointId, and an optional - * pointer to the WebRTCTransportRequestorServer. + * pointer to the WebRTCTransportRequestorCluster. * * @param peerId The PeerId (fabric + nodeId) for the remote device. * @param endpointId The Matter endpoint on the remote device for WebRTCTransportProvider cluster. - * @param requestorServer Pointer to a WebRTCTransportRequestorServer instance. + * @param requestorServer Pointer to a WebRTCTransportRequestorCluster instance. */ void Init(const chip::ScopedNodeId & peerId, chip::EndpointId endpointId, - chip::app::Clusters::WebRTCTransportRequestor::WebRTCTransportRequestorServer * requestorServer); + chip::app::Clusters::WebRTCTransportRequestor::WebRTCTransportRequestorCluster * requestorServer); /** * @brief Sends a SolicitOffer command to the remote device. @@ -221,7 +221,7 @@ class WebRTCProviderClient : public chip::app::CommandSender::Callback State mState = State::Idle; - chip::app::Clusters::WebRTCTransportRequestor::WebRTCTransportRequestorServer * mRequestorServer = nullptr; + chip::app::Clusters::WebRTCTransportRequestor::WebRTCTransportRequestorCluster * mRequestorServer = nullptr; // Data needed to send the WebRTCTransportProvider commands chip::app::Clusters::WebRTCTransportProvider::Commands::SolicitOffer::Type mSolicitOfferData; diff --git a/examples/camera-controller/webrtc-manager/WebRTCRequestorDelegate.cpp b/examples/camera-controller/webrtc-manager/WebRTCRequestorDelegate.cpp index a3c6fd9dd43..e5196a88d6d 100644 --- a/examples/camera-controller/webrtc-manager/WebRTCRequestorDelegate.cpp +++ b/examples/camera-controller/webrtc-manager/WebRTCRequestorDelegate.cpp @@ -26,25 +26,26 @@ using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::app::Clusters::WebRTCTransportRequestor; -CHIP_ERROR WebRTCRequestorDelegate::HandleOffer(uint16_t sessionId, const OfferArgs & args) +CHIP_ERROR WebRTCRequestorDelegate::HandleOffer(const WebRTCSessionStruct & session, const OfferArgs & args) { ChipLogProgress(Camera, "WebRTCRequestorDelegate::HandleOffer"); - return WebRTCManager::Instance().HandleOffer(sessionId, args); + return WebRTCManager::Instance().HandleOffer(session, args); } -CHIP_ERROR WebRTCRequestorDelegate::HandleAnswer(uint16_t sessionId, const std::string & sdpAnswer) +CHIP_ERROR WebRTCRequestorDelegate::HandleAnswer(const WebRTCSessionStruct & session, const std::string & sdpAnswer) { ChipLogProgress(Camera, "WebRTCRequestorDelegate::HandleAnswer"); - return WebRTCManager::Instance().HandleAnswer(sessionId, sdpAnswer); + return WebRTCManager::Instance().HandleAnswer(session, sdpAnswer); } -CHIP_ERROR WebRTCRequestorDelegate::HandleICECandidates(uint16_t sessionId, const std::vector & candidates) +CHIP_ERROR WebRTCRequestorDelegate::HandleICECandidates(const WebRTCSessionStruct & session, + const std::vector & candidates) { ChipLogProgress(Camera, "WebRTCRequestorDelegate::HandleICECandidates"); - return WebRTCManager::Instance().HandleICECandidates(sessionId, candidates); + return WebRTCManager::Instance().HandleICECandidates(session, candidates); } -CHIP_ERROR WebRTCRequestorDelegate::HandleEnd(uint16_t sessionId, WebRTCEndReasonEnum reasonCode) +CHIP_ERROR WebRTCRequestorDelegate::HandleEnd(const WebRTCSessionStruct & session, WebRTCEndReasonEnum reasonCode) { ChipLogProgress(Camera, "WebRTCRequestorDelegate::HandleEnd"); return CHIP_NO_ERROR; diff --git a/examples/camera-controller/webrtc-manager/WebRTCRequestorDelegate.h b/examples/camera-controller/webrtc-manager/WebRTCRequestorDelegate.h index 635a6076028..4d5279df434 100644 --- a/examples/camera-controller/webrtc-manager/WebRTCRequestorDelegate.h +++ b/examples/camera-controller/webrtc-manager/WebRTCRequestorDelegate.h @@ -19,22 +19,24 @@ #pragma once #include -#include +#include class WebRTCRequestorDelegate : public chip::app::Clusters::WebRTCTransportRequestor::Delegate { public: using ICECandidateStruct = chip::app::Clusters::Globals::Structs::ICECandidateStruct::Type; + using WebRTCSessionStruct = chip::app::Clusters::Globals::Structs::WebRTCSessionStruct::Type; using WebRTCEndReasonEnum = chip::app::Clusters::Globals::WebRTCEndReasonEnum; WebRTCRequestorDelegate() = default; ~WebRTCRequestorDelegate() = default; - CHIP_ERROR HandleOffer(uint16_t sessionId, const OfferArgs & args) override; + CHIP_ERROR HandleOffer(const WebRTCSessionStruct & session, const OfferArgs & args) override; - CHIP_ERROR HandleAnswer(uint16_t sessionId, const std::string & sdpAnswer) override; + CHIP_ERROR HandleAnswer(const WebRTCSessionStruct & session, const std::string & sdpAnswer) override; - CHIP_ERROR HandleICECandidates(uint16_t sessionId, const std::vector & candidates) override; + CHIP_ERROR HandleICECandidates(const WebRTCSessionStruct & session, + const std::vector & candidates) override; - CHIP_ERROR HandleEnd(uint16_t sessionId, WebRTCEndReasonEnum reasonCode) override; + CHIP_ERROR HandleEnd(const WebRTCSessionStruct & session, WebRTCEndReasonEnum reasonCode) override; }; diff --git a/examples/chef/ameba/main/chipinterface.cpp b/examples/chef/ameba/main/chipinterface.cpp index a83a89e2a82..314326cb197 100755 --- a/examples/chef/ameba/main/chipinterface.cpp +++ b/examples/chef/ameba/main/chipinterface.cpp @@ -100,11 +100,9 @@ static void InitServer(intptr_t context) static AmebaObserver sAmebaObserver; initParams.appDelegate = &sAmebaObserver; - + chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); chip::Server::GetInstance().Init(initParams); - gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); - chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); NetWorkCommissioningInstInit(); diff --git a/examples/chef/devices/icd_rootnode_contactsensor_ed3b19ec55.matter b/examples/chef/devices/icd_rootnode_contactsensor_ed3b19ec55.matter index 78d7dfbcc13..6792947fe2f 100644 --- a/examples/chef/devices/icd_rootnode_contactsensor_ed3b19ec55.matter +++ b/examples/chef/devices/icd_rootnode_contactsensor_ed3b19ec55.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/noip_rootnode_dimmablelight_bCwGYSDpoe.matter b/examples/chef/devices/noip_rootnode_dimmablelight_bCwGYSDpoe.matter index 2e9259bee0f..0c35dfe782e 100644 --- a/examples/chef/devices/noip_rootnode_dimmablelight_bCwGYSDpoe.matter +++ b/examples/chef/devices/noip_rootnode_dimmablelight_bCwGYSDpoe.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter b/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter index 0bc75c2cb08..df48b41ea67 100644 --- a/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter +++ b/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } 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 58935a3878b..9fd949e7999 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 @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.matter b/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.matter index 118db2580ef..a1db7d9b5bd 100644 --- a/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.matter +++ b/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_basicvideoplayer_0ff86e943b.matter b/examples/chef/devices/rootnode_basicvideoplayer_0ff86e943b.matter index 9bf6b79a868..30484021d2b 100644 --- a/examples/chef/devices/rootnode_basicvideoplayer_0ff86e943b.matter +++ b/examples/chef/devices/rootnode_basicvideoplayer_0ff86e943b.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_colortemperaturelight_hbUnzYVeyn.matter b/examples/chef/devices/rootnode_colortemperaturelight_hbUnzYVeyn.matter index 435bbe50e7d..60be7ef8f2b 100644 --- a/examples/chef/devices/rootnode_colortemperaturelight_hbUnzYVeyn.matter +++ b/examples/chef/devices/rootnode_colortemperaturelight_hbUnzYVeyn.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_contactsensor_27f76aeaf5.matter b/examples/chef/devices/rootnode_contactsensor_27f76aeaf5.matter index 1ff8368f8f8..d651ec84277 100644 --- a/examples/chef/devices/rootnode_contactsensor_27f76aeaf5.matter +++ b/examples/chef/devices/rootnode_contactsensor_27f76aeaf5.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_contactsensor_lFAGG1bfRO.matter b/examples/chef/devices/rootnode_contactsensor_lFAGG1bfRO.matter index de9e8d19652..98fdee977e8 100644 --- a/examples/chef/devices/rootnode_contactsensor_lFAGG1bfRO.matter +++ b/examples/chef/devices/rootnode_contactsensor_lFAGG1bfRO.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.matter b/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.matter index 4f7e61ba3ce..6d257c9b631 100644 --- a/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.matter +++ b/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_cooktop_cooksurface_d3c174cc88.matter b/examples/chef/devices/rootnode_cooktop_cooksurface_d3c174cc88.matter index 71f0cd99c34..11a3e0ff811 100644 --- a/examples/chef/devices/rootnode_cooktop_cooksurface_d3c174cc88.matter +++ b/examples/chef/devices/rootnode_cooktop_cooksurface_d3c174cc88.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_dimmablelight_bCwGYSDpoe.matter b/examples/chef/devices/rootnode_dimmablelight_bCwGYSDpoe.matter index 928b3e26983..d31742a0dcb 100644 --- a/examples/chef/devices/rootnode_dimmablelight_bCwGYSDpoe.matter +++ b/examples/chef/devices/rootnode_dimmablelight_bCwGYSDpoe.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_dimmablepluginunit_f8a9a0b9d4.matter b/examples/chef/devices/rootnode_dimmablepluginunit_f8a9a0b9d4.matter index 75985d9c819..60d925062d7 100644 --- a/examples/chef/devices/rootnode_dimmablepluginunit_f8a9a0b9d4.matter +++ b/examples/chef/devices/rootnode_dimmablepluginunit_f8a9a0b9d4.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_dishwasher_cc105034fe.matter b/examples/chef/devices/rootnode_dishwasher_cc105034fe.matter index ed03193bdcb..a0ca8529dd5 100644 --- a/examples/chef/devices/rootnode_dishwasher_cc105034fe.matter +++ b/examples/chef/devices/rootnode_dishwasher_cc105034fe.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter b/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter index 9e88321e70c..458746e6e05 100644 --- a/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter +++ b/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_extendedcolorlight_8lcaaYJVAa.matter b/examples/chef/devices/rootnode_extendedcolorlight_8lcaaYJVAa.matter index c5d4ac9d3bc..79c1c1dcd2c 100644 --- a/examples/chef/devices/rootnode_extendedcolorlight_8lcaaYJVAa.matter +++ b/examples/chef/devices/rootnode_extendedcolorlight_8lcaaYJVAa.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_extractorhood_0359bf807d.matter b/examples/chef/devices/rootnode_extractorhood_0359bf807d.matter index 45a3f20c2e3..4217b74bf10 100644 --- a/examples/chef/devices/rootnode_extractorhood_0359bf807d.matter +++ b/examples/chef/devices/rootnode_extractorhood_0359bf807d.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter b/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter index 615f6fb14d6..05bd7723e30 100644 --- a/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter +++ b/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_flowsensor_1zVxHedlaV.matter b/examples/chef/devices/rootnode_flowsensor_1zVxHedlaV.matter index b2a550ef310..f17206e6dea 100644 --- a/examples/chef/devices/rootnode_flowsensor_1zVxHedlaV.matter +++ b/examples/chef/devices/rootnode_flowsensor_1zVxHedlaV.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_genericswitch_2dfff6e516.matter b/examples/chef/devices/rootnode_genericswitch_2dfff6e516.matter index a95e9fc0792..372edffeace 100644 --- a/examples/chef/devices/rootnode_genericswitch_2dfff6e516.matter +++ b/examples/chef/devices/rootnode_genericswitch_2dfff6e516.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_genericswitch_9866e35d0b.matter b/examples/chef/devices/rootnode_genericswitch_9866e35d0b.matter index db8fb9542c8..27f77732e87 100644 --- a/examples/chef/devices/rootnode_genericswitch_9866e35d0b.matter +++ b/examples/chef/devices/rootnode_genericswitch_9866e35d0b.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_heatpump_87ivjRAECh.matter b/examples/chef/devices/rootnode_heatpump_87ivjRAECh.matter index fe1b85b8b39..2226fec39ae 100644 --- a/examples/chef/devices/rootnode_heatpump_87ivjRAECh.matter +++ b/examples/chef/devices/rootnode_heatpump_87ivjRAECh.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_humiditysensor_Xyj4gda6Hb.matter b/examples/chef/devices/rootnode_humiditysensor_Xyj4gda6Hb.matter index 0afec52cf25..c78f24041e2 100644 --- a/examples/chef/devices/rootnode_humiditysensor_Xyj4gda6Hb.matter +++ b/examples/chef/devices/rootnode_humiditysensor_Xyj4gda6Hb.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_laundrydryer_01796fe396.matter b/examples/chef/devices/rootnode_laundrydryer_01796fe396.matter index c67e2f7c195..e23b988912a 100644 --- a/examples/chef/devices/rootnode_laundrydryer_01796fe396.matter +++ b/examples/chef/devices/rootnode_laundrydryer_01796fe396.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_laundrywasher_fb10d238c8.matter b/examples/chef/devices/rootnode_laundrywasher_fb10d238c8.matter index 435d214daf9..be66864c15b 100644 --- a/examples/chef/devices/rootnode_laundrywasher_fb10d238c8.matter +++ b/examples/chef/devices/rootnode_laundrywasher_fb10d238c8.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_lightsensor_lZQycTFcJK.matter b/examples/chef/devices/rootnode_lightsensor_lZQycTFcJK.matter index 1c747260739..1d81ea70160 100644 --- a/examples/chef/devices/rootnode_lightsensor_lZQycTFcJK.matter +++ b/examples/chef/devices/rootnode_lightsensor_lZQycTFcJK.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_microwaveoven_37420684d3.matter b/examples/chef/devices/rootnode_microwaveoven_37420684d3.matter index 35d121bae6b..1a9ffeb0253 100644 --- a/examples/chef/devices/rootnode_microwaveoven_37420684d3.matter +++ b/examples/chef/devices/rootnode_microwaveoven_37420684d3.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_mounteddimmableloadcontrol_a9a1a87f2d.matter b/examples/chef/devices/rootnode_mounteddimmableloadcontrol_a9a1a87f2d.matter index 7411783f25d..d3a91588b06 100644 --- a/examples/chef/devices/rootnode_mounteddimmableloadcontrol_a9a1a87f2d.matter +++ b/examples/chef/devices/rootnode_mounteddimmableloadcontrol_a9a1a87f2d.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_mountedonoffcontrol_ec30c757a6.matter b/examples/chef/devices/rootnode_mountedonoffcontrol_ec30c757a6.matter index d16631ef261..fdb12586a7c 100644 --- a/examples/chef/devices/rootnode_mountedonoffcontrol_ec30c757a6.matter +++ b/examples/chef/devices/rootnode_mountedonoffcontrol_ec30c757a6.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_occupancysensor_iHyVgifZuo.matter b/examples/chef/devices/rootnode_occupancysensor_iHyVgifZuo.matter index 9875789237f..4a4d76cd480 100644 --- a/examples/chef/devices/rootnode_occupancysensor_iHyVgifZuo.matter +++ b/examples/chef/devices/rootnode_occupancysensor_iHyVgifZuo.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_onofflight_bbs1b7IaOV.matter b/examples/chef/devices/rootnode_onofflight_bbs1b7IaOV.matter index 5d7a4acecdd..ad2351a4706 100644 --- a/examples/chef/devices/rootnode_onofflight_bbs1b7IaOV.matter +++ b/examples/chef/devices/rootnode_onofflight_bbs1b7IaOV.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_onofflight_samplemei.matter b/examples/chef/devices/rootnode_onofflight_samplemei.matter index f97aa47f594..c9b9c22eb82 100644 --- a/examples/chef/devices/rootnode_onofflight_samplemei.matter +++ b/examples/chef/devices/rootnode_onofflight_samplemei.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_onofflightswitch_FsPlMr090Q.matter b/examples/chef/devices/rootnode_onofflightswitch_FsPlMr090Q.matter index 95339d678f2..b5e9d79d046 100644 --- a/examples/chef/devices/rootnode_onofflightswitch_FsPlMr090Q.matter +++ b/examples/chef/devices/rootnode_onofflightswitch_FsPlMr090Q.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_onoffpluginunit_Wtf8ss5EBY.matter b/examples/chef/devices/rootnode_onoffpluginunit_Wtf8ss5EBY.matter index 72355a5135b..d381eceec5b 100644 --- a/examples/chef/devices/rootnode_onoffpluginunit_Wtf8ss5EBY.matter +++ b/examples/chef/devices/rootnode_onoffpluginunit_Wtf8ss5EBY.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_oven_temperaturecontrolledcabinet_cooktop_cooksurface_738dd18832.matter b/examples/chef/devices/rootnode_oven_temperaturecontrolledcabinet_cooktop_cooksurface_738dd18832.matter index 312d24a7811..3bbc64a853e 100644 --- a/examples/chef/devices/rootnode_oven_temperaturecontrolledcabinet_cooktop_cooksurface_738dd18832.matter +++ b/examples/chef/devices/rootnode_oven_temperaturecontrolledcabinet_cooktop_cooksurface_738dd18832.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_pressuresensor_s0qC9wLH4k.matter b/examples/chef/devices/rootnode_pressuresensor_s0qC9wLH4k.matter index fdc8bdbaa57..6f94325c394 100644 --- a/examples/chef/devices/rootnode_pressuresensor_s0qC9wLH4k.matter +++ b/examples/chef/devices/rootnode_pressuresensor_s0qC9wLH4k.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_pump_5f904818cc.matter b/examples/chef/devices/rootnode_pump_5f904818cc.matter index 596397336eb..67fa5889f2f 100644 --- a/examples/chef/devices/rootnode_pump_5f904818cc.matter +++ b/examples/chef/devices/rootnode_pump_5f904818cc.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_rainsensor_a7aa5d7738.matter b/examples/chef/devices/rootnode_rainsensor_a7aa5d7738.matter index 10e81b6138a..832b5073e83 100644 --- a/examples/chef/devices/rootnode_rainsensor_a7aa5d7738.matter +++ b/examples/chef/devices/rootnode_rainsensor_a7aa5d7738.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_refrigerator_temperaturecontrolledcabinet_temperaturecontrolledcabinet_ffdb696680.matter b/examples/chef/devices/rootnode_refrigerator_temperaturecontrolledcabinet_temperaturecontrolledcabinet_ffdb696680.matter index 003d569598e..ba20a881995 100644 --- a/examples/chef/devices/rootnode_refrigerator_temperaturecontrolledcabinet_temperaturecontrolledcabinet_ffdb696680.matter +++ b/examples/chef/devices/rootnode_refrigerator_temperaturecontrolledcabinet_temperaturecontrolledcabinet_ffdb696680.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_roboticvacuumcleaner_1807ff0c49.matter b/examples/chef/devices/rootnode_roboticvacuumcleaner_1807ff0c49.matter index 1aa1709bc64..7ca03d8b887 100644 --- a/examples/chef/devices/rootnode_roboticvacuumcleaner_1807ff0c49.matter +++ b/examples/chef/devices/rootnode_roboticvacuumcleaner_1807ff0c49.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_roomairconditioner_9cf3607804.matter b/examples/chef/devices/rootnode_roomairconditioner_9cf3607804.matter index 20de8050e00..43bd698b5b0 100644 --- a/examples/chef/devices/rootnode_roomairconditioner_9cf3607804.matter +++ b/examples/chef/devices/rootnode_roomairconditioner_9cf3607804.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_smokecoalarm_686fe0dcb8.matter b/examples/chef/devices/rootnode_smokecoalarm_686fe0dcb8.matter index 6354ef0f2e2..d1a6c8b61d0 100644 --- a/examples/chef/devices/rootnode_smokecoalarm_686fe0dcb8.matter +++ b/examples/chef/devices/rootnode_smokecoalarm_686fe0dcb8.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_speaker_RpzeXdimqA.matter b/examples/chef/devices/rootnode_speaker_RpzeXdimqA.matter index db698723e91..48d5db992dd 100644 --- a/examples/chef/devices/rootnode_speaker_RpzeXdimqA.matter +++ b/examples/chef/devices/rootnode_speaker_RpzeXdimqA.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_temperaturesensor_Qy1zkNW7c3.matter b/examples/chef/devices/rootnode_temperaturesensor_Qy1zkNW7c3.matter index 1157fdbab27..eb6066b8563 100644 --- a/examples/chef/devices/rootnode_temperaturesensor_Qy1zkNW7c3.matter +++ b/examples/chef/devices/rootnode_temperaturesensor_Qy1zkNW7c3.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter b/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter index 9a8aeb6332c..840c591893c 100644 --- a/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter +++ b/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_waterfreezedetector_dd94a13a16.matter b/examples/chef/devices/rootnode_waterfreezedetector_dd94a13a16.matter index f32585da188..f20d608fa4f 100644 --- a/examples/chef/devices/rootnode_waterfreezedetector_dd94a13a16.matter +++ b/examples/chef/devices/rootnode_waterfreezedetector_dd94a13a16.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_waterleakdetector_0b067acfa3.matter b/examples/chef/devices/rootnode_waterleakdetector_0b067acfa3.matter index 27c9d3f5c08..47bf3b63bd0 100644 --- a/examples/chef/devices/rootnode_waterleakdetector_0b067acfa3.matter +++ b/examples/chef/devices/rootnode_waterleakdetector_0b067acfa3.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_watervalve_6bb39f1f67.matter b/examples/chef/devices/rootnode_watervalve_6bb39f1f67.matter index 89cb3a40760..42838435c53 100644 --- a/examples/chef/devices/rootnode_watervalve_6bb39f1f67.matter +++ b/examples/chef/devices/rootnode_watervalve_6bb39f1f67.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chef/devices/rootnode_windowcovering_RLCxaGi9Yx.matter b/examples/chef/devices/rootnode_windowcovering_RLCxaGi9Yx.matter index 4737bb25624..6a44a561b14 100644 --- a/examples/chef/devices/rootnode_windowcovering_RLCxaGi9Yx.matter +++ b/examples/chef/devices/rootnode_windowcovering_RLCxaGi9Yx.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/chip-tool/commands/common/CHIPCommand.cpp b/examples/chip-tool/commands/common/CHIPCommand.cpp index 44a4179472a..a8edf1de71a 100644 --- a/examples/chip-tool/commands/common/CHIPCommand.cpp +++ b/examples/chip-tool/commands/common/CHIPCommand.cpp @@ -477,7 +477,7 @@ CHIP_ERROR CHIPCommand::InitializeCommissioner(CommissionerIdentity & identity, #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY VerifyOrReturnError(chip::CanCastTo(CHIP_UDC_PORT + fabricId), CHIP_ERROR_INVALID_ARGUMENT); uint16_t udcListenPort = static_cast(CHIP_UDC_PORT + fabricId); - commissioner->SetUdcListenPort(udcListenPort); + ReturnErrorOnFailure(commissioner->SetUdcListenPort(udcListenPort)); #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY chip::Controller::SetupParams commissionerParams; @@ -545,7 +545,7 @@ CHIP_ERROR CHIPCommand::InitializeCommissioner(CommissionerIdentity & identity, chip::Credentials::SetSingleIpkEpochKey(&sGroupDataProvider, fabricIndex, defaultIpk, compressed_fabric_id_span)); } - CHIPCommand::sICDClientStorage.UpdateFabricList(commissioner->GetFabricIndex()); + ReturnErrorOnFailure(CHIPCommand::sICDClientStorage.UpdateFabricList(commissioner->GetFabricIndex())); mCommissioners[identity] = std::move(commissioner); diff --git a/examples/chip-tool/commands/common/Commands.cpp b/examples/chip-tool/commands/common/Commands.cpp index 6a815f98e89..8f79db2d636 100644 --- a/examples/chip-tool/commands/common/Commands.cpp +++ b/examples/chip-tool/commands/common/Commands.cpp @@ -64,7 +64,7 @@ template ::value, int> = 0> static void UseStorageDirectory(T & storageManagerImpl, const char * storageDirectory) { std::string platformKVS = std::string(storageDirectory) + "/chip_tool_kvs"; - storageManagerImpl.Init(platformKVS.c_str()); + TEMPORARY_RETURN_IGNORED storageManagerImpl.Init(platformKVS.c_str()); } template ::value, int> = 0> diff --git a/examples/chip-tool/commands/icd/ICDCommand.cpp b/examples/chip-tool/commands/icd/ICDCommand.cpp index a66192e48bf..146fefe19df 100644 --- a/examples/chip-tool/commands/icd/ICDCommand.cpp +++ b/examples/chip-tool/commands/icd/ICDCommand.cpp @@ -57,11 +57,13 @@ CHIP_ERROR ICDListCommand::RunCommand() 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); + TEMPORARY_RETURN_IGNORED 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); - Encoding::BytesToHex(info.hmac_key_handle.As(), Crypto::kHMAC_CCM128_Key_Length, - icdHmacKeyHex, sizeof(icdHmacKeyHex), chip::Encoding::HexFlags::kNullTerminate); + TEMPORARY_RETURN_IGNORED 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); } diff --git a/examples/chip-tool/commands/interactive/InteractiveCommands.cpp b/examples/chip-tool/commands/interactive/InteractiveCommands.cpp index 7c843cc900b..871d078a4e8 100644 --- a/examples/chip-tool/commands/interactive/InteractiveCommands.cpp +++ b/examples/chip-tool/commands/interactive/InteractiveCommands.cpp @@ -107,7 +107,8 @@ struct InteractiveServerResult if (mIsAsyncReport && mTimeout) { - chip::DeviceLayer::PlatformMgr().ScheduleWork(StartAsyncTimeout, reinterpret_cast(this)); + TEMPORARY_RETURN_IGNORED chip::DeviceLayer::PlatformMgr().ScheduleWork(StartAsyncTimeout, + reinterpret_cast(this)); } } @@ -117,7 +118,8 @@ struct InteractiveServerResult if (mIsAsyncReport && mTimeout) { - chip::DeviceLayer::PlatformMgr().ScheduleWork(StopAsyncTimeout, reinterpret_cast(this)); + TEMPORARY_RETURN_IGNORED chip::DeviceLayer::PlatformMgr().ScheduleWork(StopAsyncTimeout, + reinterpret_cast(this)); } mEnabled = false; @@ -231,18 +233,18 @@ struct InteractiveServerResult { auto self = reinterpret_cast(arg); auto timeout = chip::System::Clock::Seconds16(self->mTimeout); - chip::DeviceLayer::SystemLayer().StartTimer(timeout, OnAsyncTimeout, self); + TEMPORARY_RETURN_IGNORED chip::DeviceLayer::SystemLayer().StartTimer(timeout, OnAsyncTimeout, self); } static void StopAsyncTimeout(intptr_t arg) { auto self = reinterpret_cast(arg); - chip::DeviceLayer::SystemLayer().CancelTimer(OnAsyncTimeout, self); + TEMPORARY_RETURN_IGNORED chip::DeviceLayer::SystemLayer().CancelTimer(OnAsyncTimeout, self); } static void OnAsyncTimeout(chip::System::Layer *, void * appState) { - RemoteDataModelLogger::LogErrorAsJSON(CHIP_ERROR_TIMEOUT); + TEMPORARY_RETURN_IGNORED RemoteDataModelLogger::LogErrorAsJSON(CHIP_ERROR_TIMEOUT); } }; diff --git a/examples/chip-tool/commands/pairing/PairingCommand.cpp b/examples/chip-tool/commands/pairing/PairingCommand.cpp index 7b3e2d9ec16..07756d7c9e8 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.cpp +++ b/examples/chip-tool/commands/pairing/PairingCommand.cpp @@ -183,12 +183,13 @@ CommissioningParameters PairingCommand::GetCommissioningParameters() if (!mICDSymmetricKey.HasValue()) { - Crypto::DRBG_get_bytes(mRandomGeneratedICDSymmetricKey, sizeof(mRandomGeneratedICDSymmetricKey)); + TEMPORARY_RETURN_IGNORED Crypto::DRBG_get_bytes(mRandomGeneratedICDSymmetricKey, + sizeof(mRandomGeneratedICDSymmetricKey)); mICDSymmetricKey.SetValue(ByteSpan(mRandomGeneratedICDSymmetricKey)); } if (!mICDCheckInNodeId.HasValue()) { - mICDCheckInNodeId.SetValue(CurrentCommissioner().GetNodeId()); + TEMPORARY_RETURN_IGNORED mICDCheckInNodeId.SetValue(CurrentCommissioner().GetNodeId()); } if (!mICDMonitoredSubject.HasValue()) { @@ -498,8 +499,9 @@ void PairingCommand::OnICDRegistrationComplete(ScopedNodeId nodeId, uint32_t icd { char icdSymmetricKeyHex[Crypto::kAES_CCM128_Key_Length * 2 + 1]; - Encoding::BytesToHex(mICDSymmetricKey.Value().data(), mICDSymmetricKey.Value().size(), icdSymmetricKeyHex, - sizeof(icdSymmetricKeyHex), Encoding::HexFlags::kNullTerminate); + TEMPORARY_RETURN_IGNORED Encoding::BytesToHex(mICDSymmetricKey.Value().data(), mICDSymmetricKey.Value().size(), + icdSymmetricKeyHex, sizeof(icdSymmetricKeyHex), + Encoding::HexFlags::kNullTerminate); app::ICDClientInfo clientInfo; clientInfo.check_in_node = ScopedNodeId(mICDCheckInNodeId.Value(), nodeId.GetFabricIndex()); @@ -515,7 +517,7 @@ void PairingCommand::OnICDRegistrationComplete(ScopedNodeId nodeId, uint32_t icd if (err != CHIP_NO_ERROR) { - CHIPCommand::sICDClientStorage.RemoveKey(clientInfo); + TEMPORARY_RETURN_IGNORED CHIPCommand::sICDClientStorage.RemoveKey(clientInfo); ChipLogError(chipTool, "Failed to persist symmetric key for " ChipLogFormatX64 ": %s", ChipLogValueX64(nodeId.GetNodeId()), err.AsString()); SetCommandExitStatus(err); @@ -558,7 +560,7 @@ CHIP_ERROR PairingCommand::WiFiCredentialsNeeded(EndpointId endpoint) // outermost ScheduleLambda is only there to avoid the prompt interleaving // with logging that happens on the Matter thread after this function // returns. - DeviceLayer::SystemLayer().ScheduleLambda([this] { + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().ScheduleLambda([this] { mPrompterThread.emplace([this] { do { @@ -582,7 +584,7 @@ CHIP_ERROR PairingCommand::WiFiCredentialsNeeded(EndpointId endpoint) ChipLogError(chipTool, "Invalid value for password"); } while (true); - DeviceLayer::SystemLayer().ScheduleLambda([this] { + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().ScheduleLambda([this] { // Ensure that the background thread (and its writes to our members) is done. mPrompterThread->join(); mPrompterThread.reset(); @@ -591,9 +593,9 @@ CHIP_ERROR PairingCommand::WiFiCredentialsNeeded(EndpointId endpoint) CommissioningParameters params = commissioner.GetCommissioningParameters(); auto credentials = Controller::WiFiCredentials(mSSID, mPassword); params.SetWiFiCredentials(credentials); - commissioner.UpdateCommissioningParameters(params); + TEMPORARY_RETURN_IGNORED commissioner.UpdateCommissioningParameters(params); - commissioner.NetworkCredentialsReady(); + TEMPORARY_RETURN_IGNORED commissioner.NetworkCredentialsReady(); }); }); }); @@ -616,7 +618,7 @@ CHIP_ERROR PairingCommand::ThreadCredentialsNeeded(EndpointId endpoint) // outermost ScheduleLambda is only there to avoid the prompt interleaving // with logging that happens on the Matter thread after this function // returns. - DeviceLayer::SystemLayer().ScheduleLambda([this] { + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().ScheduleLambda([this] { mPrompterThread.emplace([this] { do { @@ -629,7 +631,7 @@ CHIP_ERROR PairingCommand::ThreadCredentialsNeeded(EndpointId endpoint) ChipLogError(chipTool, "Invalid value for operational dataset"); } while (true); - DeviceLayer::SystemLayer().ScheduleLambda([this] { + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().ScheduleLambda([this] { // Ensure that the background thread (and its writes to our members) is done. mPrompterThread->join(); mPrompterThread.reset(); @@ -637,9 +639,9 @@ CHIP_ERROR PairingCommand::ThreadCredentialsNeeded(EndpointId endpoint) auto & commissioner = CurrentCommissioner(); CommissioningParameters params = commissioner.GetCommissioningParameters(); params.SetThreadOperationalDataset(mOperationalDataset); - commissioner.UpdateCommissioningParameters(params); + TEMPORARY_RETURN_IGNORED commissioner.UpdateCommissioningParameters(params); - commissioner.NetworkCredentialsReady(); + TEMPORARY_RETURN_IGNORED commissioner.NetworkCredentialsReady(); }); }); }); diff --git a/examples/closure-app/closure-common/closure-app.matter b/examples/closure-app/closure-common/closure-app.matter index 61a5e1dbe1a..63140788374 100644 --- a/examples/closure-app/closure-common/closure-app.matter +++ b/examples/closure-app/closure-common/closure-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/closure-app/closure-common/src/ClosureControlEndpoint.cpp b/examples/closure-app/closure-common/src/ClosureControlEndpoint.cpp index 139ddb4e18d..85647c1dffb 100644 --- a/examples/closure-app/closure-common/src/ClosureControlEndpoint.cpp +++ b/examples/closure-app/closure-common/src/ClosureControlEndpoint.cpp @@ -221,19 +221,19 @@ void ClosureControlEndpoint::OnCalibrateActionComplete() MakeOptional(Globals::ThreeLevelAutoEnum::kAuto), DataModel::MakeNullable(true))); DataModel::Nullable overallTargetState = DataModel::NullNullable; - mLogic.SetMainState(MainStateEnum::kStopped); - mLogic.SetOverallCurrentState(overallCurrentState); - mLogic.SetOverallTargetState(overallTargetState); - mLogic.SetCountdownTimeFromDelegate(0); - mLogic.GenerateMovementCompletedEvent(); + TEMPORARY_RETURN_IGNORED mLogic.SetMainState(MainStateEnum::kStopped); + TEMPORARY_RETURN_IGNORED mLogic.SetOverallCurrentState(overallCurrentState); + TEMPORARY_RETURN_IGNORED mLogic.SetOverallTargetState(overallTargetState); + TEMPORARY_RETURN_IGNORED mLogic.SetCountdownTimeFromDelegate(0); + TEMPORARY_RETURN_IGNORED mLogic.GenerateMovementCompletedEvent(); } void ClosureControlEndpoint::OnMoveToActionComplete() { UpdateCurrentStateFromTargetState(); - mLogic.SetMainState(MainStateEnum::kStopped); - mLogic.SetCountdownTimeFromDelegate(0); - mLogic.GenerateMovementCompletedEvent(); + TEMPORARY_RETURN_IGNORED mLogic.SetMainState(MainStateEnum::kStopped); + TEMPORARY_RETURN_IGNORED mLogic.SetCountdownTimeFromDelegate(0); + TEMPORARY_RETURN_IGNORED mLogic.GenerateMovementCompletedEvent(); } void ClosureControlEndpoint::UpdateCurrentStateFromTargetState() @@ -286,7 +286,7 @@ void ClosureControlEndpoint::UpdateCurrentStateFromTargetState() overallCurrentState.Value().secureState.SetNonNull(isClosureInSecureState); - mLogic.SetOverallCurrentState(overallCurrentState); + TEMPORARY_RETURN_IGNORED mLogic.SetOverallCurrentState(overallCurrentState); } CurrentPositionEnum ClosureControlEndpoint::MapTargetPositionToCurrentPositioning(TargetPositionEnum value) @@ -310,7 +310,7 @@ CurrentPositionEnum ClosureControlEndpoint::MapTargetPositionToCurrentPositionin void ClosureControlEndpoint::OnPanelMotionActionComplete() { - mLogic.SetMainState(MainStateEnum::kStopped); + TEMPORARY_RETURN_IGNORED mLogic.SetMainState(MainStateEnum::kStopped); // Set the OverallState position to PartiallyOpened as motion has been stopped auto position = MakeOptional(DataModel::MakeNullable(CurrentPositionEnum::kPartiallyOpened)); @@ -347,8 +347,8 @@ void ClosureControlEndpoint::OnPanelMotionActionComplete() overallCurrentState.Value().speed.SetValue(overallTargetState.Value().speed.Value()); } } - mLogic.SetOverallCurrentState(overallCurrentState); + TEMPORARY_RETURN_IGNORED mLogic.SetOverallCurrentState(overallCurrentState); - mLogic.SetCountdownTimeFromDelegate(0); - mLogic.GenerateMovementCompletedEvent(); + TEMPORARY_RETURN_IGNORED mLogic.SetCountdownTimeFromDelegate(0); + TEMPORARY_RETURN_IGNORED mLogic.GenerateMovementCompletedEvent(); } diff --git a/examples/closure-app/closure-common/src/ClosureDimensionEndpoint.cpp b/examples/closure-app/closure-common/src/ClosureDimensionEndpoint.cpp index 943d380b2a4..58758def6d6 100644 --- a/examples/closure-app/closure-common/src/ClosureDimensionEndpoint.cpp +++ b/examples/closure-app/closure-common/src/ClosureDimensionEndpoint.cpp @@ -92,8 +92,8 @@ void ClosureDimensionEndpoint::OnCalibrateActionComplete() GenericDimensionStateStruct(MakeOptional(DataModel::MakeNullable(kFullClosedTargetPosition)), MakeOptional(DataModel::MakeNullable(true)), MakeOptional(Globals::ThreeLevelAutoEnum::kAuto))); DataModel::Nullable targetState{ DataModel::NullNullable }; - mLogic.SetCurrentState(currentState); - mLogic.SetTargetState(targetState); + TEMPORARY_RETURN_IGNORED mLogic.SetCurrentState(currentState); + TEMPORARY_RETURN_IGNORED mLogic.SetTargetState(targetState); } void ClosureDimensionEndpoint::OnMoveToActionComplete() @@ -131,7 +131,7 @@ void ClosureDimensionEndpoint::UpdateCurrentStateFromTargetState() currentState.Value().speed.SetValue(targetState.Value().speed.Value()); } - mLogic.SetCurrentState(currentState); + TEMPORARY_RETURN_IGNORED mLogic.SetCurrentState(currentState); } void ClosureDimensionEndpoint::OnPanelMotionActionComplete() diff --git a/examples/closure-app/linux/ClosureManager.cpp b/examples/closure-app/linux/ClosureManager.cpp index a220cdc0b1f..0bb37112de3 100644 --- a/examples/closure-app/linux/ClosureManager.cpp +++ b/examples/closure-app/linux/ClosureManager.cpp @@ -90,12 +90,12 @@ void ClosureManager::Init() ChipLogProgress(AppServer, "Closure Panel Endpoint 3 initialized successfully"); // Set Taglist for Closure endpoints - SetTagList(/* endpoint= */ kClosureEndpoint1, - Span(kClosureEndpoint1TagList)); - SetTagList(/* endpoint= */ kClosurePanelEndpoint2, - Span(kClosurePanelEndpoint2TagList)); - SetTagList(/* endpoint= */ kClosurePanelEndpoint3, - Span(kClosurePanelEndpoint3TagList)); + SuccessOrDie(SetTagList(/* endpoint= */ kClosureEndpoint1, + Span(kClosureEndpoint1TagList))); + SuccessOrDie(SetTagList(/* endpoint= */ kClosurePanelEndpoint2, + Span(kClosurePanelEndpoint2TagList))); + SuccessOrDie(SetTagList(/* endpoint= */ kClosurePanelEndpoint3, + Span(kClosurePanelEndpoint3TagList))); // Set Initial state for Closure endpoints VerifyOrDie(SetClosureControlInitialState(mClosureEndpoint1) == CHIP_NO_ERROR); @@ -382,7 +382,8 @@ ClosureManager::OnMoveToCommand(const Optional & position, c mEp1CurrentAction = ClosureAction::kMoveToAction; mEp1MotionInProgress = true; - DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kMotionCountdownTimeMs), HandleEp1ClosureActionTimer, this); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kMotionCountdownTimeMs), + HandleEp1ClosureActionTimer, this); return Status::Success; } @@ -661,10 +662,10 @@ void ClosureManager::HandlePanelUnlatchAction(EndpointId endpointId) ep1OverallCurrentState.Value().latch.SetValue(DataModel::MakeNullable(false)); ep1OverallCurrentState.Value().secureState.SetNonNull(false); - mClosureEndpoint1.GetLogic().SetOverallCurrentState(ep1OverallCurrentState); + TEMPORARY_RETURN_IGNORED mClosureEndpoint1.GetLogic().SetOverallCurrentState(ep1OverallCurrentState); panelCurrentState.Value().latch.SetValue(false); - panelEp->GetLogic().SetCurrentState(panelCurrentState); + TEMPORARY_RETURN_IGNORED panelEp->GetLogic().SetCurrentState(panelCurrentState); ChipLogProgress(AppServer, "Unlatched action completed"); } @@ -714,7 +715,7 @@ void ClosureManager::HandlePanelSetTargetAction(EndpointId endpointId) VerifyOrReturn(!nextPosition.IsNull(), ChipLogError(AppServer, "Next position is not set for Endpoint %d", endpointId)); panelCurrentState.Value().position.SetValue(DataModel::MakeNullable(nextPosition.Value())); - ep->GetLogic().SetCurrentState(panelCurrentState); + TEMPORARY_RETURN_IGNORED ep->GetLogic().SetCurrentState(panelCurrentState); panelProgressPossible = (nextPosition.Value() != panelTargetState.Value().position.Value().Value()); ChipLogProgress(AppServer, "EndPoint %d Current Position: %d, Target Position: %d", endpointId, nextPosition.Value(), @@ -766,10 +767,10 @@ void ClosureManager::HandlePanelSetTargetAction(EndpointId endpointId) ep1OverallCurrentState.Value().latch.SetValue(DataModel::MakeNullable(true)); ep1OverallCurrentState.Value().secureState.SetNonNull(false); - mClosureEndpoint1.GetLogic().SetOverallCurrentState(ep1OverallCurrentState); + TEMPORARY_RETURN_IGNORED mClosureEndpoint1.GetLogic().SetOverallCurrentState(ep1OverallCurrentState); panelCurrentState.Value().latch.SetValue(DataModel::MakeNullable(true)); - ep->GetLogic().SetCurrentState(panelCurrentState); + TEMPORARY_RETURN_IGNORED ep->GetLogic().SetCurrentState(panelCurrentState); ChipLogProgress(AppServer, "Latch action completed"); } @@ -834,7 +835,7 @@ void ClosureManager::HandlePanelStepAction(EndpointId endpointId) } panelCurrentState.Value().position.SetValue(DataModel::MakeNullable(nextCurrentPosition)); - ep->GetLogic().SetCurrentState(panelCurrentState); + TEMPORARY_RETURN_IGNORED ep->GetLogic().SetCurrentState(panelCurrentState); // Cancel any existing timer before starting a new action if (endpointId == kClosurePanelEndpoint2) @@ -917,11 +918,11 @@ void ClosureManager::HandleClosureMotionAction() ChipLogProgress(AppServer, "Performing unlatch action"); ep1CurrentState.Value().latch.SetValue(DataModel::MakeNullable(false)); ep1CurrentState.Value().secureState.SetNonNull(false); - instance.mClosureEndpoint1.GetLogic().SetOverallCurrentState(ep1CurrentState); + TEMPORARY_RETURN_IGNORED instance.mClosureEndpoint1.GetLogic().SetOverallCurrentState(ep1CurrentState); ep2CurrentState.Value().latch.SetValue(DataModel::MakeNullable(false)); - instance.mClosurePanelEndpoint2.GetLogic().SetCurrentState(ep2CurrentState); + TEMPORARY_RETURN_IGNORED instance.mClosurePanelEndpoint2.GetLogic().SetCurrentState(ep2CurrentState); ep3CurrentState.Value().latch.SetValue(DataModel::MakeNullable(false)); - instance.mClosurePanelEndpoint3.GetLogic().SetCurrentState(ep3CurrentState); + TEMPORARY_RETURN_IGNORED instance.mClosurePanelEndpoint3.GetLogic().SetCurrentState(ep3CurrentState); ChipLogProgress(AppServer, "Unlatched action completed"); } } @@ -939,7 +940,7 @@ void ClosureManager::HandleClosureMotionAction() { VerifyOrReturn(!ep2NextPosition.IsNull(), ChipLogError(AppServer, "Failed to get next position for Endpoint 2")); ep2CurrentState.Value().position.SetValue(DataModel::MakeNullable(ep2NextPosition.Value())); - instance.mClosurePanelEndpoint2.GetLogic().SetCurrentState(ep2CurrentState); + TEMPORARY_RETURN_IGNORED instance.mClosurePanelEndpoint2.GetLogic().SetCurrentState(ep2CurrentState); isEndPoint2ProgressPossible = (ep2NextPosition.Value() != ep2TargetState.Value().position.Value().Value()); ChipLogProgress(AppServer, "EndPoint 2 Current Position: %d, Target Position: %d", ep2NextPosition.Value(), ep2TargetState.Value().position.Value().Value()); @@ -950,7 +951,7 @@ void ClosureManager::HandleClosureMotionAction() { VerifyOrReturn(!ep3NextPosition.IsNull(), ChipLogError(AppServer, "Failed to get next position for Endpoint 3")); ep3CurrentState.Value().position.SetValue(DataModel::MakeNullable(ep3NextPosition.Value())); - instance.mClosurePanelEndpoint3.GetLogic().SetCurrentState(ep3CurrentState); + TEMPORARY_RETURN_IGNORED instance.mClosurePanelEndpoint3.GetLogic().SetCurrentState(ep3CurrentState); isEndPoint3ProgressPossible = (ep3NextPosition.Value() != ep3TargetState.Value().position.Value().Value()); ChipLogProgress(AppServer, "EndPoint 3 Current Position: %d, Target Position: %d", ep3NextPosition.Value(), ep3TargetState.Value().position.Value().Value()); @@ -970,8 +971,8 @@ void ClosureManager::HandleClosureMotionAction() { mEp1CurrentAction = ClosureAction::kMoveToAction; mEp1MotionInProgress = true; - DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kMotionCountdownTimeMs), HandleEp1ClosureActionTimer, - this); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kMotionCountdownTimeMs), + HandleEp1ClosureActionTimer, this); ChipLogProgress(AppServer, "Rescheduled HandleEp1ClosureActionTimer for motion action"); return; } @@ -1000,11 +1001,11 @@ void ClosureManager::HandleClosureMotionAction() ep1CurrentState.Value().secureState.SetNonNull(false); } } - instance.mClosureEndpoint1.GetLogic().SetOverallCurrentState(ep1CurrentState); + TEMPORARY_RETURN_IGNORED instance.mClosureEndpoint1.GetLogic().SetOverallCurrentState(ep1CurrentState); ep2CurrentState.Value().latch.SetValue(DataModel::MakeNullable(true)); - instance.mClosurePanelEndpoint2.GetLogic().SetCurrentState(ep2CurrentState); + TEMPORARY_RETURN_IGNORED instance.mClosurePanelEndpoint2.GetLogic().SetCurrentState(ep2CurrentState); ep3CurrentState.Value().latch.SetValue(DataModel::MakeNullable(true)); - instance.mClosurePanelEndpoint3.GetLogic().SetCurrentState(ep3CurrentState); + TEMPORARY_RETURN_IGNORED instance.mClosurePanelEndpoint3.GetLogic().SetCurrentState(ep3CurrentState); ChipLogProgress(AppServer, "latched action complete"); } } @@ -1058,7 +1059,7 @@ ClosureDimensionEndpoint * ClosureManager::GetCurrentPanelInstance(EndpointId en { return &instance.mClosurePanelEndpoint2; } - else if (endpointId == instance.mClosurePanelEndpoint3.GetEndpointId()) + if (endpointId == instance.mClosurePanelEndpoint3.GetEndpointId()) { return &instance.mClosurePanelEndpoint3; } diff --git a/examples/closure-app/silabs/data_model/closure-thread-app.matter b/examples/closure-app/silabs/data_model/closure-thread-app.matter index 58babd9cff3..3176411caec 100644 --- a/examples/closure-app/silabs/data_model/closure-thread-app.matter +++ b/examples/closure-app/silabs/data_model/closure-thread-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/closure-app/silabs/data_model/closure-wifi-app.matter b/examples/closure-app/silabs/data_model/closure-wifi-app.matter index ecb1079b19d..3ad289490bb 100644 --- a/examples/closure-app/silabs/data_model/closure-wifi-app.matter +++ b/examples/closure-app/silabs/data_model/closure-wifi-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/common/pigweed/rpc_services/JointFabric.h b/examples/common/pigweed/rpc_services/JointFabric.h index c6c14a0bd6f..5431f7ca27c 100644 --- a/examples/common/pigweed/rpc_services/JointFabric.h +++ b/examples/common/pigweed/rpc_services/JointFabric.h @@ -43,8 +43,8 @@ class JointFabric : public pw_rpc::nanopb::JointFabric::Service, pu static void FinalizeCommissioningWork(intptr_t arg) { OwnershipTransferContext * data = reinterpret_cast(arg); - chip::JFAMgr().FinalizeCommissioning(data->mNodeId, data->mJCM, data->mTrustedIcacPublicKeyBSerialized, - data->mPeerAdminJFAdminClusterEndpointId); + TEMPORARY_RETURN_IGNORED chip::JFAMgr().FinalizeCommissioning( + data->mNodeId, data->mJCM, data->mTrustedIcacPublicKeyBSerialized, data->mPeerAdminJFAdminClusterEndpointId); chip::Platform::Delete(data); } diff --git a/examples/common/tracing/TraceDecoder.h b/examples/common/tracing/TraceDecoder.h index 9a99041578d..1dd96629c17 100644 --- a/examples/common/tracing/TraceDecoder.h +++ b/examples/common/tracing/TraceDecoder.h @@ -38,7 +38,7 @@ class TraceDecoder : public TraceStream void SetOptions(TraceDecoderOptions options) { mOptions = options; } // TraceStream Interface - void StartEvent(const std::string & label) override { ReadString(label.c_str()); } + void StartEvent(const std::string & label) override { TEMPORARY_RETURN_IGNORED ReadString(label.c_str()); } void AddField(const std::string & tag, const std::string & data) override { diff --git a/examples/common/tracing/decoder/interaction_model/Decoder.cpp b/examples/common/tracing/decoder/interaction_model/Decoder.cpp index 8563fd8a344..d34c151f242 100644 --- a/examples/common/tracing/decoder/interaction_model/Decoder.cpp +++ b/examples/common/tracing/decoder/interaction_model/Decoder.cpp @@ -137,7 +137,7 @@ CHIP_ERROR DecodeStatusResponse(TLV::TLVReader & reader, bool decode) { app::StatusResponseMessage::Parser parser; ReturnErrorOnFailure(parser.Init(reader)); - parser.PrettyPrint(); + TEMPORARY_RETURN_IGNORED parser.PrettyPrint(); } #endif @@ -179,7 +179,7 @@ CHIP_ERROR DecodeSubscribeResponse(TLV::TLVReader & reader, bool decode) { app::SubscribeResponseMessage::Parser parser; ReturnErrorOnFailure(parser.Init(reader)); - parser.PrettyPrint(); + TEMPORARY_RETURN_IGNORED parser.PrettyPrint(); } #endif @@ -195,7 +195,7 @@ CHIP_ERROR DecodeReportData(TLV::TLVReader & reader, bool decode) { app::ReportDataMessage::Parser parser; ReturnErrorOnFailure(parser.Init(reader)); - parser.PrettyPrint(); + TEMPORARY_RETURN_IGNORED parser.PrettyPrint(); } #endif @@ -255,7 +255,7 @@ CHIP_ERROR DecodeInvokeCommandResponse(TLV::TLVReader & reader, bool decode) { app::InvokeResponseMessage::Parser parser; ReturnErrorOnFailure(parser.Init(reader)); - parser.PrettyPrint(); + TEMPORARY_RETURN_IGNORED parser.PrettyPrint(); } #endif @@ -269,7 +269,7 @@ CHIP_ERROR DecodeTimedRequest(TLV::TLVReader & reader, bool decode) { app::TimedRequestMessage::Parser parser; ReturnErrorOnFailure(parser.Init(reader)); - parser.PrettyPrint(); + TEMPORARY_RETURN_IGNORED parser.PrettyPrint(); } #endif diff --git a/examples/common/tracing/decoder/interaction_model/DecoderCustomLog.cpp b/examples/common/tracing/decoder/interaction_model/DecoderCustomLog.cpp index 089a32b380a..ef66d7632a6 100644 --- a/examples/common/tracing/decoder/interaction_model/DecoderCustomLog.cpp +++ b/examples/common/tracing/decoder/interaction_model/DecoderCustomLog.cpp @@ -304,11 +304,11 @@ CHIP_ERROR MaybeDecodeAttributeData(TLV::TLVReader & reader) { if (to_underlying(app::AttributePathIB::Tag::kCluster) == TLV::TagNumFromTag(reader.GetTag())) { - reader.Get(clusterId); + TEMPORARY_RETURN_IGNORED reader.Get(clusterId); } else if (to_underlying(app::AttributePathIB::Tag::kAttribute) == TLV::TagNumFromTag(reader.GetTag())) { - reader.Get(attributeId); + TEMPORARY_RETURN_IGNORED reader.Get(attributeId); } } ReturnErrorOnFailure(reader.ExitContainer(containerType)); @@ -351,11 +351,11 @@ CHIP_ERROR MaybeDecodeCommandData(TLV::TLVReader & reader) { if (to_underlying(app::CommandPathIB::Tag::kClusterId) == TLV::TagNumFromTag(reader.GetTag())) { - reader.Get(clusterId); + TEMPORARY_RETURN_IGNORED reader.Get(clusterId); } else if (to_underlying(app::CommandPathIB::Tag::kCommandId) == TLV::TagNumFromTag(reader.GetTag())) { - reader.Get(commandId); + TEMPORARY_RETURN_IGNORED reader.Get(commandId); } } ReturnErrorOnFailure(reader.ExitContainer(containerType)); diff --git a/examples/contact-sensor-app/bouffalolab/data_model/contact-sensor-app.matter b/examples/contact-sensor-app/bouffalolab/data_model/contact-sensor-app.matter index 59a6c065efc..efa9d208954 100644 --- a/examples/contact-sensor-app/bouffalolab/data_model/contact-sensor-app.matter +++ b/examples/contact-sensor-app/bouffalolab/data_model/contact-sensor-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter b/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter index 71c0ebdf93b..7c0f1cee2a7 100644 --- a/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter +++ b/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/contact-sensor-app/nxp/README.md b/examples/contact-sensor-app/nxp/README.md index d5c75fbd655..1b123fa1316 100644 --- a/examples/contact-sensor-app/nxp/README.md +++ b/examples/contact-sensor-app/nxp/README.md @@ -1,197 +1,160 @@ # Matter NXP Contact Sensor Example Application -This reference application implements a Contact Sensor device type. It uses -board buttons or `matter-cli` for user input and LEDs for state feedback. You -can use this example as a reference for creating your own application. - -The example is based on: - -- [Matter](https://github.com/project-chip/connectedhomeip) -- [NXP github SDK](https://github.com/nxp-mcuxpresso/mcux-sdk) +- [Overview](#overview) +- [Supported Platforms](#supported-platforms) +- [Environment Setup, Building, and Testing](#build) +- [Data Model](#data-model) +- [Manufacturing Data](#factory-data) +- [Long Idle Time ICD Support](#long-idle-time-icd-support) +- [Low Power](#low-power) -- [Matter NXP Contact Sensor Example Application](#matter-nxp-contact-sensor-example-application) - - [Supported devices](#supported-devices) - - [Introduction](#introduction) - - [Device UI](#device-ui) - - [Prerequisites for building](#prerequisites-for-building) - - [Building](#building) - - [Data model](#data-model) - - [Manufacturing data](#manufacturing-data) - - [Long Idle Time ICD Support](#long-idle-time-icd-support) - - [Low power](#low-power) - - [Flashing and debugging](#flashing-and-debugging) + -## Supported devices +## Overview -- [mcxw71](mcxw71/README.md) -- [mcxw72](mcxw72/README.md) - -## Introduction +This reference application implements a Contact Sensor device type. It uses +board buttons or `matter-cli` for user input and LEDs for state feedback. You +can use this example as a reference for creating your own application. -The application showcases a contact sensor that communicates with clients over a -low-power, 802.15.4 Thread network. +The example is based on +[Project CHIP](https://github.com/project-chip/connectedhomeip) and NXP SDK, and +provides a prototype application that demonstrates device commissioning and +different cluster control. -It can be commissioned into an existing Matter network using a controller such -as `chip-tool`. +This contact sensor communicates with clients over a low-power, 802.15.4 Thread +network. It can be commissioned into an existing Matter network using a +controller, such as `chip-tool`. -This example implements a `User-Intent Commissioning Flow`, meaning the user has -to press a button in order for the device to be ready for commissioning. The -initial commissioning is done through `ble-thread` pairing method. +This example implements a `User-Intent Commissioning Flow`, meaning that the +user is required to press a button on the device in order to get it ready for +commissioning. The initial commissioning is usually performed using the +`ble-thread` pairing method. The Thread network dataset will be transferred on the device using a secure session over Bluetooth LE. In order to start the commissioning process, the user must enable BLE advertising on the device manually. To pair successfully, the commissioner must know the commissioning information corresponding to the -device: setup passcode and discriminator. This data is usually encoded within a -QR code or printed to the UART console. - -## Device UI +device: setup passcode and/or discriminator. This data is usually encoded within +a QR code or printed to the device's UART console. -The example application provides a simple UI that depicts the state of the -device and offers basic user control. This UI is implemented via the -general-purpose LEDs and buttons built in the evaluation boards. Please see each -supported device readme file for details. + -## Prerequisites for building +## Supported Platforms -In order to build the example, it is recommended to use a Linux distribution. -Please visit the supported Operating Systems list in -[BUILDING.md](../../../docs/guides/BUILDING.md#prerequisites). +The Contact Sensor example is supported on the following platforms: -- Make sure that below prerequisites are correctly installed (as described in - [BUILDING.md](../../../docs/guides/BUILDING.md#prerequisites)) +| NXP platform | Dedicated readme | +| ------------ | ------------------------------------------------------------------- | +| MCXW71 | [NXP MCXW71 Guide](../../../docs/platforms/nxp/nxp_mcxw71_guide.md) | +| MCXW72 | [NXP MCXW72 Guide](../../../docs/platforms/nxp/nxp_mcxw72_guide.md) | -``` -sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev -``` +For details on platform-specific requirements and configurations, please refer +to the respective platform's readme. -- Step 1: checkout NXP specific submodules only +A list of popular standard contact sensor app build targets is presented below. +These targets can be used with the `build_example.py` tool. - ``` - user@ubuntu:~/Desktop/git/connectedhomeip$ scripts/checkout_submodules.py --shallow --platform nxp --recursive - ``` +| Target name | Description | +| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------- | +| `nxp--freertos-contact-sensor-thread-mtd-frdm` | Default contact sensor | +| `nxp--freertos-contact-sensor-thread-mtd-low-power-frdm` | Default low-power contact sensor | +| `nxp--freertos-contact-sensor-thread-mtd-low-power-factory-frdm` | Default low-power contact sensor with factory data | +| `nxp--freertos-contact-sensor-thread-mtd-low-power-lit-frdm` | Low-power contact sensor as LIT ICD | +| `nxp--freertos-contact-sensor-thread-mtd-low-power-sw-v2-frdm` | Low-power contact sensor with software version 2 (can be used to test OTA) | +| `nxp--freertos-contact-sensor-thread-mtd-low-power-factory-sw-v2-frdm` | Low-power contact sensor with factory data and software version 2 (can be used to test OTA) | -- Step 2: activate local environment +where `device` is one of the [supported platforms](#supported-platforms). - ``` - user@ubuntu:~/Desktop/git/connectedhomeip$ source scripts/activate.sh - ``` + - If the script says the environment is out of date, you can update it by - running the following command: +## Environment Setup, Building, and Testing - ``` - user@ubuntu:~/Desktop/git/connectedhomeip$ source scripts/bootstrap.sh - ``` +All the information required to set up the environment, build the application, +and test it can be found in the common readme for NXP platforms: -- Step 3: Init NXP SDK(s) +- NXP FreeRTOS Platforms : Refer to the + [CHIP NXP Examples Guide for FreeRTOS platforms](../../../docs/platforms/nxp/nxp_examples_freertos_platforms.md) - ``` - user@ubuntu:~/Desktop/git/connectedhomeip$ third_party/nxp/nxp_matter_support/scripts/update_nxp_sdk.py --platform common - ``` + -Note: By default, `update_nxp_sdk.py` will try to initialize all NXP SDKs. -Please run the script with arg `--help` to view all available options. - -## Building - -There are two options for building this reference app: - -- Using `build_examples.py` framework. -- Manually generating `ninja` files using `gn`. - -For manual generation and building, please see the specific readme file for your -device. - -A list of all available contact sensor targets can be viewed in the following -table: - -| target name | description | -| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------- | -| nxp-device-freertos-contact-sensor-low-power | Default low-power contact sensor | -| nxp-device-freertos-contact-sensor-low-power-factory | Default low-power contact sensor with factory data | -| nxp-device-freertos-contact-sensor-low-power-lit | Low-power contact sensor as LIT ICD | -| nxp-device-freertos-contact-sensor-low-power-sw-v2 | Low-power contact sensor with software version 2 (can be used to test OTA) | -| nxp-device-freertos-contact-sensor-low-power-factory-sw-v2 | Low-power contact sensor with factory data and software version 2 (can be used to test OTA) | - -where `device` can be one of the [Supported devices](#supported-devices). - -### Data model +## Data Model There are two available data models that can be used by the application: -| path | description | +| Path | Description | | -------------------------------- | ------------------------------ | | `zap-lit/contact-sensor-app.zap` | Data model for LIT ICD support | | `zap-sit/contact-sensor-app.zap` | Data model for SIT ICD support | -The selection is done automatically by the build system based on the ICD -configuration. +The data model is selected automatically by the build system based on the user +ICD flavor build option (SIT or LIT). -The data model can be changed by simply replacing the gn `deps` statement -corresponding to data model target. + -### Manufacturing data +## Manufacturing Data -Use `nxp_use_factory_data=true` in the gn build command to enable factory data. +The support for manufacturing data is enabled at build time when you use the +appropriate build configuration files for this feature. Please refer to the +[NXP Matter examples guide for FreeRTOS](../../../docs/platforms/nxp/nxp_examples_freertos_platforms.md) +for details on the build process and available build configurations. +Manufacturing data can also be forced in the build command line by using the +`CONFIG_CHIP_FACTORY_DATA=y` build option or by using the appropriate +`build_examples.py` [targets](#supported-platforms). -For a full guide on manufacturing flow, please see +For a full guide on the manufacturing flow, please refer to the [Guide for writing manufacturing data on NXP devices](../../../docs/platforms/nxp/nxp_manufacturing_flow.md). -### Long Idle Time ICD Support + + +## Long Idle Time ICD Support By default, the application is compiled as a SIT ICD (Short Idle Time Intermittently Connected Device). -This is a list of ICD configuration gn args. - -| gn arg | default value | description | -| ------------------------------------------------------------------------------ | ------------- | ---------------------------------------------------------------------------------------------------------- | -| nxp_ot_idle_interval_ms | 2000 (ms) | OT Idle Interval duration | -| nxp_ot_active_interval_ms | 500 (ms) | OT Active Interval duration | -| nxp_idle_mode_duration_s | 600 (s) | Idle Mode Interval duration | -| nxp_active_mode_duration_ms | 10000 (ms) | Active Mode Interval duration | -| nxp_active_mode_threshold_ms | 1000 (ms) | Active Mode Threshold value | -| nxp_icd_supported_clients_per_fabric | 2 | Registration slots per fabric | -| chip_enable_icd_lit | false | Enable LIT ICD support | -| chip_enable_icd_dsls | false | Enable LIT ICD DSLS support | -| chip_persist_subscriptions | true | Try once to re-establish subscriptions from the server side after reboot. May be disabled for LIT use case | -| chip_subscription_timeout_resumption | true | Same as above, but try to re-establish timeout out subscriptions | -| using `Fibonacci Backoff` for retries pacing. May be disabled for LIT use case | - -If LIT ICD support is needed then `chip_enable_icd_lit=true` must be specified -as gn argument and the above parameters must be modified to comply with LIT -requirements (e.g.: LIT devices must configure -`chip_ot_idle_interval_ms > 15000`). Example LIT configuration: - -``` -nxp_ot_idle_interval_ms = 15000 # 15s Idle Intervals -nxp_ot_active_interval_ms = 500 # 500ms Active Intervals -nxp_idle_mode_duration_s = 3600 # 60min Idle Mode Interval -nxp_active_mode_duration_ms = 0 # 0 Active Mode Interval -nxp_active_mode_threshold_ms = 30000 # 30s Active Mode Threshold -``` - -### Low power - -The example also offers the possibility to run in low power mode. This means -that the board will go in deep sleep most of the time and the power consumption -will be very low. - -In order to build with low power support, the following gn args must be used: - -``` -nxp_use_low_power = true -chip_openthread_ftd = false -nxp_enable_ot_cli = false -chip_logging = false -``` - -In order to maintain a low power consumption, the UI LEDs are disabled. Console -logs can be used instead, but it might affect low power timings. Also, please -note that once the board is flashed with MCUXpresso the debugger disconnects -because the board enters low power. - -## Flashing and debugging - -Please see the device specific readme file. +The following is a list of ICD configuration build options. These options can be +provided on the build command line to override default values. Please refer to +your [platform guide](#supported-platforms) for details on the build process. + +| Build option | Default value | Description | +| --------------------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------- | +| `CONFIG_CHIP_ICD_SLOW_POLL_INTERVAL` | 2000 (ms) | OT Idle Mode poll interval duration | +| `CONFIG_CHIP_ICD_FAST_POLLING_INTERVAL` | 500 (ms) | OT Active Mode poll interval duration | +| `CONFIG_CHIP_ICD_IDLE_MODE_DURATION` | 600 (s) | Idle Mode Interval duration | +| `CONFIG_CHIP_ICD_ACTIVE_MODE_DURATION` | 10000 (ms) | Active Mode Interval duration | +| `CONFIG_CHIP_ICD_ACTIVE_MODE_THRESHOLD` | 5000 (ms) | Active Mode Threshold duration | +| `CONFIG_CHIP_ICD_CLIENTS_PER_FABRIC` | 2 | Registration slots per fabric | +| `CONFIG_CHIP_ICD_DSLS_SUPPORT` | n | Enable LIT ICD DSLS support | +| `CONFIG_CHIP_PERSISTENT_SUBSCRIPTIONS` | y | Try once to re-establish subscriptions from the server side after reboot. May be disabled for LIT use case | + +If LIT ICD support is required then `prj_thread_mtd_low_power_lit.conf` build +configuration file should be used when building the application. This will +automatically configure the above parameters to define a LIT device. You can +still override these values on the build command line in case you want to use +different values from the defaults. + +| Build option | LIT ICD default value | +| --------------------------------------- | --------------------- | +| `CONFIG_CHIP_ICD_SLOW_POLL_INTERVAL` | 15000 (ms) | +| `CONFIG_CHIP_ICD_FAST_POLLING_INTERVAL` | 500 (ms) | +| `CONFIG_CHIP_ICD_IDLE_MODE_DURATION` | 3600 (s) | +| `CONFIG_CHIP_ICD_ACTIVE_MODE_DURATION` | 15000 (ms) | +| `CONFIG_CHIP_ICD_ACTIVE_MODE_THRESHOLD` | 30000 (ms) | + + + +## Low Power + +This example also offers the possibility to run in low power mode. This means +that the device will use deep sleep/power down most of the time to minimize +power consumption. + +Low power support is enabled at build time when using the build configuration +files appropriate for low-power app configurations. Please refer to the +[NXP Matter examples guide for FreeRTOS](../../../docs/platforms/nxp/nxp_examples_freertos_platforms.md) +for details on the build process and available build configurations. + +In order to maintain low power consumption, the UI LEDs are disabled and device +log and Matter CLI will not be available. For debugging purposes device log can +be forced using the `CONFIG_LOG=y` build option, but this might affect low power +timings. Also, please note that once the application is flashed onto the board +the debugger might disconnect when the board enters low power. diff --git a/examples/contact-sensor-app/nxp/mcxw71/.gn b/examples/contact-sensor-app/nxp/mcxw71/.gn deleted file mode 100644 index ece782b1bb7..00000000000 --- a/examples/contact-sensor-app/nxp/mcxw71/.gn +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2020-2024 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") - -# The location of the build configuration file. -buildconfig = "${build_root}/config/BUILDCONFIG.gn" - -# CHIP uses angle bracket includes. -check_system_includes = true - -default_args = { - target_cpu = "arm" - target_os = "freertos" - - import("//args.gni") - - # Import default platform configs - import("${chip_root}/src/platform/nxp/mcxw71/args.gni") -} diff --git a/examples/contact-sensor-app/nxp/mcxw71/BUILD.gn b/examples/contact-sensor-app/nxp/mcxw71/BUILD.gn deleted file mode 100644 index 3fe4a2f2fe9..00000000000 --- a/examples/contact-sensor-app/nxp/mcxw71/BUILD.gn +++ /dev/null @@ -1,274 +0,0 @@ -# Copyright (c) 2021-2024 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") -import("//build_overrides/nxp_sdk.gni") -import("//build_overrides/openthread.gni") - -import("${nxp_sdk_build_root}/nxp_sdk.gni") - -import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") - -import("${nxp_sdk_build_root}/${nxp_sdk_name}/${nxp_sdk_name}.gni") - -import("${chip_root}/src/app/icd/icd.gni") -import("${chip_root}/src/crypto/crypto.gni") -import("${chip_root}/src/platform/device.gni") -import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") - -declare_args() { - # Setup discriminator as argument - setup_discriminator = 3840 - chip_with_diag_logs_demo = true -} - -assert(current_os == "freertos") -assert(target_os == "freertos") - -example_platform_dir = "${chip_root}/examples/platform/nxp/${nxp_platform}" -common_example_dir = "${chip_root}/examples/platform/nxp/common" -support_common_platform_dir = - "${nxp_sdk_matter_support_root}/examples/platform/common" - -mcxw71_sdk("sdk") { - defines = [] - include_dirs = [] - sources = [] - - # Indicate the path to CHIPProjectConfig.h - include_dirs += [ "include/config" ] - - # Indicate the default path to FreeRTOSConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/freeRTOS" ] - - # Indicate the default path to OpenThreadConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/openthread" ] - - # Indicate the default path to GATT database - include_dirs += [ "${support_common_platform_dir}/ble" ] - - include_dirs += [ - "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/app_common", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/components", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/dcdc", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/ext_flash", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/low_power", - ] - - sources += [ - "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples/clock_config.c", - "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples/pin_mux.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/app_common/app_services_init.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/app_common/hardware_init.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/board.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/components/board_comp.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/dcdc/board_dcdc.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/ext_flash/board_extflash.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/low_power/board_lp.c", - "${support_common_platform_dir}/ble/ble_function_mux.c", - ] - - if (is_debug) { - defines += [ "BUILD_RELEASE=0" ] - } else { - defines += [ "BUILD_RELEASE=1" ] - } - - defines += [ - "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", - ] -} - -mcxw71_executable("contact_sensor_app") { - output_name = "chip-mcxw71-contact-example" - - defines = [] - deps = [] - include_dirs = [] - sources = [] - - # Defines used by common code - defines += [ - "CONFIG_NET_L2_OPENTHREAD=1", - "CONFIG_NETWORK_LAYER_BLE=1", - "CONFIG_THREAD_DEVICE_TYPE=kThreadDeviceType_SleepyEndDevice", - "CONFIG_OPERATIONAL_KEYSTORE=1", - "EXTERNAL_FACTORY_DATA_PROVIDER_HEADER=\"platform/nxp/common/factory_data/legacy/FactoryDataProvider.h\"", - "CONFIG_APP_FREERTOS_OS=1", - ] - - if (chip_with_diag_logs_demo) { - defines += [ "CONFIG_DIAG_LOGS_DEMO=1" ] - } - - if (nxp_use_low_power) { - defines += [ "CONFIG_LOW_POWER=1" ] - } else { - defines += [ - "CONFIG_ENABLE_FEEDBACK=1", - "APP_QUEUE_TICKS_TO_WAIT=pdMS_TO_TICKS(10)", - ] - } - - # App common files - include_dirs += [ - "${common_example_dir}/app_task/include", - "${common_example_dir}/icd/include", - "${common_example_dir}/matter_button/include", - "${common_example_dir}/clusters/include", - "${common_example_dir}/device_callbacks/include", - "${common_example_dir}/device_manager/include", - "${common_example_dir}/diagnostic_logs/include", - "${common_example_dir}/factory_data/include", - "${common_example_dir}/led_widget/include", - "${common_example_dir}/low_power/include", - "${common_example_dir}/operational_keystore/include", - "${common_example_dir}/ui_feedback/include", - "${common_example_dir}/app_ble/include", - ] - - sources += [ - "${common_example_dir}/app_ble/source/BLEApplicationManagerEmpty.cpp", - "${common_example_dir}/app_task/source/AppTaskBase.cpp", - "${common_example_dir}/app_task/source/AppTaskFreeRTOS.cpp", - "${common_example_dir}/clusters/source/ZclCallbacks.cpp", - "${common_example_dir}/device_callbacks/source/CommonDeviceCallbacks.cpp", - "${common_example_dir}/device_manager/source/CHIPDeviceManager.cpp", - "${common_example_dir}/icd/source/ICDUtil.cpp", - "${common_example_dir}/matter_button/source/ButtonApp.cpp", - "${common_example_dir}/matter_button/source/ButtonBle.cpp", - "${common_example_dir}/matter_button/source/ButtonManager.cpp", - "${common_example_dir}/matter_button/source/ButtonRegistrationAppAndBle.cpp", - "${common_example_dir}/matter_button/source/ButtonWithTimer.cpp", - "${common_example_dir}/operational_keystore/source/OperationalKeystoreS200.cpp", - "${example_platform_dir}/factory_data/source/AppFactoryDataExample.cpp", - ] - - if (nxp_use_low_power) { - sources += [ "${common_example_dir}/low_power/source/LowPower.cpp" ] - } - - if (nxp_use_factory_data) { - # Custom factory data files can be added here - } - - if (chip_enable_ota_requestor) { - defines += [ - "CONFIG_CHIP_OTA_IMAGE_PROCESSOR_HEADER=\"platform/nxp/common/ota/OTAImageProcessorImpl.h\"", - - # The status LED and the external flash CS pin are wired together. The OTA image writing may fail if used together. - "LED_MANAGER_ENABLE_STATUS_LED=0", - ] - - include_dirs += [ - "${common_example_dir}/ota_requestor/include", - "${chip_root}/src/platform/nxp/common/ota", - ] - sources += [ "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorMultiImage.cpp" ] - deps += [ "${chip_root}/src/platform/nxp:nxp_ota" ] - } - - if (chip_with_diag_logs_demo) { - sources += [ - "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsDemo.cpp", - "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp", - ] - } - - # Platform specific files - include_dirs += [ - "${example_platform_dir}/util", - "${example_platform_dir}/app/support", - "${example_platform_dir}/button", - ] - - sources += [ "${example_platform_dir}/clusters/Identify.cpp" ] - - if (chip_enable_ota_requestor) { - sources += [ "${example_platform_dir}/ota/OtaUtils.cpp" ] - } - - include_dirs += [ - "include/config", - "../common/include", - ] - - sources += [ - "../common/AppTask.cpp", - "../common/DeviceCallbacks.cpp", - "../common/ZclCallbacks.cpp", - "../common/main.cpp", - ] - - if (!nxp_use_low_power) { - sources += [ - "${common_example_dir}/ui_feedback/source/LedManager.cpp", - "${example_platform_dir}/util/LedOnOff.cpp", - ] - } - - deps += [ - "${chip_root}/examples/providers:device_info_provider_please_do_not_reuse_as_is", - "${chip_root}/src/app/clusters/network-commissioning:network-commissioning", - "${chip_root}/src/platform/logging:default", - "${chip_root}/src/setup_payload:onboarding-codes-utils", - ] - - #lit and sit are using different zap files - if (chip_enable_icd_lit) { - deps += [ "${chip_root}/examples/contact-sensor-app/nxp/zap-lit/" ] - } else { - deps += [ "${chip_root}/examples/contact-sensor-app/nxp/zap-sit/" ] - } - - if (chip_openthread_ftd) { - deps += [ - "${openthread_root}:libopenthread-cli-ftd", - "${openthread_root}:libopenthread-ftd", - ] - } else { - deps += [ - "${openthread_root}:libopenthread-cli-mtd", - "${openthread_root}:libopenthread-mtd", - ] - } - - cflags = [ "-Wconversion" ] - - ldscript = "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples/linker/gcc/connectivity.ld" - - inputs = [ ldscript ] - - ldflags = [ - "-Wl,--defsym=__heap_size__=0", - "-Wl,--defsym=__stack_size__=0x480", - "-Wl,--defsym=lp_ram_lower_limit=0x04000000", - "-Wl,--defsym=lp_ram_upper_limit=0x2001C000", - "-Wl,-print-memory-usage", - "-Wl,--no-warn-rwx-segments", - "-T" + rebase_path(ldscript, root_build_dir), - ] - - if (nxp_use_factory_data) { - ldflags += [ "-Wl,--defsym=gUseFactoryData_d=1" ] - } - - output_dir = root_out_dir -} - -group("default") { - deps = [ ":contact_sensor_app" ] -} diff --git a/examples/contact-sensor-app/nxp/mcxw71/README.md b/examples/contact-sensor-app/nxp/mcxw71/README.md deleted file mode 100644 index 6857a7c307b..00000000000 --- a/examples/contact-sensor-app/nxp/mcxw71/README.md +++ /dev/null @@ -1,195 +0,0 @@ -# Matter `MCXW71` Contact Sensor Example Application - -For generic information related to contact sensor application, please see the -[common README](../README.md). - -- [Matter `MCXW71` Contact Sensor Example Application](#matter-mcxw71-contact-sensor-example-application) - - [Introduction](#introduction) - - [Device UI](#device-ui) - - [Building](#building) - - [Flashing](#flashing) - - [Flashing the `NBU` image](#flashing-the-nbu-image) - - [Flashing the host image](#flashing-the-host-image) - - [Debugging](#debugging) - - [OTA](#ota) - -## Introduction - -This is a contact sensor application implemented for an `mcxw71` device. - -The following board was used when testing this Matter reference app for an -`mcxw71` device: -![FRDM-MCXW71](../../../platform/nxp/mcxw71/doc/images/frdm-mcxw71.jpg) - -## Device UI - -The state feedback is provided through LED effects: - -| widget | effect | description | -| ------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------- | -| LED2 | short flash on (50ms on/950ms off) | The device is in an unprovisioned (unpaired) state and is waiting for a commissioner to connect. | -| LED2 | rapid even flashing (100ms period) | The device is in an unprovisioned state and a commissioner is connected via BLE. | -| LED2 | short flash off (950ms on/50ms off) | The device is fully provisioned, but does not yet have full network (Thread) or service connectivity. | -| LED2 | solid on | The device is fully provisioned and has full network and service connectivity. | -| RGB LED | on | The `StateValue` attribute of the `BooleanState` cluster is `true` (simulating detection). | -| RGB LED | off | The `StateValue` attribute of the `BooleanState` cluster is `false` (simulating no detection). | - -NOTE: `LED2` will be disabled when OTA is used. On `FRDM-MCXW71` board, `PTB0` -is wired to both `LED2` and CS (Chip Select) of the External Flash Memory. Since -the OTA image is stored in external memory, `LED2` operations will affect OTA -operation by corrupting packages and OTA will not work. - -The user actions are summarized below: - -| button | action | state | output | -| ------ | ------------ | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| SW2 | short press | not commissioned | Enable BLE advertising | -| SW2 | short press | commissioned + device is LIT | Enable Active Mode | -| SW2 | long press | NA | Initiate a factory reset (can be cancelled by pressing the button again within the factory reset timeout limit - 6 seconds by default) | -| SW2 | double press | commissioned + device is LIT + supports DSLS | Enable / Disable SIT Mode | -| SW3 | short press | NA | Toggle attribute `StateValue` value | -| SW3 | long press | NA | Clean soft reset of the device (takes into account proper Matter shutdown procedure) | - -## Building - -Manually building requires running the following commands: - -``` -user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/contact-sensor-app/nxp/mcxw71 -user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/mcxw71$ gn gen out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/mcxw71$ ninja -C out/debug -``` - -Please note that running `gn gen out/debug` without `--args` option will use the -default gn args values found in `args.gni`. - -After a successful build, the `elf` and `srec` files are found in `out/debug/`. -See the files prefixed with `chip-mcxw71-contact-example`. - -## Flashing - -Two images must be written to the board: one for the host (CM33) and one for the -`NBU` (CM3). - -### Flashing the `NBU` image - -`NBU` image should be written only when a new NXP SDK is released. - -1. Install - [Secure Provisioning SDK tool](https://www.nxp.com/design/design-center/software/development-software/secure-provisioning-sdk-spsdk:SPSDK) - using Python: - - ``` - pip install spsdk - ``` - - Note: There might be some dependencies that cause conflicts with already - installed Python modules. However, `blhost` tool is still installed and can - be used. - -2. Updating `NBU` for Wireless examples - - It is necessary to work with the matching `NBU` image for the SDK version of - the application you are working with. This means that when you download your - SDK, prior to loading any wireless SDK example, update your `NBU` image with - the SDK provided binaries. For `FRDM` users, please write the following - binary: - - `middleware\wireless\ieee-802.15.4\bin\mcxw71\mcxw71_nbu_ble_15_4_dyn_matter_.sb3` - - Please note that `` may vary depending on the SDK version. - - 1. Place your device in `ISP` mode. - - - Make sure a jumper is placed on `JP25` - - Press and hold `SW4`, press and release Reset, then release `SW4` - - 2. Once the device is connected, you may find the assigned port by running: - - ``` - nxpdevscan - ``` - - 3. Run the `blhost` command to write the `sb3` file: - - ``` - blhost -p receive-sb-file \middleware\wireless\ieee-802.15.4\bin\mcxw71\mcxw71_nbu_ble_15_4_dyn_matter_.sb3 - ``` - -### Flashing the host image - -Host image is the one found under `out/debug/`. It should be written after each -build process. - -If debugging is needed then jump directly to the [Debugging](#debugging) -section. Otherwise, if only flashing is needed then -[JLink](https://www.segger.com/downloads/jlink/) can be used: - -- Plug `MCXW71` to the USB port (no need to keep the `SW4` button pressed - while doing this, e.g. ISP mode is not needed for host flashing) - -- Connect JLink to the device: - - ```bash - JLinkExe -device MCXW71 -if SWD -speed 4000 -autoconnect 1 - ``` - -- Run the following commands: - ```bash - reset - halt - loadfile chip-mcxw71-contact-example.srec - reset - go - quit - ``` - -## Debugging - -One option for debugging would be to use MCUXpresso IDE. - -- Drag-and-drop the zip file containing the NXP SDK in the "Installed SDKs" - tab: - -![Installed SDKs](../../../platform/nxp/mcxw71/doc/images/mcxw71_installed_sdks.jpg) - -- Import any demo application from the installed SDK: - -``` -Import SDK example(s).. -> choose a demo app (demo_apps -> hello_world) -> Finish -``` - -![Import demo](../../../platform/nxp/mcxw71/doc/images/import_demo.jpg) - -- Flash the previously imported demo application on the board: - -``` -Right click on the application (from Project Explorer) -> Debug as -> JLink/CMSIS-DAP -``` - -After this step, a debug configuration specific for the `MCXW71` board was -created. This debug configuration will be used later on for debugging the -application resulted after ot-nxp compilation. - -- Import Matter repo in MCUXpresso IDE as Makefile Project. Use _none_ as - _Toolchain for Indexer Settings_: - -``` -File -> Import -> C/C++ -> Existing Code as Makefile Project -``` - -![New Project](../../../platform/nxp/mcxw71/doc/images/new_project.jpg) - -- Replace the path of the existing demo application with the path of the - `MCXW71` application: - -``` -Run -> Debug Configurations... -> C/C++ Application -``` - -![](../../../platform/nxp/mcxw71/doc/images/mcxw71_debug.jpg) - -## OTA - -Please see -[mcxw71 OTA guide](../../../../docs/platforms/nxp/nxp_mcxw71_ota_guide.md). diff --git a/examples/contact-sensor-app/nxp/mcxw71/args.gni b/examples/contact-sensor-app/nxp/mcxw71/args.gni deleted file mode 100644 index fcffe044d35..00000000000 --- a/examples/contact-sensor-app/nxp/mcxw71/args.gni +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2020-2024 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") -import("${chip_root}/config/standalone/args.gni") - -# SDK target. This is overridden to add our SDK app_config.h & defines. -nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") -nxp_device = "MCXW716C" -nxp_board = "frdmmcxw71" - -chip_enable_ota_requestor = true -chip_stack_lock_tracking = "fatal" -chip_enable_ble = true -chip_generate_link_map_file = true - -chip_system_config_provide_statistics = false -chip_system_config_use_openthread_inet_endpoints = true -chip_with_lwip = false - -chip_enable_icd_server = true -chip_enable_icd_lit = false -chip_enable_icd_dsls = false -chip_persist_subscriptions = true -chip_subscription_timeout_resumption = true - -is_debug = false - -chip_crypto = "platform" -chip_openthread_ftd = false -nxp_enable_ot_cli = false - -chip_with_diag_logs_demo = true diff --git a/examples/contact-sensor-app/nxp/mcxw71/build_overrides b/examples/contact-sensor-app/nxp/mcxw71/build_overrides deleted file mode 120000 index ee19c065d61..00000000000 --- a/examples/contact-sensor-app/nxp/mcxw71/build_overrides +++ /dev/null @@ -1 +0,0 @@ -../../../build_overrides/ \ No newline at end of file diff --git a/examples/contact-sensor-app/nxp/mcxw71/include/config/AppConfig.h b/examples/contact-sensor-app/nxp/mcxw71/include/config/AppConfig.h deleted file mode 100644 index 89f4bf9333c..00000000000 --- a/examples/contact-sensor-app/nxp/mcxw71/include/config/AppConfig.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 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 - -/* ---- App Config ---- */ - -/* ---- Button Manager Config ---- */ -#define BUTTON_MANAGER_FACTORY_RESET_TIMEOUT_MS 6000 - -/* ---- LED Manager Config ---- */ -#define LED_MANAGER_STATUS_LED_INDEX 0 -#define LED_MANAGER_LIGHT_LED_INDEX 1 diff --git a/examples/contact-sensor-app/nxp/mcxw71/include/config/CHIPProjectConfig.h b/examples/contact-sensor-app/nxp/mcxw71/include/config/CHIPProjectConfig.h deleted file mode 100644 index 37f882796d6..00000000000 --- a/examples/contact-sensor-app/nxp/mcxw71/include/config/CHIPProjectConfig.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2020-2023 Project CHIP Authors - * Copyright (c) 2020 Google LLC. - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Example project configuration file for CHIP. - * - * This is a place to put application or project-specific overrides - * to the default configuration values for general CHIP features. - * - */ - -#pragma once - -// Use hard-coded test certificates already embedded in generic chip code => set it to 0 -// Use real/development certificates => set it to 1 + file the provisioning section from -// the internal flash -#ifndef CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -#define CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA 0 -#endif - -#if CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA - -// VID/PID for product => will be used by Basic Information Cluster -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0x1037 -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0xA401 - -// Set the following define to use the Certification Declaration from below and not use it stored in factory data section -#ifndef CHIP_USE_DEVICE_CONFIG_CERTIFICATION_DECLARATION -#define CHIP_USE_DEVICE_CONFIG_CERTIFICATION_DECLARATION 0 -#endif - -#ifndef CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION -//-> format_version = 1 -//-> vendor_id = 0x1037 -//-> product_id_array = [ 0xA401 ] -//-> device_type_id = 0x0015 -//-> certificate_id = "ZIG20142ZB330003-24" -//-> security_level = 0 -//-> security_information = 0 -//-> version_number = 0x2694 -//-> certification_type = 1 -//-> dac_origin_vendor_id is not present -//-> dac_origin_product_id is not present -#define CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION \ - { \ - 0x30, 0x81, 0xe7, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x81, 0xd9, 0x30, 0x81, 0xd6, \ - 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, \ - 0x44, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x37, 0x04, 0x35, 0x15, 0x24, 0x00, \ - 0x01, 0x25, 0x01, 0x37, 0x10, 0x36, 0x02, 0x05, 0x01, 0xa4, 0x18, 0x24, 0x03, 0x15, 0x2c, 0x04, 0x13, 0x5a, 0x49, \ - 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x34, 0x24, 0x05, \ - 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x76, 0x98, 0x24, 0x08, 0x01, 0x18, 0x31, 0x7c, 0x30, 0x7a, 0x02, 0x01, 0x03, \ - 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04, \ - 0xf3, 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0a, 0x06, \ - 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x46, 0x30, 0x44, 0x02, 0x20, 0x12, 0xec, 0x79, 0xdc, \ - 0x03, 0xd3, 0x4f, 0xf9, 0x79, 0xef, 0x56, 0x4e, 0x5b, 0x4f, 0xfc, 0xf5, 0xb1, 0x5a, 0xdb, 0xdf, 0xd9, 0xf8, 0x47, \ - 0xff, 0x81, 0xc3, 0x82, 0x2f, 0xa3, 0x2b, 0xb8, 0x3f, 0x02, 0x20, 0x53, 0x0d, 0x5d, 0xbd, 0xc6, 0xa4, 0x80, 0x67, \ - 0x1f, 0x10, 0xfb, 0xab, 0x00, 0x08, 0xee, 0x15, 0xa0, 0x6c, 0x40, 0x97, 0x55, 0x80, 0x28, 0x3e, 0xf3, 0xd9, 0x61, \ - 0x1f, 0x5b, 0x1d, 0x51, 0x02 \ - } - -// All remaining data will be pulled from the provisioning region of flash. -#endif - -#else - -/** - * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID - * - * 0xFFF1: Test vendor. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1 - -/** - * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID - * - */ -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8006 - -// Use a default setup PIN code if one hasn't been provisioned in flash. -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 -#endif - -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 -#endif - -// Use a default pairing code if one hasn't been provisioned in flash. -#define CHIP_DEVICE_CONFIG_USE_TEST_PAIRING_CODE "CHIPUS" - -/** - * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER - * - * Enables the use of a hard-coded default serial number if none - * is found in CHIP NV storage. - */ -#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN" - -#endif // CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA - -/** - * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION - * - * The hardware version number assigned to device or product by the device vendor. This - * number is scoped to the device product id, and typically corresponds to a revision of the - * physical device, a change to its packaging, and/or a change to its marketing presentation. - * This value is generally *not* incremented for device software versions. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 100 - -#ifndef CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING "v0.1.0" -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING - * - * A string identifying the software version running on the device. - * CHIP currently expects the software version to be in the format - * {MAJOR_VERSION}.0d{MINOR_VERSION} - */ -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION NXP_CONFIG_DEVICE_SOFTWARE_VERSION -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "NXP Semiconductors" -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "NXP Demo App" -#endif - -/** - * CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_TIMEOUT - * - * The amount of time in miliseconds after which BLE should change his advertisements - * from fast interval to slow interval. - * - * 30000 (30 secondes). - */ -#define CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_TIMEOUT (30 * 1000) - -/** - * CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT - * - * The amount of time in miliseconds after which BLE advertisement should be disabled, counting - * from the moment of slow advertisement commencement. - * - * Defaults to 9000000 (15 minutes). - */ -#define CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT (15 * 60 * 1000) - -/** - * CONFIG_CHIP_NFC_ONBOARDING_PAYLOAD, CHIP_DEVICE_CONFIG_ENABLE_NFC_ONBOARDING_PAYLOAD - * - * NFC onboarding payload is not supported - */ -#define CONFIG_CHIP_NFC_ONBOARDING_PAYLOAD 0 -#define CHIP_DEVICE_CONFIG_ENABLE_NFC_ONBOARDING_PAYLOAD 0 - -/** - * @def CHIP_CONFIG_MAX_FABRICS - * - * @brief - * Maximum number of fabrics the device can participate in. Each fabric can - * provision the device with its unique operational credentials and manage - * its own access control lists. - */ -#define CHIP_CONFIG_MAX_FABRICS 5 // 5 is the minimum number of supported fabrics - -#define CHIP_DEVICE_CONFIG_ENABLE_SED 1 - -/** - * @def CHIP_DEVICE_CONFIG_KVS_WEAR_STATS - * - * @brief Toggle support for key value store wear stats on or off. - */ -#define CHIP_DEVICE_CONFIG_KVS_WEAR_STATS 0 - -/** - * @def CHIP_IM_MAX_NUM_COMMAND_HANDLER - * - * @brief Defines the maximum number of CommandHandler, limits the number of active commands transactions on server. - */ -#define CHIP_IM_MAX_NUM_COMMAND_HANDLER 2 - -/** - * @def CHIP_IM_MAX_NUM_WRITE_HANDLER - * - * @brief Defines the maximum number of WriteHandler, limits the number of active write transactions on server. - */ -#define CHIP_IM_MAX_NUM_WRITE_HANDLER 2 - -/** - * CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE - * - * For a development build, set the default importance of events to be logged as Debug. - * Since debug is the lowest importance level, this means all standard, critical, info and - * debug importance level vi events get logged. - */ -#if BUILD_RELEASE -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Production -#else -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug -#endif // BUILD_RELEASE - -#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1 - -#if CONFIG_DIAG_LOGS_DEMO -#define CHIP_CONFIG_ENABLE_BDX_LOG_TRANSFER 1 -#define CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE 1024 -#endif diff --git a/examples/contact-sensor-app/nxp/mcxw71/third_party/connectedhomeip b/examples/contact-sensor-app/nxp/mcxw71/third_party/connectedhomeip deleted file mode 120000 index 59307833b4f..00000000000 --- a/examples/contact-sensor-app/nxp/mcxw71/third_party/connectedhomeip +++ /dev/null @@ -1 +0,0 @@ -../../../../.. \ No newline at end of file diff --git a/examples/contact-sensor-app/nxp/mcxw72/BUILD.gn b/examples/contact-sensor-app/nxp/mcxw72/BUILD.gn index 95d4b5cdefa..2c426598597 100644 --- a/examples/contact-sensor-app/nxp/mcxw72/BUILD.gn +++ b/examples/contact-sensor-app/nxp/mcxw72/BUILD.gn @@ -177,7 +177,8 @@ mcxw72_executable("contact_sensor_app") { include_dirs += [ "${common_example_dir}/ota_requestor/include" ] sources += [ "${common_example_dir}/../mcxw71/ota/OtaUtils.cpp", - "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorMultiImage.cpp", + "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorCommon.cpp", + "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorEmptySelfTest.cpp", ] deps += [ "${chip_root}/src/platform/nxp:nxp_ota" ] } diff --git a/examples/contact-sensor-app/nxp/mcxw72/README.md b/examples/contact-sensor-app/nxp/mcxw72/README.md deleted file mode 100644 index c60ee4d126e..00000000000 --- a/examples/contact-sensor-app/nxp/mcxw72/README.md +++ /dev/null @@ -1,213 +0,0 @@ -# Matter `MCXW72` Contact Sensor Example Application - -For generic information related to contact sensor application, please see the -[common README](../README.md). - -- [Matter `MCXW72` Contact Sensor Example Application](#matter-mcxw72-contact-sensor-example-application) - - [Introduction](#introduction) - - [Device UI](#device-ui) - - [Configure `matter-cli`](#configure-matter-cli) - - [Building](#building) - - [Flashing](#flashing) - - [Flashing the `NBU` image with `blhost`](#flashing-the-nbu-image-with-blhost) - - [Flashing the `NBU` image with `JLink`](#flashing-the-nbu-image-with-jlink) - - [Flashing the host image](#flashing-the-host-image) - - [Factory data](#factory-data) - - [OTA](#ota) - -## Introduction - -This is a contact sensor application implemented for an `mcxw72` device. - -The following board was used when testing this Matter reference app for a -`mcxw72` device: - -![MCXW72-EVK](../../../platform/nxp/mcxw72/doc/images/mcxw72evk.png) - -Please see -[`MCXW72` product page](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/mcx-arm-cortex-m/mcx-w-series-microcontrollers/mcx-w72x-secure-and-ultra-low-power-mcus-for-matter-thread-zigbee-and-bluetooth-le:MCX-W72X) -for more information. - -## Device UI - -This reference app is using `matter-cli` to send commands to the board through a -UART interface. - -| interface | role | -| --------- | ---------------------------------- | -| UART0 | Used for logs | -| UART1 | Used for `matter-cli` and flashing | - -The user actions are summarized below: - -| matter-cli command | output | -| ------------------------- | ------------------------ | -| `mattercommissioning on` | Enable BLE advertising | -| `mattercommissioning off` | Disable BLE advertising | -| `matterfactoryreset` | Initiate a factory reset | -| `matterreset` | Reset the device | - -### Additional UART interface - -You need a `USB-UART` bridge to make use of the second UART interface. The pin -configuration is the following: - -- `JP11 pin 1` (UART0 TX) -- `JP12 pin 1` (UART0 RX) -- `J11 pin 4` (GND) - -The state feedback is also provided through LED effects: - -| widget | effect | description | -| ------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------- | -| LED2 | short flash on (50ms on/950ms off) | The device is in an unprovisioned (unpaired) state and is waiting for a commissioner to connect. | -| LED2 | rapid even flashing (100ms period) | The device is in an unprovisioned state and a commissioner is connected via BLE. | -| LED2 | short flash off (950ms on/50ms off) | The device is fully provisioned, but does not yet have full network (Thread) or service connectivity. | -| LED2 | solid on | The device is fully provisioned and has full network and service connectivity. | -| RGB LED | on | The `StateValue` attribute of the `BooleanState` cluster is `true` (simulating detection). | -| RGB LED | off | The `StateValue` attribute of the `BooleanState` cluster is `false` (simulating no detection). | - -The user actions are summarized below: - -| button | action | state | output | -| ------ | ----------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| SW2 | short press | not commissioned | Enable BLE advertising | -| SW2 | long press | NA | Initiate a factory reset (can be cancelled by pressing the button again within the factory reset timeout limit - 6 seconds by default) | -| SW3 | short press | NA | Toggle attribute `StateValue` value | -| SW3 | long press | NA | Clean soft reset of the device (takes into account proper Matter shutdown procedure) | - -## Building - -Manually building requires running the following commands: - -``` -user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_SDK_ROOT= -user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/contact-sensor-app/nxp/mcxw72 -user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/mcxw72$ gn gen out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/mcxw72$ ninja -C out/debug -``` - -Please note that running `gn gen out/debug` without `--args` option will use the -default gn args values found in `args.gni`. - -After a successful build, the `elf` and `srec` files are found in `out/debug/`. -See the files prefixed with `chip-mcxw72-contact-example`. - -## Flashing - -We recommend using [JLink](https://www.segger.com/downloads/jlink/) to flash -both host and `NBU` cores. To support this device, a `JLink` patch shall be -applied, so please contact your NXP liaison for guidance. - -| core | JLink target | -| ----- | ------------------ | -| host | `KW47B42ZB7_M33_0` | -| `NBU` | `KW47B42ZB7_M33_1` | - -Note: `NBU` image should be written only when a new NXP SDK is released. - -### Flashing the `NBU` image with `blhost` - -1. Install - [Secure Provisioning SDK tool](https://www.nxp.com/design/design-center/software/development-software/secure-provisioning-sdk-spsdk:SPSDK) - using Python: - - ``` - pip install spsdk - ``` - - Note: There might be some dependencies that cause conflicts with already - installed Python modules. However, `blhost` tool is still installed and can - be used. - -2. Updating `NBU` Firmware for Wireless examples - - It is necessary to work with the matching `NBU` image for the SDK version of - the application you are working with. This means that when you download your - SDK, prior to loading any wireless SDK example, update your `NBU` image with - the SDK provided binaries: - - `middleware\wireless\ieee-802.15.4\bin\mcxw72\mcxw72_nbu_ble_15_4_dyn.bin` - - 1. Place your device in `ISP` mode: - - - Press and hold `SW4` (`BOOT_CONFIG`) - - Press and hold `SW1` (`RST`) - - Relax `SW1` - - Relax `SW4` - - 2. Once the device is connected, you may find the assigned port by running: - - ``` - nxpdevscan - ``` - - 3. Run the `blhost` command to write the `bin` file: - - ``` - blhost -p write-memory 0x48800000 /middleware/wireless/ieee-802.15.4/bin/mcxw72/mcxw72_nbu_ble_15_4_dyn.bin - - ``` - -### Flashing the `NBU` image with `JLink` - -Steps: - -- Plug `MCXW72-EVK` board into the USB port -- Connect JLink to the device: - ```bash - JLinkExe -device KW47B42ZB7_M33_1 -if SWD -speed 4000 -autoconnect 1 - ``` -- Run the following commands: - ```bash - reset - halt - loadbin /middleware/wireless/ieee-802.15.4/bin/mcxw72/mcxw72_nbu_ble_15_4_dyn.bin 0 - reset - go - quit - ``` - -Note: If running into issues related to board connection, please refer to -[Flashing the `NBU` image with `blhost`](#flashing-the-nbu-image-with-blhost). -This might be needed when the `NBU` core is empty. - -### Flashing the host image - -Host image is the one found under `out/debug/`. It should be written after each -build process. - -Steps: - -- Plug `MCXW72-EVK` board into the USB port -- Connect JLink to the device: - ```bash - JLinkExe -device KW47B42ZB7_M33_0 -if SWD -speed 4000 -autoconnect 1 - ``` -- Run the following commands: - ```bash - reset - halt - loadfile chip-mcxw72-contact-example.srec - reset - go - quit - ``` - -## Factory data - -Factory data is written in `IFR0, sector 1` at a predefined offset, using -`blhost`. The expanded address is `0x2002680`: - -``` -blhost --port flash-erase-region 0x2002680 -blhost --port write-memory 0x2002680 -``` - -where `` is the OS assigned port, `` the length -of factory data binary in bytes and `` the path to the factory -data binary. - -## OTA - -Please see [OTA guide](../../../../docs/guides/nxp/nxp_mcxw71_ota_guide.md). 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 5266bda0d1e..14cec518765 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 @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } 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 ff040132360..7b68bb1e6d8 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 @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/dishwasher-app/dishwasher-common/dishwasher-app.matter b/examples/dishwasher-app/dishwasher-common/dishwasher-app.matter index e5428e98e9b..3e82b5148ea 100644 --- a/examples/dishwasher-app/dishwasher-common/dishwasher-app.matter +++ b/examples/dishwasher-app/dishwasher-common/dishwasher-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/dishwasher-app/silabs/data_model/dishwasher-thread-app.matter b/examples/dishwasher-app/silabs/data_model/dishwasher-thread-app.matter index 6399b7f0f13..399b703f77b 100644 --- a/examples/dishwasher-app/silabs/data_model/dishwasher-thread-app.matter +++ b/examples/dishwasher-app/silabs/data_model/dishwasher-thread-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/dishwasher-app/silabs/data_model/dishwasher-wifi-app.matter b/examples/dishwasher-app/silabs/data_model/dishwasher-wifi-app.matter index bed13d26a93..271a794636f 100644 --- a/examples/dishwasher-app/silabs/data_model/dishwasher-wifi-app.matter +++ b/examples/dishwasher-app/silabs/data_model/dishwasher-wifi-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/energy-gateway-app/commodity-metering/src/CommodityMeteringEventTriggers.cpp b/examples/energy-gateway-app/commodity-metering/src/CommodityMeteringEventTriggers.cpp index 3f03b98a08b..1aec76962ae 100644 --- a/examples/energy-gateway-app/commodity-metering/src/CommodityMeteringEventTriggers.cpp +++ b/examples/energy-gateway-app/commodity-metering/src/CommodityMeteringEventTriggers.cpp @@ -182,10 +182,10 @@ class TestDataManager { if (mInstance) { - mInstance->SetMaximumMeteredQuantities(mMaximumMeteredQuantities); - mInstance->SetMeteredQuantity(mMeteredQuantity); - mInstance->SetMeteredQuantityTimestamp(mMeteredQuantityTimestamp); - mInstance->SetTariffUnit(mTariffUnit); + TEMPORARY_RETURN_IGNORED mInstance->SetMaximumMeteredQuantities(mMaximumMeteredQuantities); + TEMPORARY_RETURN_IGNORED mInstance->SetMeteredQuantity(mMeteredQuantity); + TEMPORARY_RETURN_IGNORED mInstance->SetMeteredQuantityTimestamp(mMeteredQuantityTimestamp); + TEMPORARY_RETURN_IGNORED mInstance->SetTariffUnit(mTariffUnit); } } @@ -228,10 +228,10 @@ class TestDataManager mMaximumMeteredQuantities.SetNonNull(MQSamplePair.second); - mInstance->SetMaximumMeteredQuantities(mMaximumMeteredQuantities); - mInstance->SetMeteredQuantity(nullableList); - mInstance->SetMeteredQuantityTimestamp(mMeteredQuantityTimestamp); - mInstance->SetTariffUnit(mTariffUnit); + TEMPORARY_RETURN_IGNORED mInstance->SetMaximumMeteredQuantities(mMaximumMeteredQuantities); + TEMPORARY_RETURN_IGNORED mInstance->SetMeteredQuantity(nullableList); + TEMPORARY_RETURN_IGNORED mInstance->SetMeteredQuantityTimestamp(mMeteredQuantityTimestamp); + TEMPORARY_RETURN_IGNORED mInstance->SetTariffUnit(mTariffUnit); } public: diff --git a/examples/energy-gateway-app/commodity-price/src/CommodityPriceEventTriggers.cpp b/examples/energy-gateway-app/commodity-price/src/CommodityPriceEventTriggers.cpp index a48c2e6325b..9bf7e72d4b2 100644 --- a/examples/energy-gateway-app/commodity-price/src/CommodityPriceEventTriggers.cpp +++ b/examples/energy-gateway-app/commodity-price/src/CommodityPriceEventTriggers.cpp @@ -72,7 +72,7 @@ void SetTestEventTrigger_PriceUpdate() newPrice.SetNonNull(newPriceStruct); CommodityPriceInstance * inst = GetCommodityPriceInstance(); - inst->SetCurrentPrice(newPrice); + TEMPORARY_RETURN_IGNORED inst->SetCurrentPrice(newPrice); } void SetTestEventTrigger_ForecastUpdate() @@ -138,7 +138,7 @@ void SetTestEventTrigger_ForecastUpdate() DataModel::List forecastList( Span(sForecastEntries, kForecastSize)); - inst->SetForecast(forecastList); // Should now be safe: all memory lives long enough + TEMPORARY_RETURN_IGNORED inst->SetForecast(forecastList); // Should now be safe: all memory lives long enough } bool HandleCommodityPriceTestEventTrigger(uint64_t eventTrigger) diff --git a/examples/energy-gateway-app/commodity-tariff/src/CommodityTariffEventTriggers.cpp b/examples/energy-gateway-app/commodity-tariff/src/CommodityTariffEventTriggers.cpp index 83812a1274f..5784c9de414 100644 --- a/examples/energy-gateway-app/commodity-tariff/src/CommodityTariffEventTriggers.cpp +++ b/examples/energy-gateway-app/commodity-tariff/src/CommodityTariffEventTriggers.cpp @@ -81,7 +81,7 @@ void TestTimeManager::InitializeMockClock(uint32_t aInitialTimeValue_s) if (err == CHIP_NO_ERROR) { - pMockClock->SetClock_RealTime(realTime_us); + TEMPORARY_RETURN_IGNORED pMockClock->SetClock_RealTime(realTime_us); // Also set monotonic time to maintain consistency auto monotonicTime = std::chrono::duration_cast(realTime_us); @@ -93,7 +93,7 @@ void TestTimeManager::InitializeMockClock(uint32_t aInitialTimeValue_s) { // Fallback: use a reasonable default time if real time is unavailable Microseconds64 defaultTime(std::chrono::seconds(1704067200)); // Jan 1, 2024 - pMockClock->SetClock_RealTime(defaultTime); + TEMPORARY_RETURN_IGNORED pMockClock->SetClock_RealTime(defaultTime); pMockClock->SetMonotonic(std::chrono::duration_cast(defaultTime)); ChipLogProgress(DeviceLayer, "Mock clock initialized with default time"); @@ -125,14 +125,14 @@ void TestTimeManager::AdvanceMockTime(Seconds32 offset) // Get current mock time Microseconds64 currentTime, newTime; - pMockClock->GetClock_RealTime(currentTime); + TEMPORARY_RETURN_IGNORED pMockClock->GetClock_RealTime(currentTime); // Update both real time and monotonic time consistently pMockClock->AdvanceRealTime(std::chrono::duration_cast(offset)); pMockClock->AdvanceMonotonic(std::chrono::duration_cast(offset)); // Update base time reference - pMockClock->GetClock_RealTime(newTime); + TEMPORARY_RETURN_IGNORED pMockClock->GetClock_RealTime(newTime); ChipLogProgress(DeviceLayer, "Advanced mock time: %" PRIu32 "s -> %" PRIu32 "s (+%" PRIu32 "s)", std::chrono::duration_cast(currentTime).count(), @@ -231,15 +231,16 @@ void SetTestEventTrigger_TariffDataUpdated() }; // Process optional attributes - process_attribute(dg->GetMgmtObj(CommodityTariffAttrTypeEnum::kDefaultRandomizationOffset), - tariff_preset.DefaultRandomizationOffset, "DefaultRandomizationOffset", false); - process_attribute(dg->GetMgmtObj(CommodityTariffAttrTypeEnum::kDefaultRandomizationType), - tariff_preset.DefaultRandomizationType, "DefaultRandomizationType", false); - process_attribute(dg->GetMgmtObj(CommodityTariffAttrTypeEnum::kDayPatterns), tariff_preset.DayPatterns, "DayPatterns", false); - process_attribute(dg->GetMgmtObj(CommodityTariffAttrTypeEnum::kIndividualDays), tariff_preset.IndividualDays, "IndividualDays", - false); - process_attribute(dg->GetMgmtObj(CommodityTariffAttrTypeEnum::kCalendarPeriods), tariff_preset.CalendarPeriods, - "CalendarPeriods", false); + RETURN_SAFELY_IGNORED process_attribute(dg->GetMgmtObj(CommodityTariffAttrTypeEnum::kDefaultRandomizationOffset), + tariff_preset.DefaultRandomizationOffset, "DefaultRandomizationOffset", false); + RETURN_SAFELY_IGNORED process_attribute(dg->GetMgmtObj(CommodityTariffAttrTypeEnum::kDefaultRandomizationType), + tariff_preset.DefaultRandomizationType, "DefaultRandomizationType", false); + RETURN_SAFELY_IGNORED process_attribute(dg->GetMgmtObj(CommodityTariffAttrTypeEnum::kDayPatterns), tariff_preset.DayPatterns, + "DayPatterns", false); + RETURN_SAFELY_IGNORED process_attribute(dg->GetMgmtObj(CommodityTariffAttrTypeEnum::kIndividualDays), + tariff_preset.IndividualDays, "IndividualDays", false); + RETURN_SAFELY_IGNORED process_attribute(dg->GetMgmtObj(CommodityTariffAttrTypeEnum::kCalendarPeriods), + tariff_preset.CalendarPeriods, "CalendarPeriods", false); // Process mandatory attributes CHIP_ERROR err = CHIP_NO_ERROR; diff --git a/examples/energy-gateway-app/commodity-tariff/src/CommodityTariffInstance.cpp b/examples/energy-gateway-app/commodity-tariff/src/CommodityTariffInstance.cpp index b018c14f96d..8dfd4e8a5f3 100644 --- a/examples/energy-gateway-app/commodity-tariff/src/CommodityTariffInstance.cpp +++ b/examples/energy-gateway-app/commodity-tariff/src/CommodityTariffInstance.cpp @@ -52,14 +52,14 @@ void CommodityTariffInstance::ScheduleTariffTimeUpdate() { constexpr auto pollInterval = kTimerPollIntervalInSec * 1_s; - DeviceLayer::SystemLayer().StartTimer( + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().StartTimer( pollInterval, [](System::Layer *, void * context) { static_cast(context)->TariffTimeUpdCb(); }, this); } void CommodityTariffInstance::CancelTariffTimeUpdate() { - DeviceLayer::SystemLayer().CancelTimer( + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().CancelTimer( [](System::Layer *, void * context) { static_cast(context)->TariffTimeUpdCb(); }, this); } diff --git a/examples/energy-gateway-app/common/src/EnergyGatewayAppCommonMain.cpp b/examples/energy-gateway-app/common/src/EnergyGatewayAppCommonMain.cpp index 9b158bb80aa..d95c0f13d0c 100644 --- a/examples/energy-gateway-app/common/src/EnergyGatewayAppCommonMain.cpp +++ b/examples/energy-gateway-app/common/src/EnergyGatewayAppCommonMain.cpp @@ -78,8 +78,9 @@ void ElectricalEnergyTariffInit() VerifyOrDie(ElectricalGridConditionsInit(kElectricalEnergyTariffEndpointId) == CHIP_NO_ERROR); // set the descriptor TagList to include "ElectricalEnergy" and "Current" (to indicate the ActiveTariff) - SetTagList(kElectricalEnergyTariffEndpointId, - Span(electricalEnergyTariffTagList)); + TEMPORARY_RETURN_IGNORED SetTagList( + kElectricalEnergyTariffEndpointId, + Span(electricalEnergyTariffTagList)); } void ElectricalEnergyTariffShutdown() diff --git a/examples/energy-gateway-app/electrical-grid-conditions/src/ElectricalGridConditionsEventTriggers.cpp b/examples/energy-gateway-app/electrical-grid-conditions/src/ElectricalGridConditionsEventTriggers.cpp index 3c63f45c840..c2c77a44bd7 100644 --- a/examples/energy-gateway-app/electrical-grid-conditions/src/ElectricalGridConditionsEventTriggers.cpp +++ b/examples/energy-gateway-app/electrical-grid-conditions/src/ElectricalGridConditionsEventTriggers.cpp @@ -56,7 +56,7 @@ void SetTestEventTrigger_CurrentConditionsUpdate() ChipLogError(Support, "ElectricalGridConditionsInstance not available."); return; } - inst->SetCurrentConditions(newConditions); + TEMPORARY_RETURN_IGNORED inst->SetCurrentConditions(newConditions); } void SetTestEventTrigger_ForecastConditionsUpdate() @@ -110,7 +110,7 @@ void SetTestEventTrigger_ForecastConditionsUpdate() DataModel::List forecastList( Span(sForecastEntries, kForecastSize)); - inst->SetForecastConditions(forecastList); // Should now be safe: all memory lives long enough + TEMPORARY_RETURN_IGNORED inst->SetForecastConditions(forecastList); // Should now be safe: all memory lives long enough } bool HandleElectricalGridConditionsTestEventTrigger(uint64_t eventTrigger) diff --git a/examples/energy-gateway-app/energy-gateway-common/energy-gateway-app.matter b/examples/energy-gateway-app/energy-gateway-common/energy-gateway-app.matter index aa4d0f31a1c..1b870f9c778 100644 --- a/examples/energy-gateway-app/energy-gateway-common/energy-gateway-app.matter +++ b/examples/energy-gateway-app/energy-gateway-common/energy-gateway-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/energy-gateway-app/meter-identification/src/MeterIdentificationEventTriggers.cpp b/examples/energy-gateway-app/meter-identification/src/MeterIdentificationEventTriggers.cpp index 13e1730c942..ee07b4b0998 100644 --- a/examples/energy-gateway-app/meter-identification/src/MeterIdentificationEventTriggers.cpp +++ b/examples/energy-gateway-app/meter-identification/src/MeterIdentificationEventTriggers.cpp @@ -173,21 +173,21 @@ class OldMeterIdentificationAttributes { if (mInstance) { - mInstance->SetMeterType(mMeterType); - mInstance->SetPointOfDelivery(mPointOfDelivery); - mInstance->SetMeterSerialNumber(mMeterSerialNumber); - mInstance->SetProtocolVersion(mProtocolVersion); - mInstance->SetPowerThreshold(mPowerThreshold); + TEMPORARY_RETURN_IGNORED mInstance->SetMeterType(mMeterType); + TEMPORARY_RETURN_IGNORED mInstance->SetPointOfDelivery(mPointOfDelivery); + TEMPORARY_RETURN_IGNORED mInstance->SetMeterSerialNumber(mMeterSerialNumber); + TEMPORARY_RETURN_IGNORED mInstance->SetProtocolVersion(mProtocolVersion); + TEMPORARY_RETURN_IGNORED mInstance->SetPowerThreshold(mPowerThreshold); } } void UpdAttrsByPresetIdx() { - mInstance->SetMeterType(TestsDataPresets[mPresetsIdx].meterType); - mInstance->SetPointOfDelivery(TestsDataPresets[mPresetsIdx].pointOfDelivery); - mInstance->SetMeterSerialNumber(TestsDataPresets[mPresetsIdx].meterSerialNumber); - mInstance->SetProtocolVersion(TestsDataPresets[mPresetsIdx].protocolVersion); - mInstance->SetPowerThreshold(TestsDataPresets[mPresetsIdx].powerThreshold); + TEMPORARY_RETURN_IGNORED mInstance->SetMeterType(TestsDataPresets[mPresetsIdx].meterType); + TEMPORARY_RETURN_IGNORED mInstance->SetPointOfDelivery(TestsDataPresets[mPresetsIdx].pointOfDelivery); + TEMPORARY_RETURN_IGNORED mInstance->SetMeterSerialNumber(TestsDataPresets[mPresetsIdx].meterSerialNumber); + TEMPORARY_RETURN_IGNORED mInstance->SetProtocolVersion(TestsDataPresets[mPresetsIdx].protocolVersion); + TEMPORARY_RETURN_IGNORED mInstance->SetPowerThreshold(TestsDataPresets[mPresetsIdx].powerThreshold); mPresetsIdx = !mPresetsIdx; } diff --git a/examples/energy-gateway-app/meter-identification/src/MeterIdentificationInstance.cpp b/examples/energy-gateway-app/meter-identification/src/MeterIdentificationInstance.cpp index 9114e017016..62b649939ef 100644 --- a/examples/energy-gateway-app/meter-identification/src/MeterIdentificationInstance.cpp +++ b/examples/energy-gateway-app/meter-identification/src/MeterIdentificationInstance.cpp @@ -36,7 +36,7 @@ void emberAfMeterIdentificationClusterInitCallback(chip::EndpointId endpointId) VerifyOrDie(gMeterIdentificationCluster == nullptr); gMeterIdentificationCluster = std::make_unique(endpointId, chip::BitMask(Feature::kPowerThreshold)); - gMeterIdentificationCluster->Init(); + TEMPORARY_RETURN_IGNORED gMeterIdentificationCluster->Init(); } void emberAfMeterIdentificationClusterShutdownCallback(chip::EndpointId endpointId) diff --git a/examples/energy-management-app/energy-management-common/common/src/EnergyManagementAppCommonMain.cpp b/examples/energy-management-app/energy-management-common/common/src/EnergyManagementAppCommonMain.cpp index d6c16e785f6..141217fe38c 100644 --- a/examples/energy-management-app/energy-management-common/common/src/EnergyManagementAppCommonMain.cpp +++ b/examples/energy-management-app/energy-management-common/common/src/EnergyManagementAppCommonMain.cpp @@ -280,9 +280,9 @@ CHIP_ERROR EnergyManagementCommonClustersInit(chip::EndpointId endpointId) { if (!gCommonClustersInitialized) { - DeviceEnergyManagementInit(endpointId); - ElectricalPowerMeasurementInit(endpointId); - PowerTopologyInit(endpointId); + TEMPORARY_RETURN_IGNORED DeviceEnergyManagementInit(endpointId); + TEMPORARY_RETURN_IGNORED ElectricalPowerMeasurementInit(endpointId); + TEMPORARY_RETURN_IGNORED PowerTopologyInit(endpointId); } VerifyOrReturnError(gDEMDelegate && gDEMInstance, CHIP_ERROR_INCORRECT_STATE); VerifyOrReturnError(gEPMDelegate && gEPMInstance, CHIP_ERROR_INCORRECT_STATE); @@ -342,10 +342,10 @@ void emberAfElectricalEnergyMeasurementClusterInitCallback(chip::EndpointId endp if (gEEMAttrAccess) { - gEEMAttrAccess->Init(); + TEMPORARY_RETURN_IGNORED gEEMAttrAccess->Init(); - SetMeasurementAccuracy(endpointId, accuracy); - SetCumulativeReset(endpointId, MakeOptional(resetStruct)); + TEMPORARY_RETURN_IGNORED SetMeasurementAccuracy(endpointId, accuracy); + TEMPORARY_RETURN_IGNORED SetCumulativeReset(endpointId, MakeOptional(resetStruct)); } } @@ -370,11 +370,11 @@ void EvseApplicationShutdown() ChipLogDetail(AppServer, "Energy Management App (EVSE): EvseApplicationShutdown()"); /* Shutdown in reverse order that they were created */ - EVSEManufacturerShutdown(); /* Free the EVSEManufacturer */ - PowerTopologyShutdown(); /* Free the PowerTopology */ - ElectricalPowerMeasurementShutdown(); /* Free the Electrical Power Measurement */ - EnergyEvseShutdown(); /* Free the EnergyEvse */ - DeviceEnergyManagementShutdown(); /* Free the DEM */ + TEMPORARY_RETURN_IGNORED EVSEManufacturerShutdown(); /* Free the EVSEManufacturer */ + TEMPORARY_RETURN_IGNORED PowerTopologyShutdown(); /* Free the PowerTopology */ + TEMPORARY_RETURN_IGNORED ElectricalPowerMeasurementShutdown(); /* Free the Electrical Power Measurement */ + TEMPORARY_RETURN_IGNORED EnergyEvseShutdown(); /* Free the EnergyEvse */ + DeviceEnergyManagementShutdown(); /* Free the DEM */ Clusters::DeviceEnergyManagementMode::Shutdown(); Clusters::EnergyEvseMode::Shutdown(); @@ -387,13 +387,13 @@ void WaterHeaterApplicationInit() VerifyOrDie(WhmApplicationInit(endpointId) == CHIP_NO_ERROR); /* For Device Energy Management we need the ESA to be Online and ready to accept commands */ - gDEMDelegate->SetESAState(ESAStateEnum::kOnline); - gDEMDelegate->SetESAType(ESATypeEnum::kWaterHeating); + TEMPORARY_RETURN_IGNORED gDEMDelegate->SetESAState(ESAStateEnum::kOnline); + TEMPORARY_RETURN_IGNORED gDEMDelegate->SetESAType(ESATypeEnum::kWaterHeating); gDEMDelegate->SetDEMManufacturerDelegate(*GetWhmManufacturer()); // Set the abs min and max power - gDEMDelegate->SetAbsMinPower(1200000); // 1.2KW - gDEMDelegate->SetAbsMaxPower(7600000); // 7.6KW + TEMPORARY_RETURN_IGNORED gDEMDelegate->SetAbsMinPower(1200000); // 1.2KW + TEMPORARY_RETURN_IGNORED gDEMDelegate->SetAbsMaxPower(7600000); // 7.6KW } void WaterHeaterApplicationShutdown() @@ -401,10 +401,10 @@ void WaterHeaterApplicationShutdown() ChipLogDetail(AppServer, "Energy Management App (WaterHeater): WaterHeaterShutdown()"); /* Shutdown in reverse order that they were created */ - PowerTopologyShutdown(); /* Free the PowerTopology */ - ElectricalPowerMeasurementShutdown(); /* Free the Energy Meter */ - DeviceEnergyManagementShutdown(); /* Free the DEM */ - WhmApplicationShutdown(); + TEMPORARY_RETURN_IGNORED PowerTopologyShutdown(); /* Free the PowerTopology */ + TEMPORARY_RETURN_IGNORED ElectricalPowerMeasurementShutdown(); /* Free the Energy Meter */ + DeviceEnergyManagementShutdown(); /* Free the DEM */ + TEMPORARY_RETURN_IGNORED WhmApplicationShutdown(); Clusters::DeviceEnergyManagementMode::Shutdown(); Clusters::WaterHeaterMode::Shutdown(); diff --git a/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp b/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp index ada4b8a15ec..0f4a0c48bc8 100644 --- a/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp +++ b/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp @@ -125,9 +125,7 @@ CHIP_ERROR ConfigureForecast(uint16_t numSlots) sForecastStruct.slots = DataModel::List(sSlots, numSlots); - GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); - - return CHIP_NO_ERROR; + return GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); } void SetTestEventTrigger_PowerAdjustment() @@ -174,7 +172,7 @@ void SetTestEventTrigger_ClearForecast() void SetTestEventTrigger_StartTimeAdjustment() { - ConfigureForecast(2); + TEMPORARY_RETURN_IGNORED ConfigureForecast(2); // Get the current forecast ad update the earliestStartTime and latestEndTime sForecastStruct = GetDEMDelegate()->GetForecast().Value(); @@ -200,7 +198,7 @@ void SetTestEventTrigger_StartTimeAdjustment() // Latest end time, in UTC, for the entire Forecast which is > sForecastStruct.endTime sForecastStruct.latestEndTime = Optional(matterEpoch * 3 + 60); - GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); + TEMPORARY_RETURN_IGNORED GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); } void SetTestEventTrigger_StartTimeAdjustmentClear() @@ -214,17 +212,17 @@ void SetTestEventTrigger_StartTimeAdjustmentClear() sForecastStruct.earliestStartTime = NullOptional; sForecastStruct.latestEndTime = NullOptional; - GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); + TEMPORARY_RETURN_IGNORED GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); } void SetTestEventTrigger_UserOptOutOptimization(OptOutStateEnum optOutState) { - GetDEMDelegate()->SetOptOutState(optOutState); + TEMPORARY_RETURN_IGNORED GetDEMDelegate()->SetOptOutState(optOutState); } void SetTestEventTrigger_Pausable() { - ConfigureForecast(2); + TEMPORARY_RETURN_IGNORED ConfigureForecast(2); } void SetTestEventTrigger_PausableNextSlot() @@ -233,12 +231,12 @@ void SetTestEventTrigger_PausableNextSlot() sForecastStruct = GetDEMDelegate()->GetForecast().Value(); sForecastStruct.activeSlotNumber.SetNonNull(1); - GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); + TEMPORARY_RETURN_IGNORED GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); } void SetTestEventTrigger_Forecast() { - ConfigureForecast(2); + TEMPORARY_RETURN_IGNORED ConfigureForecast(2); } void SetTestEventTrigger_ForecastClear() @@ -251,12 +249,12 @@ void SetTestEventTrigger_ForecastClear() sForecastStruct.activeSlotNumber.SetNull(); sForecastStruct.slots = DataModel::List(); - GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); + TEMPORARY_RETURN_IGNORED GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); } void SetTestEventTrigger_ForecastAdjustment() { - ConfigureForecast(2); + TEMPORARY_RETURN_IGNORED ConfigureForecast(2); // The following values need to match the equivalent values in src/python_testing/TC_DEM_2_5.py sForecastStruct = GetDEMDelegate()->GetForecast().Value(); @@ -267,7 +265,7 @@ void SetTestEventTrigger_ForecastAdjustment() sForecastStruct.slots = DataModel::List(sSlots, 2); - GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); + TEMPORARY_RETURN_IGNORED GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); } void SetTestEventTrigger_ForecastAdjustmentNextSlot() @@ -275,12 +273,12 @@ void SetTestEventTrigger_ForecastAdjustmentNextSlot() sForecastStruct = GetDEMDelegate()->GetForecast().Value(); sForecastStruct.activeSlotNumber.SetNonNull(sForecastStruct.activeSlotNumber.Value() + 1); - GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); + TEMPORARY_RETURN_IGNORED GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); } void SetTestEventTrigger_ConstraintBasedAdjustment() { - ConfigureForecast(4); + TEMPORARY_RETURN_IGNORED ConfigureForecast(4); } bool HandleDeviceEnergyManagementTestEventTrigger(uint64_t eventTrigger) diff --git a/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp b/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp index baa28228979..aa045864ae7 100644 --- a/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp +++ b/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp @@ -118,18 +118,18 @@ Status DeviceEnergyManagementDelegate::PowerAdjustRequest(const int64_t powerMw, } } - SetESAState(ESAStateEnum::kPowerAdjustActive); + TEMPORARY_RETURN_IGNORED SetESAState(ESAStateEnum::kPowerAdjustActive); // mPowerAdjustCapabilityStruct is guaranteed to have a value as validated in Instance::HandlePowerAdjustRequest. // If it did not have a value, this method would not have been called. switch (cause) { case AdjustmentCauseEnum::kLocalOptimization: - SetPowerAdjustmentCapabilityPowerAdjustReason(PowerAdjustReasonEnum::kLocalOptimizationAdjustment); + TEMPORARY_RETURN_IGNORED SetPowerAdjustmentCapabilityPowerAdjustReason(PowerAdjustReasonEnum::kLocalOptimizationAdjustment); break; case AdjustmentCauseEnum::kGridOptimization: - SetPowerAdjustmentCapabilityPowerAdjustReason(PowerAdjustReasonEnum::kGridOptimizationAdjustment); + TEMPORARY_RETURN_IGNORED SetPowerAdjustmentCapabilityPowerAdjustReason(PowerAdjustReasonEnum::kGridOptimizationAdjustment); break; default: @@ -176,11 +176,11 @@ void DeviceEnergyManagementDelegate::HandlePowerAdjustRequestFailure() { DeviceLayer::SystemLayer().CancelTimer(PowerAdjustTimerExpiry, this); - SetESAState(ESAStateEnum::kOnline); + TEMPORARY_RETURN_IGNORED SetESAState(ESAStateEnum::kOnline); mPowerAdjustmentInProgress = false; - SetPowerAdjustmentCapabilityPowerAdjustReason(PowerAdjustReasonEnum::kNoAdjustment); + TEMPORARY_RETURN_IGNORED SetPowerAdjustmentCapabilityPowerAdjustReason(PowerAdjustReasonEnum::kNoAdjustment); // TODO // Should we inform the mpDEMManufacturerDelegate that PowerAdjustRequest has failed? @@ -213,17 +213,17 @@ void DeviceEnergyManagementDelegate::HandlePowerAdjustTimerExpiry() // The PowerAdjustment is no longer in progress mPowerAdjustmentInProgress = false; - SetESAState(ESAStateEnum::kOnline); + TEMPORARY_RETURN_IGNORED SetESAState(ESAStateEnum::kOnline); - SetPowerAdjustmentCapabilityPowerAdjustReason(PowerAdjustReasonEnum::kNoAdjustment); + TEMPORARY_RETURN_IGNORED SetPowerAdjustmentCapabilityPowerAdjustReason(PowerAdjustReasonEnum::kNoAdjustment); // Generate a PowerAdjustEnd event - GeneratePowerAdjustEndEvent(CauseEnum::kNormalCompletion); + TEMPORARY_RETURN_IGNORED GeneratePowerAdjustEndEvent(CauseEnum::kNormalCompletion); // Update the forecast with new expected end time if (mpDEMManufacturerDelegate != nullptr) { - mpDEMManufacturerDelegate->HandleDeviceEnergyManagementPowerAdjustCompletion(); + TEMPORARY_RETURN_IGNORED mpDEMManufacturerDelegate->HandleDeviceEnergyManagementPowerAdjustCompletion(); } } @@ -266,10 +266,10 @@ CHIP_ERROR DeviceEnergyManagementDelegate::CancelPowerAdjustRequestAndGenerateEv { DeviceLayer::SystemLayer().CancelTimer(PowerAdjustTimerExpiry, this); - SetESAState(ESAStateEnum::kOnline); + TEMPORARY_RETURN_IGNORED SetESAState(ESAStateEnum::kOnline); mPowerAdjustmentInProgress = false; - SetPowerAdjustmentCapabilityPowerAdjustReason(PowerAdjustReasonEnum::kNoAdjustment); + TEMPORARY_RETURN_IGNORED SetPowerAdjustmentCapabilityPowerAdjustReason(PowerAdjustReasonEnum::kNoAdjustment); CHIP_ERROR err = GeneratePowerAdjustEndEvent(cause); @@ -459,7 +459,7 @@ Status DeviceEnergyManagementDelegate::PauseRequest(const uint32_t durationS, Ad } } - SetESAState(ESAStateEnum::kPaused); + TEMPORARY_RETURN_IGNORED SetESAState(ESAStateEnum::kPaused); // Update the forecaseUpdateReason based on the AdjustmentCause if (cause == AdjustmentCauseEnum::kLocalOptimization) @@ -487,7 +487,7 @@ void DeviceEnergyManagementDelegate::HandlePauseRequestFailure() { DeviceLayer::SystemLayer().CancelTimer(PowerAdjustTimerExpiry, this); - SetESAState(ESAStateEnum::kOnline); + TEMPORARY_RETURN_IGNORED SetESAState(ESAStateEnum::kOnline); mPauseRequestInProgress = false; @@ -520,15 +520,15 @@ void DeviceEnergyManagementDelegate::HandlePauseRequestTimerExpiry() // The PauseRequestment is no longer in progress mPauseRequestInProgress = false; - SetESAState(ESAStateEnum::kOnline); + TEMPORARY_RETURN_IGNORED SetESAState(ESAStateEnum::kOnline); // Generate a Resumed event - GenerateResumedEvent(CauseEnum::kNormalCompletion); + TEMPORARY_RETURN_IGNORED GenerateResumedEvent(CauseEnum::kNormalCompletion); // It is expected the mpDEMManufacturerDelegate will update the forecast with new expected end time if (mpDEMManufacturerDelegate != nullptr) { - mpDEMManufacturerDelegate->HandleDeviceEnergyManagementPauseCompletion(); + TEMPORARY_RETURN_IGNORED mpDEMManufacturerDelegate->HandleDeviceEnergyManagementPauseCompletion(); } } @@ -546,7 +546,7 @@ CHIP_ERROR DeviceEnergyManagementDelegate::CancelPauseRequestAndGenerateEvent(Ca { mPauseRequestInProgress = false; - SetESAState(ESAStateEnum::kOnline); + TEMPORARY_RETURN_IGNORED SetESAState(ESAStateEnum::kOnline); DeviceLayer::SystemLayer().CancelTimer(PauseRequestTimerExpiry, this); diff --git a/examples/energy-management-app/energy-management-common/device-energy-management/src/device-energy-management-mode.cpp b/examples/energy-management-app/energy-management-common/device-energy-management/src/device-energy-management-mode.cpp index 4ba97af82d4..3225985770b 100644 --- a/examples/energy-management-app/energy-management-common/device-energy-management/src/device-energy-management-mode.cpp +++ b/examples/energy-management-app/energy-management-common/device-energy-management/src/device-energy-management-mode.cpp @@ -107,7 +107,7 @@ void emberAfDeviceEnergyManagementModeClusterInitCallback(chip::EndpointId endpo gDeviceEnergyManagementModeDelegate = std::make_unique(); gDeviceEnergyManagementModeInstance = std::make_unique(gDeviceEnergyManagementModeDelegate.get(), endpointId, DeviceEnergyManagementMode::Id, 0); - gDeviceEnergyManagementModeInstance->Init(); + TEMPORARY_RETURN_IGNORED gDeviceEnergyManagementModeInstance->Init(); } void emberAfDeviceEnergyManagementModeClusterShutdownCallback(chip::EndpointId endpointId) diff --git a/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp index f30ecec9cc9..5ad08105fd2 100644 --- a/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp +++ b/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp @@ -70,12 +70,12 @@ CHIP_ERROR EVSEManufacturer::Init(chip::EndpointId powerSourceEndpointId) VerifyOrReturnLogError(dem != nullptr, CHIP_ERROR_UNINITIALIZED); /* For Device Energy Management we need the ESA to be Online and ready to accept commands */ - dem->SetESAState(ESAStateEnum::kOnline); - dem->SetESAType(ESATypeEnum::kEvse); + TEMPORARY_RETURN_IGNORED dem->SetESAState(ESAStateEnum::kOnline); + TEMPORARY_RETURN_IGNORED dem->SetESAType(ESATypeEnum::kEvse); // Set the abs min and max power - dem->SetAbsMinPower(1200000); // 1.2KW - dem->SetAbsMaxPower(7600000); // 7.6KW + TEMPORARY_RETURN_IGNORED dem->SetAbsMinPower(1200000); // 1.2KW + TEMPORARY_RETURN_IGNORED dem->SetAbsMaxPower(7600000); // 7.6KW /* * This is an example implementation for manufacturers to consider @@ -406,16 +406,17 @@ CHIP_ERROR EVSEManufacturer::ComputeChargingSchedule() /* Determine requiredEnergy based on if we support SoC Reporting or fallback to AddedEnergy target */ if (DetermineRequiredEnergy(dg, requiredEnergy_mWh, targetSoC, targetAddedEnergy_mWh) == CHIP_NO_ERROR) { - ComputeStartTime(dg, startTime_epoch_s, tempTargetTime_epoch_s, now_epoch_s, requiredEnergy_mWh); + TEMPORARY_RETURN_IGNORED ComputeStartTime(dg, startTime_epoch_s, tempTargetTime_epoch_s, now_epoch_s, + requiredEnergy_mWh); } } } // Update the attributes to allow a UI to inform the user - dg->SetNextChargeStartTime(startTime_epoch_s); - dg->SetNextChargeTargetTime(targetTime_epoch_s); - dg->SetNextChargeRequiredEnergy(targetAddedEnergy_mWh); - dg->SetNextChargeTargetSoC(targetSoC); + TEMPORARY_RETURN_IGNORED dg->SetNextChargeStartTime(startTime_epoch_s); + TEMPORARY_RETURN_IGNORED dg->SetNextChargeTargetTime(targetTime_epoch_s); + TEMPORARY_RETURN_IGNORED dg->SetNextChargeRequiredEnergy(targetAddedEnergy_mWh); + TEMPORARY_RETURN_IGNORED dg->SetNextChargeTargetSoC(targetSoC); return err; } @@ -462,9 +463,7 @@ CHIP_ERROR EVSEManufacturer::InitializePowerSourceCluster(chip::EndpointId endpo // Note per API - we do not need to maintain the span after the SetEndpointList has been called // since it takes a copy (see power-source-server.cpp) - PowerSourceServer::Instance().SetEndpointList(endpointId, endpointList); - - return CHIP_NO_ERROR; + return PowerSourceServer::Instance().SetEndpointList(endpointId, endpointList); } /** @@ -484,9 +483,9 @@ CHIP_ERROR EVSEManufacturer::SendPowerReading(EndpointId aEndpointId, int64_t aA ElectricalPowerMeasurementDelegate * dg = mn->GetEPMDelegate(); VerifyOrReturnError(dg != nullptr, CHIP_ERROR_UNINITIALIZED); - dg->SetActivePower(MakeNullable(aActivePower_mW)); - dg->SetVoltage(MakeNullable(aVoltage_mV)); - dg->SetActiveCurrent(MakeNullable(aActiveCurrent_mA)); + TEMPORARY_RETURN_IGNORED dg->SetActivePower(MakeNullable(aActivePower_mW)); + TEMPORARY_RETURN_IGNORED dg->SetVoltage(MakeNullable(aVoltage_mV)); + TEMPORARY_RETURN_IGNORED dg->SetActiveCurrent(MakeNullable(aActiveCurrent_mA)); return CHIP_NO_ERROR; } @@ -662,12 +661,12 @@ void EVSEManufacturer::ApplicationCallbackHandler(const EVSECbInfo * cb, intptr_ { case EVSECallbackType::StateChanged: ChipLogProgress(AppServer, "EVSE callback - state changed"); - pClass->ComputeChargingSchedule(); + TEMPORARY_RETURN_IGNORED pClass->ComputeChargingSchedule(); break; case EVSECallbackType::ChargeCurrentChanged: ChipLogProgress(AppServer, "EVSE callback - maxChargeCurrent changed to %ld", static_cast(cb->ChargingCurrent.maximumChargeCurrent)); - pClass->ComputeChargingSchedule(); + TEMPORARY_RETURN_IGNORED pClass->ComputeChargingSchedule(); pClass->UpdateEVFakeReadings(cb->ChargingCurrent.maximumChargeCurrent); break; case EVSECallbackType::DischargeCurrentChanged: @@ -688,7 +687,7 @@ void EVSEManufacturer::ApplicationCallbackHandler(const EVSECbInfo * cb, intptr_ case EVSECallbackType::ChargingPreferencesChanged: ChipLogProgress(AppServer, "EVSE callback - ChargingPreferencesChanged"); - pClass->ComputeChargingSchedule(); + TEMPORARY_RETURN_IGNORED pClass->ComputeChargingSchedule(); break; default: diff --git a/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseDelegateImpl.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseDelegateImpl.cpp index 38dec12ddbe..7a87ad9ac73 100644 --- a/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseDelegateImpl.cpp +++ b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseDelegateImpl.cpp @@ -41,11 +41,11 @@ Status EnergyEvseDelegate::Disable() DataModel::Nullable disableTime(0); /* update ChargingEnabledUntil & DischargingEnabledUntil to show 0 */ - SetChargingEnabledUntil(disableTime); - SetDischargingEnabledUntil(disableTime); + TEMPORARY_RETURN_IGNORED SetChargingEnabledUntil(disableTime); + TEMPORARY_RETURN_IGNORED SetDischargingEnabledUntil(disableTime); /* update MinimumChargeCurrent & MaximumChargeCurrent to 0 */ - SetMinimumChargeCurrent(0); + TEMPORARY_RETURN_IGNORED SetMinimumChargeCurrent(0); mMaximumChargingCurrentLimitFromCommand = 0; ComputeMaxChargeCurrentLimit(); @@ -91,18 +91,18 @@ Status EnergyEvseDelegate::EnableCharging(const DataModel::Nullable & { /* Charging enabled indefinitely */ ChipLogProgress(AppServer, "Charging enabled indefinitely"); - SetChargingEnabledUntil(chargingEnabledUntil); + TEMPORARY_RETURN_IGNORED SetChargingEnabledUntil(chargingEnabledUntil); } else { /* check chargingEnabledUntil is in the future */ ChipLogProgress(AppServer, "Charging enabled until: %lu", static_cast(chargingEnabledUntil.Value())); - SetChargingEnabledUntil(chargingEnabledUntil); + TEMPORARY_RETURN_IGNORED SetChargingEnabledUntil(chargingEnabledUntil); } /* If it looks ok, store the min & max charging current */ mMaximumChargingCurrentLimitFromCommand = maximumChargeCurrent; - SetMinimumChargeCurrent(minimumChargeCurrent); + TEMPORARY_RETURN_IGNORED SetMinimumChargeCurrent(minimumChargeCurrent); // TODO persist these to KVS ComputeMaxChargeCurrentLimit(); @@ -131,13 +131,13 @@ Status EnergyEvseDelegate::EnableDischarging(const DataModel::Nullable { /* Discharging enabled indefinitely */ ChipLogProgress(AppServer, "Discharging enabled indefinitely"); - SetDischargingEnabledUntil(dischargingEnabledUntil); + TEMPORARY_RETURN_IGNORED SetDischargingEnabledUntil(dischargingEnabledUntil); } else { ChipLogProgress(AppServer, "Discharging enabled until: %lu", static_cast(dischargingEnabledUntil.Value())); - SetDischargingEnabledUntil(dischargingEnabledUntil); + TEMPORARY_RETURN_IGNORED SetDischargingEnabledUntil(dischargingEnabledUntil); } /* If it looks ok, store the max discharging current */ @@ -199,10 +199,10 @@ void EnergyEvseDelegate::HandleEnabledStateExpiration(uint32_t matterEpochSecond if (chargingExpired) { // set to zero to indicate disabled - SetChargingEnabledUntil(DataModel::Nullable(0)); + TEMPORARY_RETURN_IGNORED SetChargingEnabledUntil(DataModel::Nullable(0)); // update MinimumChargeCurrent & MaximumChargeCurrent to 0 - SetMinimumChargeCurrent(0); + TEMPORARY_RETURN_IGNORED SetMinimumChargeCurrent(0); mMaximumChargingCurrentLimitFromCommand = 0; ComputeMaxChargeCurrentLimit(); @@ -210,7 +210,7 @@ void EnergyEvseDelegate::HandleEnabledStateExpiration(uint32_t matterEpochSecond // Change to discharging-only if discharging is still enabled if (!dischargingExpired) { - SetSupplyState(SupplyStateEnum::kDischargingEnabled); + TEMPORARY_RETURN_IGNORED SetSupplyState(SupplyStateEnum::kDischargingEnabled); } else { @@ -222,7 +222,7 @@ void EnergyEvseDelegate::HandleEnabledStateExpiration(uint32_t matterEpochSecond if (dischargingExpired) { // set to zero to indicate disabled - SetDischargingEnabledUntil(DataModel::Nullable(0)); + TEMPORARY_RETURN_IGNORED SetDischargingEnabledUntil(DataModel::Nullable(0)); // update MaximumDischargeCurrent to 0 mMaximumDischargingCurrentLimitFromCommand = 0; @@ -231,7 +231,7 @@ void EnergyEvseDelegate::HandleEnabledStateExpiration(uint32_t matterEpochSecond // Change to charging-only if charging is still enabled if (!chargingExpired) { - SetSupplyState(SupplyStateEnum::kChargingEnabled); + TEMPORARY_RETURN_IGNORED SetSupplyState(SupplyStateEnum::kChargingEnabled); } else { @@ -283,8 +283,8 @@ Status EnergyEvseDelegate::ScheduleCheckOnEnabledTimeout() if (err == CHIP_ERROR_REAL_TIME_NOT_SYNCED) { // Real time isn't sync'd - check again in 30 seconds - DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(kPeriodicCheckIntervalRealTimeClockNotSynced_sec), - EvseCheckTimerExpiry, this); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().StartTimer( + System::Clock::Seconds32(kPeriodicCheckIntervalRealTimeClockNotSynced_sec), EvseCheckTimerExpiry, this); return Status::Success; } @@ -298,7 +298,7 @@ Status EnergyEvseDelegate::ScheduleCheckOnEnabledTimeout() // Timer hasn't expired yet - schedule future check uint32_t delta = enabledUntilTime.Value() - matterEpochSeconds; ChipLogDetail(AppServer, "Setting EVSE Enable check timer for %lu seconds", static_cast(delta)); - DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(delta), EvseCheckTimerExpiry, this); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(delta), EvseCheckTimerExpiry, this); return Status::Success; } @@ -351,7 +351,7 @@ Status EnergyEvseDelegate::StartDiagnostics() } // Update the SupplyState - this will automatically callback the Application StateChanged callback - SetSupplyState(SupplyStateEnum::kDisabledDiagnostics); + TEMPORARY_RETURN_IGNORED SetSupplyState(SupplyStateEnum::kDisabledDiagnostics); return Status::Success; } @@ -688,7 +688,7 @@ Status EnergyEvseDelegate::HwSetFault(FaultStateEnum newFaultState) SendFaultEvent(newFaultState); /* Updated FaultState before we call into the handlers */ - SetFaultState(newFaultState); + TEMPORARY_RETURN_IGNORED SetFaultState(newFaultState); if (newFaultState == FaultStateEnum::kNoError) { @@ -799,7 +799,7 @@ Status EnergyEvseDelegate::HwDiagnosticsComplete() /* Restore the SupplyState to Disabled (per spec) - client will need to * re-enable charging or discharging to get out of this state */ - SetSupplyState(SupplyStateEnum::kDisabled); + TEMPORARY_RETURN_IGNORED SetSupplyState(SupplyStateEnum::kDisabled); return Status::Success; } @@ -871,7 +871,7 @@ Status EnergyEvseDelegate::HandleEVPluggedInEvent() SendEVConnectedEvent(); /* Set the state to either PluggedInNoDemand or PluggedInDemand as indicated by mHwState */ - SetState(mHwState); + TEMPORARY_RETURN_IGNORED SetState(mHwState); } // else we are already plugged in - ignore return Status::Success; @@ -891,7 +891,7 @@ Status EnergyEvseDelegate::HandleEVNotDetectedEvent() // TODO get energy meter readings - #35370 mSession.StopSession(mEndpointId, 0, 0); SendEVNotDetectedEvent(); - SetState(StateEnum::kNotPluggedIn); + TEMPORARY_RETURN_IGNORED SetState(StateEnum::kNotPluggedIn); return Status::Success; } @@ -906,7 +906,7 @@ Status EnergyEvseDelegate::HandleEVNoDemandEvent() SendEnergyTransferStoppedEvent(EnergyTransferStoppedReasonEnum::kEVStopped); } /* We must still be plugged in to get here - so no need to check if we are plugged in! */ - SetState(StateEnum::kPluggedInNoDemand); + TEMPORARY_RETURN_IGNORED SetState(StateEnum::kPluggedInNoDemand); return Status::Success; } Status EnergyEvseDelegate::HandleEVDemandEvent() @@ -916,12 +916,12 @@ Status EnergyEvseDelegate::HandleEVDemandEvent() { case SupplyStateEnum::kChargingEnabled: ComputeMaxChargeCurrentLimit(); - SetState(StateEnum::kPluggedInCharging); + TEMPORARY_RETURN_IGNORED SetState(StateEnum::kPluggedInCharging); SendEnergyTransferStartedEvent(); break; case SupplyStateEnum::kDischargingEnabled: ComputeMaxDischargeCurrentLimit(); - SetState(StateEnum::kPluggedInDischarging); + TEMPORARY_RETURN_IGNORED SetState(StateEnum::kPluggedInDischarging); SendEnergyTransferStartedEvent(); break; case SupplyStateEnum::kEnabled: @@ -933,7 +933,7 @@ Status EnergyEvseDelegate::HandleEVDemandEvent() */ ComputeMaxChargeCurrentLimit(); ComputeMaxDischargeCurrentLimit(); - SetState(StateEnum::kPluggedInCharging); + TEMPORARY_RETURN_IGNORED SetState(StateEnum::kPluggedInCharging); SendEnergyTransferStartedEvent(); break; case SupplyStateEnum::kDisabled: @@ -941,7 +941,7 @@ Status EnergyEvseDelegate::HandleEVDemandEvent() case SupplyStateEnum::kDisabledDiagnostics: /* We must be plugged in, and the event is asking for demand * but we can't charge or discharge now - leave it as kPluggedInDemand */ - SetState(StateEnum::kPluggedInDemand); + TEMPORARY_RETURN_IGNORED SetState(StateEnum::kPluggedInDemand); break; case SupplyStateEnum::kUnknownEnumValue: ChipLogError(AppServer, "EVSE: HandleEVDemandEvent called in unexpected SupplyState"); @@ -981,14 +981,14 @@ Status EnergyEvseDelegate::HandleChargingEnabledEvent() { case SupplyStateEnum::kDisabled: // it was kDisabled, then the state becomes kChargingEnabled - SetSupplyState(SupplyStateEnum::kChargingEnabled); + TEMPORARY_RETURN_IGNORED SetSupplyState(SupplyStateEnum::kChargingEnabled); break; case SupplyStateEnum::kChargingEnabled: // No change break; case SupplyStateEnum::kDischargingEnabled: // If the SupplyState was already kDischargingEnabled the state becomes kEnabled - SetSupplyState(SupplyStateEnum::kEnabled); + TEMPORARY_RETURN_IGNORED SetSupplyState(SupplyStateEnum::kEnabled); break; case SupplyStateEnum::kDisabledError: case SupplyStateEnum::kDisabledDiagnostics: @@ -1008,7 +1008,7 @@ Status EnergyEvseDelegate::HandleChargingEnabledEvent() break; case StateEnum::kPluggedInDemand: ComputeMaxChargeCurrentLimit(); - SetState(StateEnum::kPluggedInCharging); + TEMPORARY_RETURN_IGNORED SetState(StateEnum::kPluggedInCharging); SendEnergyTransferStartedEvent(); break; case StateEnum::kPluggedInCharging: @@ -1039,11 +1039,11 @@ Status EnergyEvseDelegate::HandleDischargingEnabledEvent() { case SupplyStateEnum::kDisabled: // it was kDisabled, then the state becomes kDischargingEnabled - SetSupplyState(SupplyStateEnum::kDischargingEnabled); + TEMPORARY_RETURN_IGNORED SetSupplyState(SupplyStateEnum::kDischargingEnabled); break; case SupplyStateEnum::kChargingEnabled: // If the SupplyState was already kChargingEnabled the state becomes kEnabled - SetSupplyState(SupplyStateEnum::kEnabled); + TEMPORARY_RETURN_IGNORED SetSupplyState(SupplyStateEnum::kEnabled); break; case SupplyStateEnum::kDischargingEnabled: // No change @@ -1089,7 +1089,7 @@ Status EnergyEvseDelegate::HandleDisabledEvent() } /* update SupplyState to disabled */ - SetSupplyState(SupplyStateEnum::kDisabled); + TEMPORARY_RETURN_IGNORED SetSupplyState(SupplyStateEnum::kDisabled); switch (mState) { @@ -1100,7 +1100,7 @@ Status EnergyEvseDelegate::HandleDisabledEvent() case StateEnum::kPluggedInCharging: case StateEnum::kPluggedInDischarging: SendEnergyTransferStoppedEvent(EnergyTransferStoppedReasonEnum::kEVSEStopped); - SetState(mHwState); + TEMPORARY_RETURN_IGNORED SetState(mHwState); break; default: break; @@ -1132,8 +1132,8 @@ Status EnergyEvseDelegate::HandleFaultRaised() } /* Update State & SupplyState */ - SetState(StateEnum::kFault); - SetSupplyState(SupplyStateEnum::kDisabledError); + TEMPORARY_RETURN_IGNORED SetState(StateEnum::kFault); + TEMPORARY_RETURN_IGNORED SetSupplyState(SupplyStateEnum::kDisabledError); return Status::Success; } @@ -1149,8 +1149,8 @@ Status EnergyEvseDelegate::HandleFaultCleared() /* Restore the State and SupplyState back to old values once all the faults have cleared * Changing the State should notify the application, so it can continue charging etc */ - SetState(mStateBeforeFault); - SetSupplyState(mSupplyStateBeforeFault); + TEMPORARY_RETURN_IGNORED SetState(mStateBeforeFault); + TEMPORARY_RETURN_IGNORED SetSupplyState(mSupplyStateBeforeFault); /* put back the sentinel to catch new faults if more are raised */ mStateBeforeFault = StateEnum::kUnknownEnumValue; @@ -1554,7 +1554,7 @@ CHIP_ERROR EnergyEvseDelegate::SetChargingEnabledUntil(DataModel::NullableWriteScalarValue(path, mChargingEnabledUntil); + TEMPORARY_RETURN_IGNORED GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mChargingEnabledUntil); MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, ChargingEnabledUntil::Id); } @@ -1586,7 +1586,7 @@ CHIP_ERROR EnergyEvseDelegate::SetDischargingEnabledUntil(DataModel::NullableWriteScalarValue(path, mDischargingEnabledUntil); + TEMPORARY_RETURN_IGNORED GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mDischargingEnabledUntil); MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, DischargingEnabledUntil::Id); } @@ -1695,7 +1695,7 @@ CHIP_ERROR EnergyEvseDelegate::SetUserMaximumChargeCurrent(int64_t newValue) // Write new value to persistent storage. ConcreteAttributePath path = ConcreteAttributePath(mEndpointId, EnergyEvse::Id, UserMaximumChargeCurrent::Id); - GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mUserMaximumChargeCurrent); + TEMPORARY_RETURN_IGNORED GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mUserMaximumChargeCurrent); MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, UserMaximumChargeCurrent::Id); } @@ -1725,7 +1725,7 @@ CHIP_ERROR EnergyEvseDelegate::SetRandomizationDelayWindow(uint32_t newValue) // Write new value to persistent storage. ConcreteAttributePath path = ConcreteAttributePath(mEndpointId, EnergyEvse::Id, RandomizationDelayWindow::Id); - GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mRandomizationDelayWindow); + TEMPORARY_RETURN_IGNORED GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mRandomizationDelayWindow); MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, RandomizationDelayWindow::Id); } @@ -1860,7 +1860,7 @@ CHIP_ERROR EnergyEvseDelegate::SetApproximateEVEfficiency(DataModel::NullableWriteScalarValue(path, mApproximateEVEfficiency); + TEMPORARY_RETURN_IGNORED GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mApproximateEVEfficiency); MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, ApproximateEVEfficiency::Id); } @@ -2001,7 +2001,7 @@ void EvseSession::StartSession(EndpointId endpointId, int64_t chargingMeterValue // Write values to persistent storage. ConcreteAttributePath path = ConcreteAttributePath(endpointId, EnergyEvse::Id, SessionID::Id); - GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mSessionID); + TEMPORARY_RETURN_IGNORED GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mSessionID); // TODO persist mStartTime // TODO persist mSessionEnergyChargedAtStart diff --git a/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseEventTriggers.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseEventTriggers.cpp index 21676f76bd6..9f5ef148b43 100644 --- a/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseEventTriggers.cpp +++ b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseEventTriggers.cpp @@ -62,7 +62,7 @@ void SetTestEventTrigger_BasicFunctionality() dg->HwSetMaxHardwareChargeCurrentLimit(32000); dg->HwSetMaxHardwareDischargeCurrentLimit(32000); dg->HwSetCircuitCapacity(32000); - dg->SetUserMaximumChargeCurrent(32000); + TEMPORARY_RETURN_IGNORED dg->SetUserMaximumChargeCurrent(32000); dg->HwSetState(StateEnum::kNotPluggedIn); } void SetTestEventTrigger_BasicFunctionalityClear() @@ -72,7 +72,7 @@ void SetTestEventTrigger_BasicFunctionalityClear() dg->HwSetMaxHardwareChargeCurrentLimit(sEVSETestEventSaveData.mOldMaxHardwareChargeCurrentLimit); dg->HwSetMaxHardwareDischargeCurrentLimit(sEVSETestEventSaveData.mOldMaxHardwareDischargeCurrentLimit); dg->HwSetCircuitCapacity(sEVSETestEventSaveData.mOldCircuitCapacity); - dg->SetUserMaximumChargeCurrent(sEVSETestEventSaveData.mOldUserMaximumChargeCurrent); + TEMPORARY_RETURN_IGNORED dg->SetUserMaximumChargeCurrent(sEVSETestEventSaveData.mOldUserMaximumChargeCurrent); dg->HwSetState(sEVSETestEventSaveData.mOldHwStateBasic); } void SetTestEventTrigger_EVPluggedIn() @@ -145,15 +145,15 @@ void SetTestEventTrigger_EVSESetSoCLow() { // Set SoC 20%, 70kWh BatterySize EnergyEvseDelegate * dg = GetEvseDelegate(); - dg->SetStateOfCharge(20); - dg->SetBatteryCapacity(70000000); + TEMPORARY_RETURN_IGNORED dg->SetStateOfCharge(20); + TEMPORARY_RETURN_IGNORED dg->SetBatteryCapacity(70000000); } void SetTestEventTrigger_EVSESetSoCHigh() { // Set SoC 95%, 70kWh BatterySize EnergyEvseDelegate * dg = GetEvseDelegate(); - dg->SetStateOfCharge(95); - dg->SetBatteryCapacity(70000000); + TEMPORARY_RETURN_IGNORED dg->SetStateOfCharge(95); + TEMPORARY_RETURN_IGNORED dg->SetBatteryCapacity(70000000); } void SetTestEventTrigger_EVSESetSoCClear() { @@ -161,8 +161,8 @@ void SetTestEventTrigger_EVSESetSoCClear() EnergyEvseDelegate * dg = GetEvseDelegate(); DataModel::Nullable noSoC; DataModel::Nullable noBatteryCapacity; - dg->SetStateOfCharge(noSoC); - dg->SetBatteryCapacity(noBatteryCapacity); + TEMPORARY_RETURN_IGNORED dg->SetStateOfCharge(noSoC); + TEMPORARY_RETURN_IGNORED dg->SetBatteryCapacity(noBatteryCapacity); } void SetTestEventTrigger_EVSESetVehicleID() { diff --git a/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseMain.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseMain.cpp index bd3c3fa36b8..4b53ce675e5 100644 --- a/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseMain.cpp +++ b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseMain.cpp @@ -202,7 +202,7 @@ CHIP_ERROR EVSEManufacturerShutdown() if (gEvseManufacturer) { /* Shutdown the EVSEManufacturer */ - gEvseManufacturer->Shutdown(); + TEMPORARY_RETURN_IGNORED gEvseManufacturer->Shutdown(); gEvseManufacturer.reset(); } diff --git a/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseManager.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseManager.cpp index 31cd574003a..b064ea02862 100644 --- a/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseManager.cpp +++ b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseManager.cpp @@ -49,7 +49,7 @@ CHIP_ERROR EnergyEvseManager::LoadPersistentAttributes() if (err == CHIP_NO_ERROR) { ChipLogDetail(AppServer, "EVSE: successfully loaded ChargingEnabledUntil from NVM"); - mDelegate->SetChargingEnabledUntil(tempChargingEnabledUntil); + TEMPORARY_RETURN_IGNORED mDelegate->SetChargingEnabledUntil(tempChargingEnabledUntil); } else { @@ -63,7 +63,7 @@ CHIP_ERROR EnergyEvseManager::LoadPersistentAttributes() if (err == CHIP_NO_ERROR) { ChipLogDetail(AppServer, "EVSE: successfully loaded DischargingEnabledUntil from NVM"); - mDelegate->SetDischargingEnabledUntil(tempDischargingEnabledUntil); + TEMPORARY_RETURN_IGNORED mDelegate->SetDischargingEnabledUntil(tempDischargingEnabledUntil); } else { @@ -77,7 +77,7 @@ CHIP_ERROR EnergyEvseManager::LoadPersistentAttributes() if (err == CHIP_NO_ERROR) { ChipLogDetail(AppServer, "EVSE: successfully loaded UserMaximumChargeCurrent from NVM"); - mDelegate->SetUserMaximumChargeCurrent(tempUserMaximumChargeCurrent); + TEMPORARY_RETURN_IGNORED mDelegate->SetUserMaximumChargeCurrent(tempUserMaximumChargeCurrent); } else { @@ -91,7 +91,7 @@ CHIP_ERROR EnergyEvseManager::LoadPersistentAttributes() if (err == CHIP_NO_ERROR) { ChipLogDetail(AppServer, "EVSE: successfully loaded RandomizationDelayWindow from NVM"); - mDelegate->SetRandomizationDelayWindow(tempRandomizationDelayWindow); + TEMPORARY_RETURN_IGNORED mDelegate->SetRandomizationDelayWindow(tempRandomizationDelayWindow); } else { @@ -105,7 +105,7 @@ CHIP_ERROR EnergyEvseManager::LoadPersistentAttributes() if (err == CHIP_NO_ERROR) { ChipLogDetail(AppServer, "EVSE: successfully loaded ApproximateEVEfficiency from NVM"); - mDelegate->SetApproximateEVEfficiency(tempApproxEVEfficiency); + TEMPORARY_RETURN_IGNORED mDelegate->SetApproximateEVEfficiency(tempApproxEVEfficiency); } else { diff --git a/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseTargetsStore.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseTargetsStore.cpp index 9793b5c2c6f..d9d73422c83 100644 --- a/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseTargetsStore.cpp +++ b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseTargetsStore.cpp @@ -43,7 +43,7 @@ CHIP_ERROR EvseTargetsDelegate::Init(PersistentStorageDelegate * targetStore) mpTargetStore = targetStore; // Set FabricDelegate - chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(this); + TEMPORARY_RETURN_IGNORED chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(this); return CHIP_NO_ERROR; } @@ -444,7 +444,7 @@ EvseTargetsDelegate::SaveTargets(DataModel::List(writer.GetLengthWritten()); ChipLogProgress(AppServer, "SaveTargets: length written 0x" ChipLogFormatX64, ChipLogValueX64(len)); - writer.Finalize(backingBuffer); + TEMPORARY_RETURN_IGNORED writer.Finalize(backingBuffer); ReturnErrorOnFailure(mpTargetStore->SyncSetKeyValue(spEvseTargetsKeyName, backingBuffer.Get(), static_cast(len))); @@ -454,7 +454,7 @@ EvseTargetsDelegate::SaveTargets(DataModel::ListSyncDeleteKeyValue(spEvseTargetsKeyName); + TEMPORARY_RETURN_IGNORED mpTargetStore->SyncDeleteKeyValue(spEvseTargetsKeyName); // Now reload from persistent storage so that mChargingTargetSchedulesList gets updated (it will be empty) CHIP_ERROR err = LoadTargets(); diff --git a/examples/energy-management-app/energy-management-common/energy-evse/src/energy-evse-mode.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/energy-evse-mode.cpp index 5c1e95fc231..5dbe4c2fc5d 100644 --- a/examples/energy-management-app/energy-management-common/energy-evse/src/energy-evse-mode.cpp +++ b/examples/energy-management-app/energy-management-common/energy-evse/src/energy-evse-mode.cpp @@ -98,7 +98,7 @@ void emberAfEnergyEvseModeClusterInitCallback(chip::EndpointId endpointId) VerifyOrDie(!gEnergyEvseModeDelegate && !gEnergyEvseModeInstance); gEnergyEvseModeDelegate = std::make_unique(); gEnergyEvseModeInstance = std::make_unique(gEnergyEvseModeDelegate.get(), 0x1, EnergyEvseMode::Id, 0); - gEnergyEvseModeInstance->Init(); + TEMPORARY_RETURN_IGNORED gEnergyEvseModeInstance->Init(); } void emberAfEnergyEvseModeClusterShutdownCallback(chip::EndpointId endpointId) diff --git a/examples/energy-management-app/energy-management-common/energy-management-app.matter b/examples/energy-management-app/energy-management-common/energy-management-app.matter index 20f373022c9..d3f1976e461 100644 --- a/examples/energy-management-app/energy-management-common/energy-management-app.matter +++ b/examples/energy-management-app/energy-management-common/energy-management-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/energy-management-app/energy-management-common/energy-reporting/src/FakeReadings.cpp b/examples/energy-management-app/energy-management-common/energy-reporting/src/FakeReadings.cpp index c8be0def20b..39db62d78ee 100644 --- a/examples/energy-management-app/energy-management-common/energy-reporting/src/FakeReadings.cpp +++ b/examples/energy-management-app/energy-management-common/energy-reporting/src/FakeReadings.cpp @@ -140,7 +140,7 @@ void FakeReadings::FakeReadingsUpdate() int64_t current = (static_cast(rand()) % (2 * mCurrentRandomness_mA)) - mCurrentRandomness_mA; current += mCurrent_mA; // add in the base current - GetDEMDelegate()->GetDEMManufacturerDelegate()->SendPowerReading(mEndpointId, power, voltage, current); + TEMPORARY_RETURN_IGNORED GetDEMDelegate()->GetDEMManufacturerDelegate()->SendPowerReading(mEndpointId, power, voltage, current); // update the energy meter - we'll assume that the power has been constant during the previous interval if (mPower_mW > 0) @@ -158,14 +158,15 @@ void FakeReadings::FakeReadingsUpdate() mTotalEnergyExported += mPeriodicEnergyExported; } - GetDEMDelegate()->GetDEMManufacturerDelegate()->SendPeriodicEnergyReading(mEndpointId, mPeriodicEnergyImported, - mPeriodicEnergyExported); + TEMPORARY_RETURN_IGNORED GetDEMDelegate()->GetDEMManufacturerDelegate()->SendPeriodicEnergyReading( + mEndpointId, mPeriodicEnergyImported, mPeriodicEnergyExported); - GetDEMDelegate()->GetDEMManufacturerDelegate()->SendCumulativeEnergyReading(mEndpointId, mTotalEnergyImported, - mTotalEnergyExported); + TEMPORARY_RETURN_IGNORED GetDEMDelegate()->GetDEMManufacturerDelegate()->SendCumulativeEnergyReading( + mEndpointId, mTotalEnergyImported, mTotalEnergyExported); // start/restart the timer - DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(mInterval_s), FakeReadingsTimerExpiry, this); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(mInterval_s), FakeReadingsTimerExpiry, + this); } /** diff --git a/examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp b/examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp index d98f7a4ad80..d498c7c410d 100644 --- a/examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp +++ b/examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp @@ -158,7 +158,7 @@ CHIP_ERROR WhmManufacturerShutdown() if (gWhmManufacturer) { /* Shutdown the WhmManufacturer */ - gWhmManufacturer->Shutdown(); + TEMPORARY_RETURN_IGNORED gWhmManufacturer->Shutdown(); gWhmManufacturer.reset(); } @@ -178,7 +178,7 @@ CHIP_ERROR WhmApplicationInit(EndpointId endpointId) CHIP_ERROR WhmApplicationShutdown() { /* Shutdown in reverse order that they were created */ - WhmManufacturerShutdown(); + TEMPORARY_RETURN_IGNORED WhmManufacturerShutdown(); return WhmShutdown(); } diff --git a/examples/energy-management-app/energy-management-common/water-heater/src/water-heater-mode.cpp b/examples/energy-management-app/energy-management-common/water-heater/src/water-heater-mode.cpp index b53ca6f7aa8..45f9cc5e9f1 100644 --- a/examples/energy-management-app/energy-management-common/water-heater/src/water-heater-mode.cpp +++ b/examples/energy-management-app/energy-management-common/water-heater/src/water-heater-mode.cpp @@ -109,7 +109,7 @@ void emberAfWaterHeaterModeClusterInitCallback(chip::EndpointId endpointId) VerifyOrDie(gWaterHeaterModeDelegate == nullptr && gWaterHeaterModeInstance == nullptr); gWaterHeaterModeDelegate = new WaterHeaterMode::ExampleWaterHeaterModeDelegate; gWaterHeaterModeInstance = new ModeBase::Instance(gWaterHeaterModeDelegate, endpointId, WaterHeaterMode::Id, 0); - gWaterHeaterModeInstance->Init(); + TEMPORARY_RETURN_IGNORED gWaterHeaterModeInstance->Init(); } void emberAfWaterHeaterModeClusterShutdownCallback(chip::EndpointId endpointId) diff --git a/examples/energy-management-app/linux/main.cpp b/examples/energy-management-app/linux/main.cpp index 3ff0dd1b7c2..b653e8bd431 100644 --- a/examples/energy-management-app/linux/main.cpp +++ b/examples/energy-management-app/linux/main.cpp @@ -109,7 +109,7 @@ static uint32_t ParseNumber(const char * pString) void ApplicationInit() { ChipLogDetail(AppServer, "Energy Management App: ApplicationInit()"); - IdentifyInit(); + SuccessOrDie(IdentifyInit()); if (strcmp(spApp, kEvseApp) == 0) { // Disable Water Heater Endpoint diff --git a/examples/fabric-admin/commands/common/CHIPCommand.cpp b/examples/fabric-admin/commands/common/CHIPCommand.cpp index c5f56d2a690..de873c71785 100644 --- a/examples/fabric-admin/commands/common/CHIPCommand.cpp +++ b/examples/fabric-admin/commands/common/CHIPCommand.cpp @@ -516,7 +516,7 @@ CHIP_ERROR CHIPCommand::InitializeCommissioner(CommissionerIdentity & identity, chip::Credentials::SetSingleIpkEpochKey(&sGroupDataProvider, fabricIndex, defaultIpk, compressed_fabric_id_span)); } - CHIPCommand::sICDClientStorage.UpdateFabricList(commissioner->GetFabricIndex()); + ReturnErrorOnFailure(CHIPCommand::sICDClientStorage.UpdateFabricList(commissioner->GetFabricIndex())); mCommissioners[identity] = std::move(commissioner); diff --git a/examples/fabric-admin/commands/common/Commands.cpp b/examples/fabric-admin/commands/common/Commands.cpp index 3bcd04e4253..ea6e6652771 100644 --- a/examples/fabric-admin/commands/common/Commands.cpp +++ b/examples/fabric-admin/commands/common/Commands.cpp @@ -64,7 +64,7 @@ template ::value, int> = 0> static void UseStorageDirectory(T & storageManagerImpl, const char * storageDirectory) { std::string platformKVS = std::string(storageDirectory) + "/chip_tool_kvs"; - storageManagerImpl.Init(platformKVS.c_str()); + TEMPORARY_RETURN_IGNORED storageManagerImpl.Init(platformKVS.c_str()); } template ::value, int> = 0> diff --git a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp index 2cb7ce8f80c..c1c131f5779 100644 --- a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp +++ b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp @@ -74,7 +74,8 @@ void FabricSyncAddBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_E // // Note: The Fabric-Admin MUST NOT send the RequestCommissioningApproval command // if the remote Fabric-Bridge lacks Fabric Synchronization support. - DeviceLayer::SystemLayer().ScheduleLambda([]() { DeviceManager::Instance().ReadSupportedDeviceCategories(); }); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().ScheduleLambda( + []() { DeviceManager::Instance().ReadSupportedDeviceCategories(); }); } } else diff --git a/examples/fabric-admin/commands/interactive/InteractiveCommands.cpp b/examples/fabric-admin/commands/interactive/InteractiveCommands.cpp index 70843e4701b..f93b943c634 100644 --- a/examples/fabric-admin/commands/interactive/InteractiveCommands.cpp +++ b/examples/fabric-admin/commands/interactive/InteractiveCommands.cpp @@ -126,7 +126,8 @@ void AttemptRpcClientConnect(System::Layer * systemLayer, void * appState) { // print to console fprintf(stderr, "Failed to connect to Fabric-Bridge, retry in %d seconds....\n", kRetryIntervalS); - systemLayer->StartTimer(System::Clock::Seconds16(kRetryIntervalS), AttemptRpcClientConnect, nullptr); + TEMPORARY_RETURN_IGNORED systemLayer->StartTimer(System::Clock::Seconds16(kRetryIntervalS), AttemptRpcClientConnect, + nullptr); } } @@ -192,7 +193,7 @@ CHIP_ERROR InteractiveStartCommand::RunCommand() admin::SetRpcRemoteServerPort(mFabricBridgeServerPort.Value()); admin::InitRpcServer(mLocalServerPort.Value()); ChipLogProgress(NotSpecified, "PW_RPC initialized."); - DeviceLayer::PlatformMgr().ScheduleWork(ExecuteDeferredConnect, 0); + TEMPORARY_RETURN_IGNORED DeviceLayer::PlatformMgr().ScheduleWork(ExecuteDeferredConnect, 0); #endif std::thread readCommands(ReadCommandThread); diff --git a/examples/fabric-admin/commands/pairing/PairingCommand.cpp b/examples/fabric-admin/commands/pairing/PairingCommand.cpp index 5ac731871f9..c84ac6a23af 100644 --- a/examples/fabric-admin/commands/pairing/PairingCommand.cpp +++ b/examples/fabric-admin/commands/pairing/PairingCommand.cpp @@ -146,7 +146,8 @@ CommissioningParameters PairingCommand::GetCommissioningParameters() if (!mICDSymmetricKey.HasValue()) { - Crypto::DRBG_get_bytes(mRandomGeneratedICDSymmetricKey, sizeof(mRandomGeneratedICDSymmetricKey)); + TEMPORARY_RETURN_IGNORED Crypto::DRBG_get_bytes(mRandomGeneratedICDSymmetricKey, + sizeof(mRandomGeneratedICDSymmetricKey)); mICDSymmetricKey.SetValue(ByteSpan(mRandomGeneratedICDSymmetricKey)); } if (!mICDCheckInNodeId.HasValue()) @@ -453,8 +454,9 @@ void PairingCommand::OnICDRegistrationComplete(ScopedNodeId nodeId, uint32_t icd { char icdSymmetricKeyHex[Crypto::kAES_CCM128_Key_Length * 2 + 1]; - Encoding::BytesToHex(mICDSymmetricKey.Value().data(), mICDSymmetricKey.Value().size(), icdSymmetricKeyHex, - sizeof(icdSymmetricKeyHex), Encoding::HexFlags::kNullTerminate); + TEMPORARY_RETURN_IGNORED Encoding::BytesToHex(mICDSymmetricKey.Value().data(), mICDSymmetricKey.Value().size(), + icdSymmetricKeyHex, sizeof(icdSymmetricKeyHex), + Encoding::HexFlags::kNullTerminate); app::ICDClientInfo clientInfo; clientInfo.peer_node = nodeId; diff --git a/examples/fabric-admin/device_manager/DeviceManager.cpp b/examples/fabric-admin/device_manager/DeviceManager.cpp index 67c634b440d..ec93bbf2a32 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.cpp +++ b/examples/fabric-admin/device_manager/DeviceManager.cpp @@ -110,7 +110,7 @@ SyncedDevice * DeviceManager::FindDeviceByNode(NodeId nodeId) void DeviceManager::RemoveSyncedDevice(chip::ScopedNodeId scopedNodeId) { #if defined(PW_RPC_ENABLED) - RemoveSynchronizedDevice(scopedNodeId); + TEMPORARY_RETURN_IGNORED RemoveSynchronizedDevice(scopedNodeId); #endif NodeId nodeId = scopedNodeId.GetNodeId(); diff --git a/examples/fabric-admin/device_manager/DeviceSubscription.cpp b/examples/fabric-admin/device_manager/DeviceSubscription.cpp index d82dbc7bde3..b31dcf06414 100644 --- a/examples/fabric-admin/device_manager/DeviceSubscription.cpp +++ b/examples/fabric-admin/device_manager/DeviceSubscription.cpp @@ -112,7 +112,7 @@ void DeviceSubscription::OnReportEnd() if (mChangeDetected) { #if defined(PW_RPC_ENABLED) - AdminCommissioningAttributeChanged(mCurrentAdministratorCommissioningAttributes); + TEMPORARY_RETURN_IGNORED AdminCommissioningAttributeChanged(mCurrentAdministratorCommissioningAttributes); #else ChipLogError(NotSpecified, "Cannot forward Administrator Commissioning Attribute to fabric bridge: RPC not enabled"); #endif @@ -137,7 +137,7 @@ void DeviceSubscription::OnError(CHIP_ERROR error) reachabilityChanged.has_id = true; reachabilityChanged.id = mCurrentAdministratorCommissioningAttributes.id; reachabilityChanged.reachability = false; - DeviceReachableChanged(reachabilityChanged); + TEMPORARY_RETURN_IGNORED DeviceReachableChanged(reachabilityChanged); } #endif ChipLogProgress(NotSpecified, "Error subscribing: %" CHIP_ERROR_FORMAT, error.Format()); @@ -222,7 +222,7 @@ void DeviceSubscription::OnDeviceConnectionFailure(const ScopedNodeId & peerId, reachabilityChanged.has_id = true; reachabilityChanged.id = mCurrentAdministratorCommissioningAttributes.id; reachabilityChanged.reachability = false; - DeviceReachableChanged(reachabilityChanged); + TEMPORARY_RETURN_IGNORED DeviceReachableChanged(reachabilityChanged); } #endif diff --git a/examples/fabric-admin/device_manager/DeviceSynchronization.cpp b/examples/fabric-admin/device_manager/DeviceSynchronization.cpp index cba26549e1a..2d033484881 100644 --- a/examples/fabric-admin/device_manager/DeviceSynchronization.cpp +++ b/examples/fabric-admin/device_manager/DeviceSynchronization.cpp @@ -276,7 +276,7 @@ void DeviceSynchronizer::SynchronizationCompleteAddDevice() ChipLogProgress(NotSpecified, "Synchronization complete and add device"); #if defined(PW_RPC_ENABLED) - AddSynchronizedDevice(mCurrentDeviceData); + TEMPORARY_RETURN_IGNORED AddSynchronizedDevice(mCurrentDeviceData); // TODO(#35077) Figure out how we should reflect CADMIN values of ICD. if (!mCurrentDeviceData.is_icd) { @@ -290,7 +290,7 @@ void DeviceSynchronizer::SynchronizationCompleteAddDevice() reachabilityChanged.has_id = true; reachabilityChanged.id = mCurrentDeviceData.id; reachabilityChanged.reachability = false; - DeviceReachableChanged(reachabilityChanged); + TEMPORARY_RETURN_IGNORED DeviceReachableChanged(reachabilityChanged); } } #endif diff --git a/examples/fabric-admin/device_manager/PairingManager.cpp b/examples/fabric-admin/device_manager/PairingManager.cpp index 1fffbd21ac7..495be34a40f 100644 --- a/examples/fabric-admin/device_manager/PairingManager.cpp +++ b/examples/fabric-admin/device_manager/PairingManager.cpp @@ -347,8 +347,9 @@ void PairingManager::OnICDRegistrationComplete(ScopedNodeId nodeId, uint32_t icd { char icdSymmetricKeyHex[Crypto::kAES_CCM128_Key_Length * 2 + 1]; - Encoding::BytesToHex(mICDSymmetricKey.Value().data(), mICDSymmetricKey.Value().size(), icdSymmetricKeyHex, - sizeof(icdSymmetricKeyHex), Encoding::HexFlags::kNullTerminate); + TEMPORARY_RETURN_IGNORED Encoding::BytesToHex(mICDSymmetricKey.Value().data(), mICDSymmetricKey.Value().size(), + icdSymmetricKeyHex, sizeof(icdSymmetricKeyHex), + Encoding::HexFlags::kNullTerminate); app::ICDClientInfo clientInfo; clientInfo.peer_node = nodeId; @@ -449,7 +450,7 @@ void PairingManager::OnDeviceAttestationCompleted(Controller::DeviceCommissioner "Failed validation: vendorID or productID must not be 0." "Requested VID: %u, Requested PID: %u.", payload.vendorID, payload.productID); - deviceCommissioner->ContinueCommissioningAfterDeviceAttestation( + TEMPORARY_RETURN_IGNORED deviceCommissioner->ContinueCommissioningAfterDeviceAttestation( device, Credentials::AttestationVerificationResult::kInvalidArgument); return; } @@ -461,7 +462,7 @@ void PairingManager::OnDeviceAttestationCompleted(Controller::DeviceCommissioner "Requested VID: %u, Requested PID: %u," "Detected VID: %u, Detected PID %u.", payload.vendorID, payload.productID, info.BasicInformationVendorId(), info.BasicInformationProductId()); - deviceCommissioner->ContinueCommissioningAfterDeviceAttestation( + TEMPORARY_RETURN_IGNORED deviceCommissioner->ContinueCommissioningAfterDeviceAttestation( device, payload.vendorID == info.BasicInformationVendorId() ? Credentials::AttestationVerificationResult::kDacProductIdMismatch @@ -498,7 +499,8 @@ CommissioningParameters PairingManager::GetCommissioningParameters() if (!mICDSymmetricKey.HasValue()) { - Crypto::DRBG_get_bytes(mRandomGeneratedICDSymmetricKey, sizeof(mRandomGeneratedICDSymmetricKey)); + TEMPORARY_RETURN_IGNORED Crypto::DRBG_get_bytes(mRandomGeneratedICDSymmetricKey, + sizeof(mRandomGeneratedICDSymmetricKey)); mICDSymmetricKey.SetValue(ByteSpan(mRandomGeneratedICDSymmetricKey)); } if (!mICDCheckInNodeId.HasValue()) diff --git a/examples/fabric-admin/rpc/RpcServer.cpp b/examples/fabric-admin/rpc/RpcServer.cpp index a7c9259dde1..6bbbb3f4ecd 100644 --- a/examples/fabric-admin/rpc/RpcServer.cpp +++ b/examples/fabric-admin/rpc/RpcServer.cpp @@ -87,7 +87,9 @@ class FabricAdmin final : public rpc::FabricAdmin, public admin::PairingDelegate // there is no mechanism for us to communicate with the client that sent out the KeepActive // command that there was a failure, we simply fail silently. After spec issue is // addressed, we can implement what spec defines here. - auto onDone = [=](uint32_t promisedActiveDuration) { ActiveChanged(scopedNodeId, promisedActiveDuration); }; + auto onDone = [=](uint32_t promisedActiveDuration) { + TEMPORARY_RETURN_IGNORED ActiveChanged(scopedNodeId, promisedActiveDuration); + }; CHIP_ERROR err = StayActiveSender::SendStayActiveCommand(checkInData.mStayActiveDurationMs, clientInfo.peer_node, app::InteractionModelEngine::GetInstance(), onDone); if (err != CHIP_NO_ERROR) @@ -151,7 +153,8 @@ class FabricAdmin final : public rpc::FabricAdmin, public admin::PairingDelegate pw::Status CommissionNode(const chip_rpc_DeviceCommissioningInfo & request, pw_protobuf_Empty & response) override { char saltHex[Crypto::kSpake2p_Max_PBKDF_Salt_Length * 2 + 1]; - Encoding::BytesToHex(request.salt.bytes, request.salt.size, saltHex, sizeof(saltHex), Encoding::HexFlags::kNullTerminate); + TEMPORARY_RETURN_IGNORED Encoding::BytesToHex(request.salt.bytes, request.salt.size, saltHex, sizeof(saltHex), + Encoding::HexFlags::kNullTerminate); ChipLogProgress(NotSpecified, "Received CommissionNode request"); @@ -203,7 +206,7 @@ class FabricAdmin final : public rpc::FabricAdmin, public admin::PairingDelegate KeepActiveWorkData * data = Platform::New(this, scopedNodeId, request.stay_active_duration_ms, request.timeout_ms); VerifyOrReturnValue(data, pw::Status::Internal()); - DeviceLayer::PlatformMgr().ScheduleWork(KeepActiveWork, reinterpret_cast(data)); + TEMPORARY_RETURN_IGNORED DeviceLayer::PlatformMgr().ScheduleWork(KeepActiveWork, reinterpret_cast(data)); return pw::OkStatus(); } diff --git a/examples/fabric-bridge-app/fabric-bridge-common/BridgedDevice.cpp b/examples/fabric-bridge-app/fabric-bridge-common/BridgedDevice.cpp index ef52e689255..f7b63530204 100644 --- a/examples/fabric-bridge-app/fabric-bridge-common/BridgedDevice.cpp +++ b/examples/fabric-bridge-app/fabric-bridge-common/BridgedDevice.cpp @@ -40,7 +40,7 @@ void BridgedDevice::LogActiveChangeEvent(uint32_t promisedActiveDurationMs) { EndpointId endpointId = mEndpointId; - DeviceLayer::SystemLayer().ScheduleLambda([endpointId, promisedActiveDurationMs]() { + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().ScheduleLambda([endpointId, promisedActiveDurationMs]() { app::Clusters::BridgedDeviceBasicInformation::Events::ActiveChanged::Type event{}; event.promisedActiveDuration = promisedActiveDurationMs; EventNumber eventNumber = 0; @@ -74,7 +74,7 @@ void BridgedDevice::ReachableChanged(bool reachable) if (reachableChanged) { SetReachable(reachable); - DeviceLayer::SystemLayer().ScheduleLambda([endpointId]() { + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().ScheduleLambda([endpointId]() { MatterReportingAttributeChangeCallback(endpointId, app::Clusters::BridgedDeviceBasicInformation::Id, app::Clusters::BridgedDeviceBasicInformation::Attributes::Reachable::Id); @@ -100,23 +100,24 @@ void BridgedDevice::SetAdminCommissioningAttributes(const AdminCommissioningAttr mAdminCommissioningAttributes = aAdminCommissioningAttributes; - DeviceLayer::SystemLayer().ScheduleLambda([endpointId, windowChanged, fabricIndexChanged, vendorChanged]() { - if (windowChanged) - { - MatterReportingAttributeChangeCallback(endpointId, app::Clusters::AdministratorCommissioning::Id, - app::Clusters::AdministratorCommissioning::Attributes::WindowStatus::Id); - } - if (fabricIndexChanged) - { - MatterReportingAttributeChangeCallback(endpointId, app::Clusters::AdministratorCommissioning::Id, - app::Clusters::AdministratorCommissioning::Attributes::AdminFabricIndex::Id); - } - if (vendorChanged) - { - MatterReportingAttributeChangeCallback(endpointId, app::Clusters::AdministratorCommissioning::Id, - app::Clusters::AdministratorCommissioning::Attributes::AdminVendorId::Id); - } - }); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().ScheduleLambda( + [endpointId, windowChanged, fabricIndexChanged, vendorChanged]() { + if (windowChanged) + { + MatterReportingAttributeChangeCallback(endpointId, app::Clusters::AdministratorCommissioning::Id, + app::Clusters::AdministratorCommissioning::Attributes::WindowStatus::Id); + } + if (fabricIndexChanged) + { + MatterReportingAttributeChangeCallback(endpointId, app::Clusters::AdministratorCommissioning::Id, + app::Clusters::AdministratorCommissioning::Attributes::AdminFabricIndex::Id); + } + if (vendorChanged) + { + MatterReportingAttributeChangeCallback(endpointId, app::Clusters::AdministratorCommissioning::Id, + app::Clusters::AdministratorCommissioning::Attributes::AdminVendorId::Id); + } + }); } void BridgedDevice::RegisterClusters() diff --git a/examples/fabric-bridge-app/fabric-bridge-common/BridgedDeviceBasicInformationImpl.cpp b/examples/fabric-bridge-app/fabric-bridge-common/BridgedDeviceBasicInformationImpl.cpp index 3a03d8f84a8..207044afd93 100644 --- a/examples/fabric-bridge-app/fabric-bridge-common/BridgedDeviceBasicInformationImpl.cpp +++ b/examples/fabric-bridge-app/fabric-bridge-common/BridgedDeviceBasicInformationImpl.cpp @@ -39,54 +39,55 @@ CHIP_ERROR BridgedDeviceBasicInformationImpl::Read(const ConcreteReadAttributePa BridgedDevice * dev = BridgedDeviceManager::Instance().GetDevice(path.mEndpointId); VerifyOrReturnError(dev != nullptr, CHIP_ERROR_NOT_FOUND); + CHIP_ERROR err = CHIP_NO_ERROR; switch (path.mAttributeId) { case BasicInformation::Attributes::Reachable::Id: - encoder.Encode(dev->IsReachable()); + err = encoder.Encode(dev->IsReachable()); break; case BasicInformation::Attributes::NodeLabel::Id: - encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().nodeLabel.c_str())); + err = encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().nodeLabel.c_str())); break; case BasicInformation::Attributes::ClusterRevision::Id: - encoder.Encode(kBridgedDeviceBasicInformationClusterRevision); + err = encoder.Encode(kBridgedDeviceBasicInformationClusterRevision); break; case BasicInformation::Attributes::FeatureMap::Id: { BitMask features; features.Set(Clusters::BridgedDeviceBasicInformation::Feature::kBridgedICDSupport, dev->IsIcd()); - encoder.Encode(features); + err = encoder.Encode(features); } break; case BasicInformation::Attributes::UniqueID::Id: - encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().uniqueId.c_str())); + err = encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().uniqueId.c_str())); break; case BasicInformation::Attributes::VendorName::Id: - encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().vendorName.c_str())); + err = encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().vendorName.c_str())); break; case BasicInformation::Attributes::VendorID::Id: - encoder.Encode(dev->GetBridgedAttributes().vendorId); + err = encoder.Encode(dev->GetBridgedAttributes().vendorId); break; case BasicInformation::Attributes::ProductName::Id: - encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().productName.c_str())); + err = encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().productName.c_str())); break; case BasicInformation::Attributes::ProductID::Id: - encoder.Encode(dev->GetBridgedAttributes().productId); + err = encoder.Encode(dev->GetBridgedAttributes().productId); break; case BasicInformation::Attributes::HardwareVersion::Id: - encoder.Encode(dev->GetBridgedAttributes().hardwareVersion); + err = encoder.Encode(dev->GetBridgedAttributes().hardwareVersion); break; case BasicInformation::Attributes::HardwareVersionString::Id: - encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().hardwareVersionString.c_str())); + err = encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().hardwareVersionString.c_str())); break; case BasicInformation::Attributes::SoftwareVersion::Id: - encoder.Encode(dev->GetBridgedAttributes().softwareVersion); + err = encoder.Encode(dev->GetBridgedAttributes().softwareVersion); break; case BasicInformation::Attributes::SoftwareVersionString::Id: - encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().softwareVersionString.c_str())); + err = encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().softwareVersionString.c_str())); break; default: return CHIP_ERROR_INVALID_ARGUMENT; } - return CHIP_NO_ERROR; + return err; } CHIP_ERROR BridgedDeviceBasicInformationImpl::Write(const ConcreteDataAttributePath & path, AttributeValueDecoder & decoder) diff --git a/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.matter b/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.matter index 791c4051922..c60dc51e8d9 100644 --- a/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.matter +++ b/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/fabric-bridge-app/linux/main.cpp b/examples/fabric-bridge-app/linux/main.cpp index 02d62981336..c3fe1ec50a7 100644 --- a/examples/fabric-bridge-app/linux/main.cpp +++ b/examples/fabric-bridge-app/linux/main.cpp @@ -104,7 +104,7 @@ void AttemptRpcClientConnect(System::Layer * systemLayer, void * appState) else { ChipLogError(NotSpecified, "Failed to connect to Fabric-Admin, retry in %d seconds....", kRetryIntervalS); - systemLayer->StartTimer(System::Clock::Seconds16(kRetryIntervalS), AttemptRpcClientConnect, nullptr); + SuccessOrDie(systemLayer->StartTimer(System::Clock::Seconds16(kRetryIntervalS), AttemptRpcClientConnect, nullptr)); } } #endif // defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE diff --git a/examples/fabric-sync/admin/DeviceSynchronization.cpp b/examples/fabric-sync/admin/DeviceSynchronization.cpp index badcbdf0e47..72d44445ceb 100644 --- a/examples/fabric-sync/admin/DeviceSynchronization.cpp +++ b/examples/fabric-sync/admin/DeviceSynchronization.cpp @@ -289,7 +289,7 @@ void DeviceSynchronizer::SynchronizationCompleteAddDevice() VerifyOrDie(mState == State::ReceivedResponse || mState == State::GettingUid); ChipLogProgress(NotSpecified, "Synchronization complete and add device"); - bridge::FabricBridge::Instance().AddSynchronizedDevice(mCurrentDeviceData); + TEMPORARY_RETURN_IGNORED bridge::FabricBridge::Instance().AddSynchronizedDevice(mCurrentDeviceData); // TODO(#35077) Figure out how we should reflect CADMIN values of ICD. if (!mCurrentDeviceData.isIcd.value_or(false)) @@ -300,7 +300,7 @@ void DeviceSynchronizer::SynchronizationCompleteAddDevice() if (err != CHIP_NO_ERROR) { ChipLogError(NotSpecified, "Failed start subscription to NodeId:" ChipLogFormatX64, ChipLogValueX64(mNodeId)); - bridge::FabricBridge::Instance().DeviceReachableChanged(mCurrentDeviceData.id, false); + TEMPORARY_RETURN_IGNORED bridge::FabricBridge::Instance().DeviceReachableChanged(mCurrentDeviceData.id, false); } } diff --git a/examples/fabric-sync/admin/FabricAdmin.cpp b/examples/fabric-sync/admin/FabricAdmin.cpp index 39ab8b372d1..cc0159d438a 100644 --- a/examples/fabric-sync/admin/FabricAdmin.cpp +++ b/examples/fabric-sync/admin/FabricAdmin.cpp @@ -80,8 +80,8 @@ CHIP_ERROR FabricAdmin::CommissionRemoteBridge(Controller::CommissioningWindowPasscodeParams params, VendorId vendorId, uint16_t productId) { char saltHex[Crypto::kSpake2p_Max_PBKDF_Salt_Length * 2 + 1]; - Encoding::BytesToHex(params.GetSalt().data(), params.GetSalt().size(), saltHex, sizeof(saltHex), - Encoding::HexFlags::kNullTerminate); + ReturnErrorOnFailure(Encoding::BytesToHex(params.GetSalt().data(), params.GetSalt().size(), saltHex, sizeof(saltHex), + Encoding::HexFlags::kNullTerminate)); ChipLogProgress(NotSpecified, "Received CommissionNode request"); @@ -135,8 +135,7 @@ CHIP_ERROR FabricAdmin::KeepActive(ScopedNodeId scopedNodeId, uint32_t stayActiv KeepActiveWorkData * data = Platform::New(this, scopedNodeId, stayActiveDurationMs, timeoutMs); VerifyOrReturnError(data != nullptr, CHIP_ERROR_NO_MEMORY); - DeviceLayer::PlatformMgr().ScheduleWork(KeepActiveWork, reinterpret_cast(data)); - return CHIP_NO_ERROR; + return DeviceLayer::PlatformMgr().ScheduleWork(KeepActiveWork, reinterpret_cast(data)); } void FabricAdmin::OnCheckInCompleted(const app::ICDClientInfo & clientInfo) @@ -169,7 +168,7 @@ void FabricAdmin::OnCheckInCompleted(const app::ICDClientInfo & clientInfo) // command that there was a failure, we simply fail silently. After spec issue is // addressed, we can implement what spec defines here. auto onDone = [=](uint32_t promisedActiveDuration) { - bridge::FabricBridge::Instance().ActiveChanged(scopedNodeId, promisedActiveDuration); + TEMPORARY_RETURN_IGNORED bridge::FabricBridge::Instance().ActiveChanged(scopedNodeId, promisedActiveDuration); }; CHIP_ERROR err = StayActiveSender::SendStayActiveCommand(checkInData.mStayActiveDurationMs, clientInfo.peer_node, app::InteractionModelEngine::GetInstance(), onDone); diff --git a/examples/fabric-sync/admin/PairingManager.cpp b/examples/fabric-sync/admin/PairingManager.cpp index 9cc75d01526..13de10e18a1 100644 --- a/examples/fabric-sync/admin/PairingManager.cpp +++ b/examples/fabric-sync/admin/PairingManager.cpp @@ -104,7 +104,7 @@ PairingManager::PairingManager() : CHIP_ERROR PairingManager::Init(Controller::DeviceCommissioner * commissioner) { VerifyOrReturnError(commissioner != nullptr, CHIP_ERROR_INCORRECT_STATE); - FabricAdmin::Instance().GetDefaultICDClientStorage().UpdateFabricList(commissioner->GetFabricIndex()); + ReturnErrorOnFailure(FabricAdmin::Instance().GetDefaultICDClientStorage().UpdateFabricList(commissioner->GetFabricIndex())); mCommissioner = commissioner; return CHIP_NO_ERROR; @@ -348,8 +348,9 @@ void PairingManager::OnICDRegistrationComplete(ScopedNodeId nodeId, uint32_t icd { char icdSymmetricKeyHex[Crypto::kAES_CCM128_Key_Length * 2 + 1]; - Encoding::BytesToHex(mICDSymmetricKey.Value().data(), mICDSymmetricKey.Value().size(), icdSymmetricKeyHex, - sizeof(icdSymmetricKeyHex), Encoding::HexFlags::kNullTerminate); + TEMPORARY_RETURN_IGNORED Encoding::BytesToHex(mICDSymmetricKey.Value().data(), mICDSymmetricKey.Value().size(), + icdSymmetricKeyHex, sizeof(icdSymmetricKeyHex), + Encoding::HexFlags::kNullTerminate); app::ICDClientInfo clientInfo; clientInfo.peer_node = nodeId; @@ -451,7 +452,7 @@ void PairingManager::OnDeviceAttestationCompleted(Controller::DeviceCommissioner "Failed validation: vendorID or productID must not be 0." "Requested VID: %u, Requested PID: %u.", payload.vendorID, payload.productID); - deviceCommissioner->ContinueCommissioningAfterDeviceAttestation( + TEMPORARY_RETURN_IGNORED deviceCommissioner->ContinueCommissioningAfterDeviceAttestation( device, Credentials::AttestationVerificationResult::kInvalidArgument); return; } @@ -463,7 +464,7 @@ void PairingManager::OnDeviceAttestationCompleted(Controller::DeviceCommissioner "Requested VID: %u, Requested PID: %u," "Detected VID: %u, Detected PID %u.", payload.vendorID, payload.productID, info.BasicInformationVendorId(), info.BasicInformationProductId()); - deviceCommissioner->ContinueCommissioningAfterDeviceAttestation( + TEMPORARY_RETURN_IGNORED deviceCommissioner->ContinueCommissioningAfterDeviceAttestation( device, payload.vendorID == info.BasicInformationVendorId() ? Credentials::AttestationVerificationResult::kDacProductIdMismatch @@ -500,7 +501,8 @@ CommissioningParameters PairingManager::GetCommissioningParameters() if (!mICDSymmetricKey.HasValue()) { - Crypto::DRBG_get_bytes(mRandomGeneratedICDSymmetricKey, sizeof(mRandomGeneratedICDSymmetricKey)); + TEMPORARY_RETURN_IGNORED Crypto::DRBG_get_bytes(mRandomGeneratedICDSymmetricKey, + sizeof(mRandomGeneratedICDSymmetricKey)); mICDSymmetricKey.SetValue(ByteSpan(mRandomGeneratedICDSymmetricKey)); } if (!mICDCheckInNodeId.HasValue()) diff --git a/examples/fabric-sync/shell/AddBridgeCommand.cpp b/examples/fabric-sync/shell/AddBridgeCommand.cpp index 11dea25cb27..b9d5f52df3c 100644 --- a/examples/fabric-sync/shell/AddBridgeCommand.cpp +++ b/examples/fabric-sync/shell/AddBridgeCommand.cpp @@ -63,7 +63,8 @@ void AddBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) // // Note: The Fabric-Admin MUST NOT send the RequestCommissioningApproval command // if the remote Fabric-Bridge lacks Fabric Synchronization support. - DeviceLayer::SystemLayer().ScheduleLambda([]() { admin::DeviceManager::Instance().ReadSupportedDeviceCategories(); }); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().ScheduleLambda( + []() { admin::DeviceManager::Instance().ReadSupportedDeviceCategories(); }); } else { diff --git a/examples/jf-admin-app/jfa-common/jfa-app.matter b/examples/jf-admin-app/jfa-common/jfa-app.matter index 8cf40cb4eee..82b9bac00ee 100644 --- a/examples/jf-admin-app/jfa-common/jfa-app.matter +++ b/examples/jf-admin-app/jfa-common/jfa-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/laundry-washer-app/nxp/CMakeLists.txt b/examples/laundry-washer-app/nxp/CMakeLists.txt new file mode 100644 index 00000000000..8ef650d78d3 --- /dev/null +++ b/examples/laundry-washer-app/nxp/CMakeLists.txt @@ -0,0 +1,113 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# **************************************************************** +# Matter Laundry Washer application for NXP FreeRTOS platforms +# **************************************************************** + +cmake_minimum_required(VERSION 3.30) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Retrieve CHIP_ROOT if provided +if (DEFINED CHIP_ROOT) + get_filename_component(CHIP_ROOT ${CHIP_ROOT} ABSOLUTE) +else() + get_filename_component(CHIP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../../ REALPATH) +endif() + +# Export CHIP_ROOT as an environment variable to be recognized by Kconfig +set(COMMON_KCONFIG_ENV_SETTINGS CHIP_ROOT=${CHIP_ROOT}) + +get_filename_component(GEN_DIR ${CHIP_ROOT}/zzz_generated/ REALPATH) +get_filename_component(NXP_EXAMPLE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/common REALPATH) +get_filename_component(NXP_EXAMPLE_ZAP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/zap REALPATH) +get_filename_component(ALL_CLUSTERS_COMMON_DIR ${CHIP_ROOT}/examples/all-clusters-app/all-clusters-common REALPATH) +get_filename_component(EXAMPLE_PLATFORM_NXP_COMMON_DIR ${CHIP_ROOT}/examples/platform/nxp/common REALPATH) +get_filename_component(NXP_MATTER_SUPPORT_DIR ${CHIP_ROOT}/third_party/nxp/nxp_matter_support REALPATH) + +# Add the CHIP stack & NXP port libs as an external module +list(APPEND EXTRA_MCUX_MODULES ${CHIP_ROOT}/config/nxp/chip-cmake-freertos) + +# If CONF_FILE_NAME is provided, append its full path to CONF_FILE +if (DEFINED CONF_FILE_NAME) + set(CONF_FILE ${CHIP_ROOT}/examples/platform/nxp/config/${CONF_FILE_NAME} ${CONF_FILE}) +endif() + +# Add application prj.conf in front of CONF_FILE +set(CONF_FILE ${CMAKE_CURRENT_SOURCE_DIR}/prj.conf ${CONF_FILE}) + +set(KCONFIG_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/Kconfig) + +# Load the MCUX SDK package +find_package(McuxSDK 3.0.0) + +# Get compiler flags and includes and pass them to CHIP target +list(APPEND CONFIG_CHIP_EXTERNAL_TARGETS McuxSDK) + +if (NOT DEFINED NXP_SDK_RECONFIG_CMAKE_DIR) + get_filename_component(NXP_SDK_RECONFIG_CMAKE_DIR ${NXP_MATTER_SUPPORT_DIR}/examples/platform/${CONFIG_CHIP_NXP_PLATFORM_FAMILY} REALPATH) +endif() + +# Include the nxp_sdk_reconfig.cmake to customize the SDK for Matter application +include(${NXP_SDK_RECONFIG_CMAKE_DIR}/nxp_sdk_reconfig.cmake) + +# Define application project name +project(chip-nxp-laundry-washer-app-example) + +# Add application definitions, include paths and source files +include(${CHIP_ROOT}/src/app/chip_data_model.cmake) + +# Add NXP common application files +include(${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/app_common.cmake) + +target_include_directories(app + PRIVATE + ${ALL_CLUSTERS_COMMON_DIR}/include + ${NXP_EXAMPLE_DIR}/main/include + ${GEN_DIR}/app-common +) + +target_sources(app + PRIVATE + ${NXP_EXAMPLE_DIR}/main/main.cpp + ${NXP_EXAMPLE_DIR}/main/AppTask.cpp + ${NXP_EXAMPLE_DIR}/main/DeviceCallbacks.cpp + ${NXP_EXAMPLE_DIR}/main/ZclCallbacks.cpp + ${NXP_EXAMPLE_DIR}/main/laundry-washer-mode.cpp + ${ALL_CLUSTERS_COMMON_DIR}/src/binding-handler.cpp + ${ALL_CLUSTERS_COMMON_DIR}/src/laundry-washer-controls-delegate-impl.cpp + ${ALL_CLUSTERS_COMMON_DIR}/src/static-supported-temperature-levels.cpp + ${ALL_CLUSTERS_COMMON_DIR}/src/operational-state-delegate-impl.cpp +) + +if(CONFIG_CHIP_ETHERNET) + message(FATAL_ERROR "Ethernet configuration is not supported in this application.") +endif() + +if(CONFIG_CHIP_WIFI AND CONFIG_NET_L2_OPENTHREAD) + message(FATAL_ERROR "WiFi + Thread (Border Router) configuration is not supported in this application.") +elseif(CONFIG_CHIP_WIFI AND NOT CONFIG_NET_L2_OPENTHREAD) + chip_configure_data_model(app + INCLUDE_SERVER + ZAP_FILE ${NXP_EXAMPLE_ZAP_DIR}/laundry-washer-app.zap + ) +elseif(CONFIG_NET_L2_OPENTHREAD AND NOT CONFIG_CHIP_WIFI) + chip_configure_data_model(app + INCLUDE_SERVER + ZAP_FILE ${NXP_EXAMPLE_ZAP_DIR}/laundry-washer-app.zap + ) +endif() \ No newline at end of file diff --git a/examples/laundry-washer-app/nxp/Kconfig b/examples/laundry-washer-app/nxp/Kconfig new file mode 100644 index 00000000000..ece44fe35dc --- /dev/null +++ b/examples/laundry-washer-app/nxp/Kconfig @@ -0,0 +1,20 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +mainmenu "Matter NXP Laundry Washer Example Application" + +source "$(CHIP_ROOT)/config/nxp/chip-cmake-freertos/Kconfig.defaults" +source "$(CHIP_ROOT)/examples/platform/nxp/common/Kconfig" +source "Kconfig.mcuxpresso" \ No newline at end of file diff --git a/examples/laundry-washer-app/nxp/README.md b/examples/laundry-washer-app/nxp/README.md new file mode 100644 index 00000000000..214e73a521b --- /dev/null +++ b/examples/laundry-washer-app/nxp/README.md @@ -0,0 +1,35 @@ +# CHIP NXP Laundry Washer Application + +## Overview + +The NXP Laundry Washer example is based on +[Project CHIP](https://github.com/project-chip/connectedhomeip) and NXP SDK, and +provides a prototype of a laundry washer device that demonstrates device +commissioning and different cluster control. + +### Supported platforms + +The Laundry Washer example is supported on the following platforms : + +| NXP platform | Dedicated readme | +| ------------------- | ---------------------------------------------------------------------------- | +| RW61x (Zephyr OS) | [NXP Zephyr Guide](../../../docs/platforms/nxp/nxp_zephyr_guide.md) | +| RW61x (FreeRTOS OS) | [NXP RW61x (FreeRTOS) Guide](../../../docs/platforms/nxp/nxp_rw61x_guide.md) | +| RT1170 | [NXP RT1170 Guide](../../../docs/platforms/nxp/nxp_rt1170_guide.md) | +| RT1060 | [NXP RT1060 Guide](../../../docs/platforms/nxp/nxp_rt1060_guide.md) | + +For details on platform-specific requirements and configurations, please refer +to the respective platform's readme. + +## Environment Setup, Building, and Testing + +All the information required to set up the environment, build the application, +and test it can be found in the common readme for NXP platforms : + +- NXP FreeRTOS Platforms : Refer to the + [CHIP NXP Examples Guide for FreeRTOS platforms](../../../docs/platforms/nxp/nxp_examples_freertos_platforms.md) +- NXP Zephyr Platform : Refer to the + [NXP Zephyr Application](../../../docs/platforms/nxp/nxp_zephyr_guide.md) + +> Note : Matter-over-WiFi + Thread Border Router configuration is not supported +> in this application. diff --git a/examples/laundry-washer-app/nxp/prj.conf b/examples/laundry-washer-app/nxp/prj.conf new file mode 100644 index 00000000000..6a0cd6c6214 --- /dev/null +++ b/examples/laundry-washer-app/nxp/prj.conf @@ -0,0 +1,28 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This file is used to set configs or override default configurations for +# the Laundry Washer application. + +CONFIG_CHIP=y +CONFIG_CHIP_LIB_SHELL=y +CONFIG_BT_DEVICE_NAME="\"NXPWasher\"" +CONFIG_CHIP_DEVICE_PRODUCT_NAME="LaundryWasher" +CONFIG_CHIP_DEVICE_TYPE=115 +CONFIG_CHIP_CUSTOM_BLE_ADV_DATA=n + +# SDK configs +CONFIG_MCUX_PRJSEG_module.board.boardfile=n \ No newline at end of file diff --git a/examples/laundry-washer-app/nxp/rt/rt1060/.gn b/examples/laundry-washer-app/nxp/rt/rt1060/.gn deleted file mode 100644 index 0985ed955a4..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rt1060/.gn +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) 2020 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") -import("//build_overrides/chip.gni") - -# The location of the build configuration file. -buildconfig = "${build_root}/config/BUILDCONFIG.gn" - -# CHIP uses angle bracket includes. -check_system_includes = true - -default_args = { - target_cpu = "arm" - target_os = "freertos" - - import("//args.gni") - - # Import common example GN args - import("${chip_root}/examples/platform/nxp/common/gn/args.gni") - - # Import default platform configs - import("${chip_root}/src/platform/nxp/rt/rt1060/args.gni") -} diff --git a/examples/laundry-washer-app/nxp/rt/rt1060/BUILD.gn b/examples/laundry-washer-app/nxp/rt/rt1060/BUILD.gn deleted file mode 100644 index 76d6e83520a..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rt1060/BUILD.gn +++ /dev/null @@ -1,327 +0,0 @@ -# Copyright (c) 2021-2023 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") -import("//build_overrides/chip.gni") -import("//build_overrides/nxp_sdk.gni") -import("//build_overrides/openthread.gni") -import("${chip_root}/src/platform/device.gni") - -#allows to get common NXP SDK gn options -import("${nxp_sdk_build_root}/nxp_sdk.gni") - -# Allows to get various RT gn options -import("${nxp_sdk_build_root}/${nxp_sdk_name}/rt_sdk.gni") - -import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") -import( - "${nxp_sdk_build_root}/${nxp_sdk_name}/${rt_platform}/${rt_platform}.gni") -import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") - -assert(current_os == "freertos") -assert(target_os == "freertos") -assert(nxp_platform == "rt/rt1060") - -declare_args() { - # Allows to enable to ota_provider support - enable_ota_provider = false - - # Allows to connect to a predefine Wi-Fi network at boot - wifi_auto_connect_at_boot = false - wifi_auto_connect_at_boot_ssid = "" - wifi_auto_connect_at_boot_password = "" - - # Setup discriminator as argument - setup_discriminator = 3840 - - chip_with_diag_logs_demo = true -} - -example_platform_dir = - "${nxp_sdk_matter_support_root}/examples/platform/${nxp_platform}" -common_example_dir = "${chip_root}/examples/platform/nxp/common" - -app_common_folder = "laundry-washer-app/nxp/zap" - -# Create here the SDK instance. -# Particular sources/defines/includes could be added/changed depending on the target application. -rt_sdk("sdk") { - defines = [] - - cflags = [] - public_deps = [] - public_configs = [] - sources = [] - include_dirs = [] - - # Indicate paths to default board files - include_dirs += [ "${example_platform_dir}/board/" ] - - # RT1060 rev A use same pin mux as rev B - # If user needs different pin mux files for rev A and rev B boards, the source and include from below needs to be updated accordingly - if (evkname == "evkmimxrt1060") { - include_dirs += [ "${example_platform_dir}/board/evkbmimxrt1060/" ] - sources += [ "${example_platform_dir}/board/evkbmimxrt1060/pin_mux.c" ] - } else { - include_dirs += [ "${example_platform_dir}/board/${evkname}/" ] - sources += [ "${example_platform_dir}/board/${evkname}/pin_mux.c" ] - } - - if (iw416_transceiver || w8801_transceiver || iwx12_transceiver) { - if (evkname == "evkmimxrt1060") { - include_dirs += [ "${example_platform_dir}/board/evkbmimxrt1060/" ] - sources += - [ "${example_platform_dir}/board/evkbmimxrt1060/sdmmc_config.c" ] - sources += - [ "${example_platform_dir}/board/evkbmimxrt1060/wifi_bt_config.c" ] - } else { - include_dirs += [ "${example_platform_dir}/board/${evkname}/" ] - sources += [ "${example_platform_dir}/board/${evkname}/sdmmc_config.c" ] - sources += [ "${example_platform_dir}/board/${evkname}/wifi_bt_config.c" ] - } - } - - sources += [ "${example_platform_dir}/board/hardware_init.c" ] - sources += [ "${example_platform_dir}/board/clock_config.c" ] - sources += [ "${example_platform_dir}/board/board.c" ] - sources += [ "${example_platform_dir}/board/peripherals.c" ] - - # Indicate the path to CHIPProjectConfig.h - include_dirs += [ "include/config" ] - - # Indicate the default path to FreeRTOSConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/freeRTOS" ] - - # Indicate the default path to OpenThreadConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/openthread" ] - - # For matter with BR feature, increase FreeRTOS heap size - if (chip_enable_wifi && chip_enable_openthread) { - defines += [ "configTOTAL_HEAP_SIZE=(size_t)(170 * 1024)" ] - } - - defines += [ - "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", - ] -} - -# Create the SDK driver instance. -# Particular sources/defines/includes could be added to add other drivers not available in the default sdk driver template -rt1060_sdk_drivers("sdk_driver") { -} - -rt_executable("laundry-washer") { - output_name = "chip-rt1060-laundry-washer-example" - - defines = [ - "CONFIG_RENDEZVOUS_MODE=7", - "CONFIG_APP_FREERTOS_OS=1", - ] - - if (chip_enable_openthread) { - defines += [ "CONFIG_NET_L2_OPENTHREAD=1" ] - } - - if (chip_with_diag_logs_demo) { - defines += [ - "CONFIG_DIAG_LOGS_DEMO=1", - "CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE=1024", - ] - } - - include_dirs = [ - "../../common/main/include", - "../../common/main", - "${chip_root}/examples/all-clusters-app/all-clusters-common/include", - "${chip_root}/examples/providers/", - ] - - sources = [ - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp", - "${chip_root}/examples/providers/DeviceInfoProviderImpl.cpp", - "../../common/main/AppTask.cpp", - "../../common/main/DeviceCallbacks.cpp", - "../../common/main/ZclCallbacks.cpp", - "../../common/main/include/AppEvent.h", - "../../common/main/include/AppTask.h", - "../../common/main/include/DeviceCallbacks.h", - "../../common/main/main.cpp", - ] - - if (chip_with_diag_logs_demo) { - include_dirs += [ - "${common_example_dir}/diagnostic_logs/include", - "${chip_root}", - ] - sources += [ - "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsDemo.cpp", - "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp", - ] - } - - # App common files - include_dirs += [ - "${common_example_dir}/icd/include", - "${common_example_dir}/matter_cli/include", - "${common_example_dir}/device_manager/include", - "${common_example_dir}/device_callbacks/include", - "${common_example_dir}/matter_button/include", - "${common_example_dir}/factory_data/include", - "${common_example_dir}/app_task/include", - ] - - sources += [ - "${chip_root}/examples/platform/nxp/${nxp_platform}/factory_data/source/AppFactoryDataExample.cpp", - "${common_example_dir}/app_task/source/AppTaskBase.cpp", - "${common_example_dir}/app_task/source/AppTaskFreeRTOS.cpp", - "${common_example_dir}/device_callbacks/source/CommonDeviceCallbacks.cpp", - "${common_example_dir}/device_manager/source/CHIPDeviceManager.cpp", - "${common_example_dir}/icd/source/ICDUtil.cpp", - "${common_example_dir}/matter_button/source/ButtonRegistrationEmpty.cpp", - ] - - deps = [ - "${chip_root}/examples/${app_common_folder}", - "${chip_root}/src/app/clusters/network-commissioning:network-commissioning", - "${chip_root}/src/setup_payload:onboarding-codes-utils", - ] - - sources += [ - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/laundry-washer-controls-delegate-impl.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp", - "../../common/main/laundry-washer-mode.cpp", - ] - - if (nxp_enable_matter_cli) { - defines += [ "ENABLE_CHIP_SHELL" ] - deps += [ - "${chip_root}/examples/shell/shell_common:shell_common", - "${chip_root}/src/lib/shell:shell", - ] - sources += [ - "${common_example_dir}/matter_cli/source/AppCLIBase.cpp", - "${common_example_dir}/matter_cli/source/AppCLIFreeRTOS.cpp", - ] - } - - if (chip_enable_ota_requestor) { - sources += [ - "${chip_root}/examples/platform/nxp/common/mcuboot_app_support/flash_partitioning.h", - "${common_example_dir}/ota_requestor/source/OTARequestorInitiator.cpp", - "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorCommon.cpp", - - #Adding mcuboot files - "${chip_root}/examples/platform/nxp/common/mcuboot_app_support/mcuboot_app_support.c", - "${chip_root}/examples/platform/nxp/common/mcuboot_app_support/mcuboot_app_support.h", - ] - include_dirs += [ - "$${common_example_dir}/ota_requestor/include", - "${chip_root}/examples/platform/nxp/common/mcuboot_app_support", - ] - } - - if (wifi_auto_connect_at_boot) { - assert(wifi_auto_connect_at_boot_ssid != "" && - wifi_auto_connect_at_boot_password != "", - "WiFi SSID and password must be specified at build time!") - - defines += [ - "CONFIG_CHIP_APP_WIFI_CONNECT_AT_BOOT=1", - "CONFIG_CHIP_APP_WIFI_SSID=\"${wifi_auto_connect_at_boot_ssid}\"", - "CONFIG_CHIP_APP_WIFI_PASSWORD=\"${wifi_auto_connect_at_boot_password}\"", - ] - - include_dirs += [ "${common_example_dir}/wifi_connect/include" ] - sources += [ "${common_example_dir}/wifi_connect/source/WifiConnect.cpp" ] - } - - if (enable_ota_provider) { - defines += [ "CONFIG_CHIP_OTA_PROVIDER=1" ] - - include_dirs += [ - "${common_example_dir}/ota_provider/include", - "${common_example_dir}/ota_provider/ota-provider-common", - ] - - sources += [ - "${common_example_dir}/ota_provider/ota-provider-common/RTBdxOtaSender.cpp", - "${common_example_dir}/ota_provider/ota-provider-common/RTOTAProviderExample.cpp", - "${common_example_dir}/ota_provider/source/OTAProvider.cpp", - ] - - deps += [ - "${chip_root}/src/app/server", - "${chip_root}/src/protocols/bdx", - "${chip_root}/third_party/jsoncpp", - ] - } - - # In case a dedicated assert function needs to be supported the flag sdk_fsl_assert_support should be set to false - # The would add to the build a dedicated application assert implementation. - if (!sdk_fsl_assert_support) { - sources += [ "${common_example_dir}/app_assert/source/AppAssert.cpp" ] - } - - cflags = [ "-Wconversion" ] - - ldscript = - "${example_platform_dir}/app/ldscripts/MIMXRT1062xxxxx_flexspi_nor.ld" - - inputs = [ ldscript ] - - ldflags = [ - "-T" + rebase_path(ldscript, root_build_dir), - "-fno-common", - "-Wl,--defsym=__stack_size__=2048", - "-ffreestanding", - "-fno-builtin", - "-mapcs", - "-u qspiflash_config", - "-u image_vector_table", - "-u boot_data", - "-u dcd_data", - "-Wl,-print-memory-usage", - "-Wl,--no-warn-rwx-segments", - ] - - if (enable_ota_provider) { - # As the OTA file will be stored in the littlefs file system, it is required to increase the size of the file system - # To be able to store an OTA file with a MAX size of 640K, - # it recommended to size the file system with: - # 161 sectors of 4K => reserved for the OTA file - # 32 sectors of 4K => reserved for Matter/OT/BLE settings storage - ldflags += [ "-Wl,--defsym=gNVMSectorCountLink_d=193" ] - } - - if (chip_enable_ota_requestor) { - # If OTA build flag is enabled, - # we would need to reserve enough space for the bootloader (MCUBoot) - # MCUBoot requires 0x11000 Bytes to be reserved at the base of the flash - # Consequently, some sections will need to be shifted - ldflags += [ "-Wl,--defsym=__mcu_boot_size__=0x11000" ] - } - - output_dir = root_out_dir -} - -group("rt1060") { - deps = [ ":laundry-washer" ] -} - -group("default") { - deps = [ ":rt1060" ] -} diff --git a/examples/laundry-washer-app/nxp/rt/rt1060/README.md b/examples/laundry-washer-app/nxp/rt/rt1060/README.md deleted file mode 100644 index f7fcebce8a2..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rt1060/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# CHIP RT1060 Thermostat Application - -All instructions describing how to use a Matter application on NXP RT1060 can be -found in [README.md](../../../../../docs/platforms/nxp/nxp_rt1060_guide.md) root -readme diff --git a/examples/laundry-washer-app/nxp/rt/rt1060/args.gni b/examples/laundry-washer-app/nxp/rt/rt1060/args.gni deleted file mode 100644 index d65714c9287..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rt1060/args.gni +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2023 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") - -# SDK target definitions -nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") -nxp_sdk_driver_target = get_label_info(":sdk_driver", "label_no_toolchain") - -# ICDM -chip_enable_icd_server = true -chip_persist_subscriptions = true -chip_subscription_timeout_resumption = true -chip_enable_icd_checkin = true diff --git a/examples/laundry-washer-app/nxp/rt/rt1060/build_overrides b/examples/laundry-washer-app/nxp/rt/rt1060/build_overrides deleted file mode 120000 index f10867042f4..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rt1060/build_overrides +++ /dev/null @@ -1 +0,0 @@ -../../../../build_overrides \ No newline at end of file diff --git a/examples/laundry-washer-app/nxp/rt/rt1060/include/config/CHIPProjectConfig.h b/examples/laundry-washer-app/nxp/rt/rt1060/include/config/CHIPProjectConfig.h deleted file mode 100644 index 61be0867102..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rt1060/include/config/CHIPProjectConfig.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2020 Google LLC. - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Example project configuration file for CHIP. - * - * This is a place to put application or project-specific overrides - * to the default configuration values for general CHIP features. - * - */ - -#pragma once - -/* - * Tells to the platform Factory Data Provider whether to use the example configuration or real/provisioned data. - */ -#ifndef CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -#define CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA 0 -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID - * - * 0xFFF1: Test vendor. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1 - -/** - * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID - * - */ -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8005 - -#if !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -// Use a default pairing code if one hasn't been provisioned in flash. -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 -#endif - -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 -#endif - -// Use a default pairing code if one hasn't been provisioned in flash. -#define CHIP_DEVICE_CONFIG_USE_TEST_PAIRING_CODE "CHIPUS" - -/** - * CHIP_DEVICE_CONFIG_USE_TEST_SERIAL_NUMBER - * - * Enables the use of a hard-coded default serial number if none - * is found in CHIP NV storage. - */ -#define CHIP_DEVICE_CONFIG_USE_TEST_SERIAL_NUMBER "DUMMY_SN" - -#endif /* !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA */ - -/** - * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION - * - * The hardware version number assigned to device or product by the device vendor. This - * number is scoped to the device product id, and typically corresponds to a revision of the - * physical device, a change to its packaging, and/or a change to its marketing presentation. - * This value is generally *not* incremented for device software versions. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 100 - -#ifndef CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING "v0.1.0" -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING - * - * A string identifying the software version running on the device. - * CHIP currently expects the software version to be in the format - * {MAJOR_VERSION}.0d{MINOR_VERSION} - */ -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION NXP_CONFIG_DEVICE_SOFTWARE_VERSION -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "NXP Semiconductors" -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "NXP Demo App" -#endif - -#ifndef CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION -//-> format_version = 1 -//-> vendor_id = 0xFFF1 -//-> product_id_array = [ 0x8000, 0x8001, 0x8002, 0x8003, 0x8004, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009, 0x800A, 0x800B, -// 0x800C, 0x800D, 0x800E, 0x800F, 0x8010, 0x8011, 0x8012, 0x8013, 0x8014, 0x8015, 0x8016, 0x8017, 0x8018, 0x8019, 0x801A, -// 0x801B, 0x801C, 0x801D, 0x801E, 0x801F, 0x8020, 0x8021, 0x8022, 0x8023, 0x8024, 0x8025, 0x8026, 0x8027, 0x8028, 0x8029, -// 0x802A, 0x802B, 0x802C, 0x802D, 0x802E, 0x802F, 0x8030, 0x8031, 0x8032, 0x8033, 0x8034, 0x8035, 0x8036, 0x8037, 0x8038, -// 0x8039, 0x803A, 0x803B, 0x803C, 0x803D, 0x803E, 0x803F, 0x8040, 0x8041, 0x8042, 0x8043, 0x8044, 0x8045, 0x8046, 0x8047, -// 0x8048, 0x8049, 0x804A, 0x804B, 0x804C, 0x804D, 0x804E, 0x804F, 0x8050, 0x8051, 0x8052, 0x8053, 0x8054, 0x8055, 0x8056, -// 0x8057, 0x8058, 0x8059, 0x805A, 0x805B, 0x805C, 0x805D, 0x805E, 0x805F, 0x8060, 0x8061, 0x8062, 0x8063 ] -//-> device_type_id = 0x0016 -//-> certificate_id = "ZIG20142ZB330003-24" -//-> security_level = 0 -//-> security_information = 0 -//-> version_number = 0x2694 -//-> certification_type = 0 -//-> dac_origin_vendor_id is not present -//-> dac_origin_product_id is not present -#define CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION \ - { \ - 0x30, 0x82, 0x02, 0x19, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0x0a, 0x30, \ - 0x82, 0x02, 0x06, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, \ - 0x02, 0x01, 0x30, 0x82, 0x01, 0x71, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, \ - 0x01, 0x62, 0x04, 0x82, 0x01, 0x5e, 0x15, 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, \ - 0x05, 0x01, 0x80, 0x05, 0x02, 0x80, 0x05, 0x03, 0x80, 0x05, 0x04, 0x80, 0x05, 0x05, 0x80, 0x05, 0x06, 0x80, 0x05, \ - 0x07, 0x80, 0x05, 0x08, 0x80, 0x05, 0x09, 0x80, 0x05, 0x0a, 0x80, 0x05, 0x0b, 0x80, 0x05, 0x0c, 0x80, 0x05, 0x0d, \ - 0x80, 0x05, 0x0e, 0x80, 0x05, 0x0f, 0x80, 0x05, 0x10, 0x80, 0x05, 0x11, 0x80, 0x05, 0x12, 0x80, 0x05, 0x13, 0x80, \ - 0x05, 0x14, 0x80, 0x05, 0x15, 0x80, 0x05, 0x16, 0x80, 0x05, 0x17, 0x80, 0x05, 0x18, 0x80, 0x05, 0x19, 0x80, 0x05, \ - 0x1a, 0x80, 0x05, 0x1b, 0x80, 0x05, 0x1c, 0x80, 0x05, 0x1d, 0x80, 0x05, 0x1e, 0x80, 0x05, 0x1f, 0x80, 0x05, 0x20, \ - 0x80, 0x05, 0x21, 0x80, 0x05, 0x22, 0x80, 0x05, 0x23, 0x80, 0x05, 0x24, 0x80, 0x05, 0x25, 0x80, 0x05, 0x26, 0x80, \ - 0x05, 0x27, 0x80, 0x05, 0x28, 0x80, 0x05, 0x29, 0x80, 0x05, 0x2a, 0x80, 0x05, 0x2b, 0x80, 0x05, 0x2c, 0x80, 0x05, \ - 0x2d, 0x80, 0x05, 0x2e, 0x80, 0x05, 0x2f, 0x80, 0x05, 0x30, 0x80, 0x05, 0x31, 0x80, 0x05, 0x32, 0x80, 0x05, 0x33, \ - 0x80, 0x05, 0x34, 0x80, 0x05, 0x35, 0x80, 0x05, 0x36, 0x80, 0x05, 0x37, 0x80, 0x05, 0x38, 0x80, 0x05, 0x39, 0x80, \ - 0x05, 0x3a, 0x80, 0x05, 0x3b, 0x80, 0x05, 0x3c, 0x80, 0x05, 0x3d, 0x80, 0x05, 0x3e, 0x80, 0x05, 0x3f, 0x80, 0x05, \ - 0x40, 0x80, 0x05, 0x41, 0x80, 0x05, 0x42, 0x80, 0x05, 0x43, 0x80, 0x05, 0x44, 0x80, 0x05, 0x45, 0x80, 0x05, 0x46, \ - 0x80, 0x05, 0x47, 0x80, 0x05, 0x48, 0x80, 0x05, 0x49, 0x80, 0x05, 0x4a, 0x80, 0x05, 0x4b, 0x80, 0x05, 0x4c, 0x80, \ - 0x05, 0x4d, 0x80, 0x05, 0x4e, 0x80, 0x05, 0x4f, 0x80, 0x05, 0x50, 0x80, 0x05, 0x51, 0x80, 0x05, 0x52, 0x80, 0x05, \ - 0x53, 0x80, 0x05, 0x54, 0x80, 0x05, 0x55, 0x80, 0x05, 0x56, 0x80, 0x05, 0x57, 0x80, 0x05, 0x58, 0x80, 0x05, 0x59, \ - 0x80, 0x05, 0x5a, 0x80, 0x05, 0x5b, 0x80, 0x05, 0x5c, 0x80, 0x05, 0x5d, 0x80, 0x05, 0x5e, 0x80, 0x05, 0x5f, 0x80, \ - 0x05, 0x60, 0x80, 0x05, 0x61, 0x80, 0x05, 0x62, 0x80, 0x05, 0x63, 0x80, 0x18, 0x24, 0x03, 0x16, 0x2c, 0x04, 0x13, \ - 0x5a, 0x49, 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x34, \ - 0x24, 0x05, 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x94, 0x26, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7d, 0x30, 0x7b, 0x02, \ - 0x01, 0x03, 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, \ - 0xf5, 0x04, 0xf3, 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, \ - 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x24, 0xe5, \ - 0xd1, 0xf4, 0x7a, 0x7d, 0x7b, 0x0d, 0x20, 0x6a, 0x26, 0xef, 0x69, 0x9b, 0x7c, 0x97, 0x57, 0xb7, 0x2d, 0x46, 0x90, \ - 0x89, 0xde, 0x31, 0x92, 0xe6, 0x78, 0xc7, 0x45, 0xe7, 0xf6, 0x0c, 0x02, 0x21, 0x00, 0xf8, 0xaa, 0x2f, 0xa7, 0x11, \ - 0xfc, 0xb7, 0x9b, 0x97, 0xe3, 0x97, 0xce, 0xda, 0x66, 0x7b, 0xae, 0x46, 0x4e, 0x2b, 0xd3, 0xff, 0xdf, 0xc3, 0xcc, \ - 0xed, 0x7a, 0xa8, 0xca, 0x5f, 0x4c, 0x1a, 0x7c \ - } -#endif - -/** - * CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC - * - * Enables synchronizing the device's real time clock with a remote CHIP Time service - * using the CHIP Time Sync protocol. - */ -// #define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 1 - -/** - * CHIP_CONFIG_EVENT_LOGGING_WDM_OFFLOAD - * - * Select the ability to offload event logs to any interested subscribers using WDM. - */ -#define CHIP_CONFIG_EVENT_LOGGING_WDM_OFFLOAD 1 - -/** - * CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS - * - * Enable recording UTC timestamps. - */ -#define CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1 - -/** - * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE - * - * A size, in bytes, of the individual debug event logging buffer. - */ -#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512) - -/** - * CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE - * - * For a development build, set the default importance of events to be logged as Debug. - * Since debug is the lowest importance level, this means all standard, critical, info and - * debug importance level vi events get logged. - */ -#if BUILD_RELEASE -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Production -#else -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug -#endif // BUILD_RELEASE - -/* Increasing the retransmission interval of the MRP messages after subsequent failures */ -#ifndef CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL -#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32) -#endif diff --git a/examples/laundry-washer-app/nxp/rt/rt1060/third_party/connectedhomeip b/examples/laundry-washer-app/nxp/rt/rt1060/third_party/connectedhomeip deleted file mode 120000 index 305f2077ffe..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rt1060/third_party/connectedhomeip +++ /dev/null @@ -1 +0,0 @@ -../../../../../.. \ No newline at end of file diff --git a/examples/laundry-washer-app/nxp/rt/rt1170/.gn b/examples/laundry-washer-app/nxp/rt/rt1170/.gn deleted file mode 100644 index 59dcfeb229a..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rt1170/.gn +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) 2020 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") -import("//build_overrides/chip.gni") - -# The location of the build configuration file. -buildconfig = "${build_root}/config/BUILDCONFIG.gn" - -# CHIP uses angle bracket includes. -check_system_includes = true - -default_args = { - target_cpu = "arm" - target_os = "freertos" - - import("//args.gni") - - # Import common example GN args - import("${chip_root}/examples/platform/nxp/common/gn/args.gni") - - # Import default platform configs - import("${chip_root}/src/platform/nxp/rt/rt1170/args.gni") -} diff --git a/examples/laundry-washer-app/nxp/rt/rt1170/BUILD.gn b/examples/laundry-washer-app/nxp/rt/rt1170/BUILD.gn deleted file mode 100644 index c465e8497ae..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rt1170/BUILD.gn +++ /dev/null @@ -1,270 +0,0 @@ -# Copyright (c) 2021-2023 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") -import("//build_overrides/chip.gni") -import("//build_overrides/nxp_sdk.gni") -import("//build_overrides/openthread.gni") -import("${chip_root}/src/platform/device.gni") - -#allows to get common NXP SDK gn options -import("${nxp_sdk_build_root}/nxp_sdk.gni") - -# Allows to get various RT gn options -import("${nxp_sdk_build_root}/${nxp_sdk_name}/rt_sdk.gni") - -import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") -import( - "${nxp_sdk_build_root}/${nxp_sdk_name}/${rt_platform}/${rt_platform}.gni") -import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") - -assert(current_os == "freertos") -assert(target_os == "freertos") -assert(nxp_platform == "rt/rt1170") - -declare_args() { - # Allows to connect to a predefine Wi-Fi network at boot - wifi_auto_connect_at_boot = false - wifi_auto_connect_at_boot_ssid = "" - wifi_auto_connect_at_boot_password = "" - - # Setup discriminator as argument - setup_discriminator = 3840 - - chip_with_diag_logs_demo = true -} - -example_platform_dir = - "${nxp_sdk_matter_support_root}/examples/platform/${nxp_platform}" -common_example_dir = "${chip_root}/examples/platform/nxp/common" - -# Use NXP custom zap files for laundry-washer device-type -app_common_folder = "laundry-washer-app/nxp/zap" - -# Create here the SDK instance. -# Particular sources/defines/includes could be added/changed depending on the target application. -rt_sdk("sdk") { - defines = [] - - cflags = [] - public_deps = [] - public_configs = [] - sources = [] - include_dirs = [] - - # Indicate paths to default board files - include_dirs += [ "${example_platform_dir}/board/" ] - sources += [ "${example_platform_dir}/board/pin_mux.c" ] - sources += [ "${example_platform_dir}/board/hardware_init.c" ] - sources += [ "${example_platform_dir}/board/clock_config.c" ] - sources += [ "${example_platform_dir}/board/board.c" ] - sources += [ "${example_platform_dir}/board/peripherals.c" ] - sources += [ "${example_platform_dir}/board/sdmmc_config.c" ] - sources += [ "${example_platform_dir}/board/wifi_bt_config.c" ] - - # Indicate the path to CHIPProjectConfig.h - include_dirs += [ "include/config" ] - - # Indicate the default path to FreeRTOSConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/freeRTOS" ] - - # Indicate the default path to OpenThreadConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/openthread" ] - - # For matter with BR feature, increase FreeRTOS heap size - if (chip_enable_wifi && chip_enable_openthread) { - defines += [ "configTOTAL_HEAP_SIZE=(size_t)(170 * 1024)" ] - } - - defines += [ - "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", - ] -} - -# Create the SDK driver instance. -# Particular sources/defines/includes could be added to add other drivers not available in the default sdk driver template -rt1170_sdk_drivers("sdk_driver") { -} - -rt_executable("laundry-washer-app") { - output_name = "chip-rt1170-laundry-washer-example" - - defines = [ - "CONFIG_RENDEZVOUS_MODE=7", - "CONFIG_APP_FREERTOS_OS=1", - ] - - if (chip_enable_openthread) { - defines += [ "CONFIG_NET_L2_OPENTHREAD=1" ] - } - - if (chip_with_diag_logs_demo) { - defines += [ - "CONFIG_DIAG_LOGS_DEMO=1", - "CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE=1024", - ] - } - - include_dirs = [ - "../../common/main/include", - "../../common/main", - "${chip_root}/examples/all-clusters-app/all-clusters-common/include", - "${chip_root}/examples/providers/", - ] - - sources = [ - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp", - "${chip_root}/examples/providers/DeviceInfoProviderImpl.cpp", - "../../common/main/AppTask.cpp", - "../../common/main/DeviceCallbacks.cpp", - "../../common/main/ZclCallbacks.cpp", - "../../common/main/include/AppEvent.h", - "../../common/main/include/AppTask.h", - "../../common/main/include/DeviceCallbacks.h", - "../../common/main/main.cpp", - ] - - if (chip_with_diag_logs_demo) { - include_dirs += [ - "${common_example_dir}/diagnostic_logs/include", - "${chip_root}", - ] - sources += [ - "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsDemo.cpp", - "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp", - ] - } - - # App common files - include_dirs += [ - "${common_example_dir}/icd/include", - "${common_example_dir}/matter_button/include", - "${common_example_dir}/matter_cli/include", - "${common_example_dir}/device_manager/include", - "${common_example_dir}/device_callbacks/include", - "${common_example_dir}/factory_data/include", - "${common_example_dir}/app_task/include", - ] - - sources += [ - "${common_example_dir}/app_task/source/AppTaskBase.cpp", - "${common_example_dir}/app_task/source/AppTaskFreeRTOS.cpp", - "${common_example_dir}/device_callbacks/source/CommonDeviceCallbacks.cpp", - "${common_example_dir}/device_manager/source/CHIPDeviceManager.cpp", - "${common_example_dir}/factory_data/source/AppFactoryDataDefaultImpl.cpp", - "${common_example_dir}/icd/source/ICDUtil.cpp", - "${common_example_dir}/matter_button/source/ButtonRegistrationEmpty.cpp", - ] - - deps = [ - "${chip_root}/examples/${app_common_folder}", - "${chip_root}/src/app/clusters/network-commissioning:network-commissioning", - "${chip_root}/src/setup_payload:onboarding-codes-utils", - ] - - sources += [ - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/laundry-washer-controls-delegate-impl.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp", - "../../common/main/laundry-washer-mode.cpp", - ] - - if (nxp_enable_matter_cli) { - defines += [ "ENABLE_CHIP_SHELL" ] - deps += [ - "${chip_root}/examples/shell/shell_common:shell_common", - "${chip_root}/src/lib/shell:shell", - ] - sources += [ - "${common_example_dir}/matter_cli/source/AppCLIBase.cpp", - "${common_example_dir}/matter_cli/source/AppCLIFreeRTOS.cpp", - ] - } - - if (chip_enable_ota_requestor) { - include_dirs += [ "${common_example_dir}/ota_requestor/include" ] - sources += [ - "${common_example_dir}/ota_requestor/source/OTARequestorInitiator.cpp", - "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorCommon.cpp", - ] - } - - if (wifi_auto_connect_at_boot) { - assert(wifi_auto_connect_at_boot_ssid != "" && - wifi_auto_connect_at_boot_password != "", - "WiFi SSID and password must be specified at build time!") - - defines += [ - "CONFIG_CHIP_APP_WIFI_CONNECT_AT_BOOT=1", - "CONFIG_CHIP_APP_WIFI_SSID=\"${wifi_auto_connect_at_boot_ssid}\"", - "CONFIG_CHIP_APP_WIFI_PASSWORD=\"${wifi_auto_connect_at_boot_password}\"", - ] - - include_dirs += [ "${common_example_dir}/wifi_connect/include" ] - sources += [ "${common_example_dir}/wifi_connect/source/WifiConnect.cpp" ] - } - - # In case a dedicated assert function needs to be supported the flag sdk_fsl_assert_support should be set to false - # The would add to the build a dedicated application assert implementation. - if (!sdk_fsl_assert_support) { - sources += [ "${common_example_dir}/app_assert/source/AppAssert.cpp" ] - } - - cflags = [ "-Wconversion" ] - - ldscript = - "${example_platform_dir}/app/ldscripts/MIMXRT1176xxxxx_cm7_flexspi_nor.ld" - - inputs = [ ldscript ] - - ldflags = [ - "-T" + rebase_path(ldscript, root_build_dir), - "-fno-common", - "-Wl,--defsym=__stack_size__=2048", - "-ffreestanding", - "-fno-builtin", - "-mapcs", - "-u qspiflash_config", - "-u image_vector_table", - "-u boot_data", - "-u dcd_data", - "-Wl,-print-memory-usage", - "-Wl,--no-warn-rwx-segments", - ] - - if (chip_enable_ota_requestor) { - if (no_mcuboot) { - # If "no_mcuboot" is set to true, the application will be linked at the base of the flash. - print( - "Warning : The OTA Requestor is enabled without MCUBoot. This will prevent the application from applying software updates.") - } else { - # we need to reserve enough space for the bootloader (MCUBoot) - # MCUBoot requires 0x40000 Bytes to be reserved at the base of the flash - # Consequently, some sections will need to be shifted - ldflags += [ "-Wl,--defsym=__m_mcuboot_size__=0x40000" ] - } - } - - output_dir = root_out_dir -} - -group("rt1170") { - deps = [ ":laundry-washer-app" ] -} - -group("default") { - deps = [ ":rt1170" ] -} diff --git a/examples/laundry-washer-app/nxp/rt/rt1170/README.md b/examples/laundry-washer-app/nxp/rt/rt1170/README.md deleted file mode 100644 index b44881ed489..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rt1170/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# CHIP RT1170 Thermostat Application - -All instructions describing how to use a Matter application on NXP RT11170 can -be found in [README.md](../../../../../docs/platforms/nxp/nxp_rt1170_guide.md) -root readme diff --git a/examples/laundry-washer-app/nxp/rt/rt1170/args.gni b/examples/laundry-washer-app/nxp/rt/rt1170/args.gni deleted file mode 100644 index d65714c9287..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rt1170/args.gni +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2023 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") - -# SDK target definitions -nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") -nxp_sdk_driver_target = get_label_info(":sdk_driver", "label_no_toolchain") - -# ICDM -chip_enable_icd_server = true -chip_persist_subscriptions = true -chip_subscription_timeout_resumption = true -chip_enable_icd_checkin = true diff --git a/examples/laundry-washer-app/nxp/rt/rt1170/build_overrides b/examples/laundry-washer-app/nxp/rt/rt1170/build_overrides deleted file mode 120000 index f10867042f4..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rt1170/build_overrides +++ /dev/null @@ -1 +0,0 @@ -../../../../build_overrides \ No newline at end of file diff --git a/examples/laundry-washer-app/nxp/rt/rt1170/include/config/CHIPProjectConfig.h b/examples/laundry-washer-app/nxp/rt/rt1170/include/config/CHIPProjectConfig.h deleted file mode 100644 index 61be0867102..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rt1170/include/config/CHIPProjectConfig.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2020 Google LLC. - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Example project configuration file for CHIP. - * - * This is a place to put application or project-specific overrides - * to the default configuration values for general CHIP features. - * - */ - -#pragma once - -/* - * Tells to the platform Factory Data Provider whether to use the example configuration or real/provisioned data. - */ -#ifndef CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -#define CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA 0 -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID - * - * 0xFFF1: Test vendor. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1 - -/** - * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID - * - */ -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8005 - -#if !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -// Use a default pairing code if one hasn't been provisioned in flash. -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 -#endif - -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 -#endif - -// Use a default pairing code if one hasn't been provisioned in flash. -#define CHIP_DEVICE_CONFIG_USE_TEST_PAIRING_CODE "CHIPUS" - -/** - * CHIP_DEVICE_CONFIG_USE_TEST_SERIAL_NUMBER - * - * Enables the use of a hard-coded default serial number if none - * is found in CHIP NV storage. - */ -#define CHIP_DEVICE_CONFIG_USE_TEST_SERIAL_NUMBER "DUMMY_SN" - -#endif /* !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA */ - -/** - * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION - * - * The hardware version number assigned to device or product by the device vendor. This - * number is scoped to the device product id, and typically corresponds to a revision of the - * physical device, a change to its packaging, and/or a change to its marketing presentation. - * This value is generally *not* incremented for device software versions. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 100 - -#ifndef CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING "v0.1.0" -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING - * - * A string identifying the software version running on the device. - * CHIP currently expects the software version to be in the format - * {MAJOR_VERSION}.0d{MINOR_VERSION} - */ -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION NXP_CONFIG_DEVICE_SOFTWARE_VERSION -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "NXP Semiconductors" -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "NXP Demo App" -#endif - -#ifndef CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION -//-> format_version = 1 -//-> vendor_id = 0xFFF1 -//-> product_id_array = [ 0x8000, 0x8001, 0x8002, 0x8003, 0x8004, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009, 0x800A, 0x800B, -// 0x800C, 0x800D, 0x800E, 0x800F, 0x8010, 0x8011, 0x8012, 0x8013, 0x8014, 0x8015, 0x8016, 0x8017, 0x8018, 0x8019, 0x801A, -// 0x801B, 0x801C, 0x801D, 0x801E, 0x801F, 0x8020, 0x8021, 0x8022, 0x8023, 0x8024, 0x8025, 0x8026, 0x8027, 0x8028, 0x8029, -// 0x802A, 0x802B, 0x802C, 0x802D, 0x802E, 0x802F, 0x8030, 0x8031, 0x8032, 0x8033, 0x8034, 0x8035, 0x8036, 0x8037, 0x8038, -// 0x8039, 0x803A, 0x803B, 0x803C, 0x803D, 0x803E, 0x803F, 0x8040, 0x8041, 0x8042, 0x8043, 0x8044, 0x8045, 0x8046, 0x8047, -// 0x8048, 0x8049, 0x804A, 0x804B, 0x804C, 0x804D, 0x804E, 0x804F, 0x8050, 0x8051, 0x8052, 0x8053, 0x8054, 0x8055, 0x8056, -// 0x8057, 0x8058, 0x8059, 0x805A, 0x805B, 0x805C, 0x805D, 0x805E, 0x805F, 0x8060, 0x8061, 0x8062, 0x8063 ] -//-> device_type_id = 0x0016 -//-> certificate_id = "ZIG20142ZB330003-24" -//-> security_level = 0 -//-> security_information = 0 -//-> version_number = 0x2694 -//-> certification_type = 0 -//-> dac_origin_vendor_id is not present -//-> dac_origin_product_id is not present -#define CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION \ - { \ - 0x30, 0x82, 0x02, 0x19, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0x0a, 0x30, \ - 0x82, 0x02, 0x06, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, \ - 0x02, 0x01, 0x30, 0x82, 0x01, 0x71, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, \ - 0x01, 0x62, 0x04, 0x82, 0x01, 0x5e, 0x15, 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, \ - 0x05, 0x01, 0x80, 0x05, 0x02, 0x80, 0x05, 0x03, 0x80, 0x05, 0x04, 0x80, 0x05, 0x05, 0x80, 0x05, 0x06, 0x80, 0x05, \ - 0x07, 0x80, 0x05, 0x08, 0x80, 0x05, 0x09, 0x80, 0x05, 0x0a, 0x80, 0x05, 0x0b, 0x80, 0x05, 0x0c, 0x80, 0x05, 0x0d, \ - 0x80, 0x05, 0x0e, 0x80, 0x05, 0x0f, 0x80, 0x05, 0x10, 0x80, 0x05, 0x11, 0x80, 0x05, 0x12, 0x80, 0x05, 0x13, 0x80, \ - 0x05, 0x14, 0x80, 0x05, 0x15, 0x80, 0x05, 0x16, 0x80, 0x05, 0x17, 0x80, 0x05, 0x18, 0x80, 0x05, 0x19, 0x80, 0x05, \ - 0x1a, 0x80, 0x05, 0x1b, 0x80, 0x05, 0x1c, 0x80, 0x05, 0x1d, 0x80, 0x05, 0x1e, 0x80, 0x05, 0x1f, 0x80, 0x05, 0x20, \ - 0x80, 0x05, 0x21, 0x80, 0x05, 0x22, 0x80, 0x05, 0x23, 0x80, 0x05, 0x24, 0x80, 0x05, 0x25, 0x80, 0x05, 0x26, 0x80, \ - 0x05, 0x27, 0x80, 0x05, 0x28, 0x80, 0x05, 0x29, 0x80, 0x05, 0x2a, 0x80, 0x05, 0x2b, 0x80, 0x05, 0x2c, 0x80, 0x05, \ - 0x2d, 0x80, 0x05, 0x2e, 0x80, 0x05, 0x2f, 0x80, 0x05, 0x30, 0x80, 0x05, 0x31, 0x80, 0x05, 0x32, 0x80, 0x05, 0x33, \ - 0x80, 0x05, 0x34, 0x80, 0x05, 0x35, 0x80, 0x05, 0x36, 0x80, 0x05, 0x37, 0x80, 0x05, 0x38, 0x80, 0x05, 0x39, 0x80, \ - 0x05, 0x3a, 0x80, 0x05, 0x3b, 0x80, 0x05, 0x3c, 0x80, 0x05, 0x3d, 0x80, 0x05, 0x3e, 0x80, 0x05, 0x3f, 0x80, 0x05, \ - 0x40, 0x80, 0x05, 0x41, 0x80, 0x05, 0x42, 0x80, 0x05, 0x43, 0x80, 0x05, 0x44, 0x80, 0x05, 0x45, 0x80, 0x05, 0x46, \ - 0x80, 0x05, 0x47, 0x80, 0x05, 0x48, 0x80, 0x05, 0x49, 0x80, 0x05, 0x4a, 0x80, 0x05, 0x4b, 0x80, 0x05, 0x4c, 0x80, \ - 0x05, 0x4d, 0x80, 0x05, 0x4e, 0x80, 0x05, 0x4f, 0x80, 0x05, 0x50, 0x80, 0x05, 0x51, 0x80, 0x05, 0x52, 0x80, 0x05, \ - 0x53, 0x80, 0x05, 0x54, 0x80, 0x05, 0x55, 0x80, 0x05, 0x56, 0x80, 0x05, 0x57, 0x80, 0x05, 0x58, 0x80, 0x05, 0x59, \ - 0x80, 0x05, 0x5a, 0x80, 0x05, 0x5b, 0x80, 0x05, 0x5c, 0x80, 0x05, 0x5d, 0x80, 0x05, 0x5e, 0x80, 0x05, 0x5f, 0x80, \ - 0x05, 0x60, 0x80, 0x05, 0x61, 0x80, 0x05, 0x62, 0x80, 0x05, 0x63, 0x80, 0x18, 0x24, 0x03, 0x16, 0x2c, 0x04, 0x13, \ - 0x5a, 0x49, 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x34, \ - 0x24, 0x05, 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x94, 0x26, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7d, 0x30, 0x7b, 0x02, \ - 0x01, 0x03, 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, \ - 0xf5, 0x04, 0xf3, 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, \ - 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x24, 0xe5, \ - 0xd1, 0xf4, 0x7a, 0x7d, 0x7b, 0x0d, 0x20, 0x6a, 0x26, 0xef, 0x69, 0x9b, 0x7c, 0x97, 0x57, 0xb7, 0x2d, 0x46, 0x90, \ - 0x89, 0xde, 0x31, 0x92, 0xe6, 0x78, 0xc7, 0x45, 0xe7, 0xf6, 0x0c, 0x02, 0x21, 0x00, 0xf8, 0xaa, 0x2f, 0xa7, 0x11, \ - 0xfc, 0xb7, 0x9b, 0x97, 0xe3, 0x97, 0xce, 0xda, 0x66, 0x7b, 0xae, 0x46, 0x4e, 0x2b, 0xd3, 0xff, 0xdf, 0xc3, 0xcc, \ - 0xed, 0x7a, 0xa8, 0xca, 0x5f, 0x4c, 0x1a, 0x7c \ - } -#endif - -/** - * CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC - * - * Enables synchronizing the device's real time clock with a remote CHIP Time service - * using the CHIP Time Sync protocol. - */ -// #define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 1 - -/** - * CHIP_CONFIG_EVENT_LOGGING_WDM_OFFLOAD - * - * Select the ability to offload event logs to any interested subscribers using WDM. - */ -#define CHIP_CONFIG_EVENT_LOGGING_WDM_OFFLOAD 1 - -/** - * CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS - * - * Enable recording UTC timestamps. - */ -#define CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1 - -/** - * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE - * - * A size, in bytes, of the individual debug event logging buffer. - */ -#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512) - -/** - * CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE - * - * For a development build, set the default importance of events to be logged as Debug. - * Since debug is the lowest importance level, this means all standard, critical, info and - * debug importance level vi events get logged. - */ -#if BUILD_RELEASE -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Production -#else -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug -#endif // BUILD_RELEASE - -/* Increasing the retransmission interval of the MRP messages after subsequent failures */ -#ifndef CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL -#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32) -#endif diff --git a/examples/laundry-washer-app/nxp/rt/rt1170/third_party/connectedhomeip b/examples/laundry-washer-app/nxp/rt/rt1170/third_party/connectedhomeip deleted file mode 120000 index 305f2077ffe..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rt1170/third_party/connectedhomeip +++ /dev/null @@ -1 +0,0 @@ -../../../../../.. \ No newline at end of file diff --git a/examples/laundry-washer-app/nxp/rt/rw61x/.gn b/examples/laundry-washer-app/nxp/rt/rw61x/.gn deleted file mode 100644 index cbbec24fe8c..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rw61x/.gn +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (c) 2020 Project CHIP Authors -# Copyright 2023 NXP -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") -import("//build_overrides/chip.gni") - -# The location of the build configuration file. -buildconfig = "${build_root}/config/BUILDCONFIG.gn" - -# CHIP uses angle bracket includes. -check_system_includes = true - -default_args = { - target_cpu = "arm" - target_os = "freertos" - - import("//args.gni") - - # Import common example GN args - import("${chip_root}/examples/platform/nxp/common/gn/args.gni") - - # Import default platform configs - import("${chip_root}/src/platform/nxp/rt/rw61x/args.gni") -} diff --git a/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn b/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn deleted file mode 100644 index 17daaad3461..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn +++ /dev/null @@ -1,293 +0,0 @@ -# Copyright (c) 2021 Project CHIP Authors -# Copyright 2023-2024 NXP -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") -import("//build_overrides/chip.gni") -import("//build_overrides/nxp_sdk.gni") -import("//build_overrides/openthread.gni") -import("${chip_root}/src/platform/device.gni") - -#allows to get common NXP SDK gn options -import("${nxp_sdk_build_root}/nxp_sdk.gni") - -# Allows to get various RT gn options -import("${nxp_sdk_build_root}/${nxp_sdk_name}/rt_sdk.gni") - -import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") -import( - "${nxp_sdk_build_root}/${nxp_sdk_name}/${rt_platform}/${rt_platform}.gni") -import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") - -assert(current_os == "freertos") -assert(target_os == "freertos") -assert(nxp_platform == "rt/rw61x") - -declare_args() { - # Allows to connect to a predefine Wi-Fi network at boot - wifi_auto_connect_at_boot = false - wifi_auto_connect_at_boot_ssid = "" - wifi_auto_connect_at_boot_password = "" - - # Setup discriminator as argument - setup_discriminator = 3840 - - chip_with_diag_logs_demo = true -} - -example_platform_dir = - "${nxp_sdk_matter_support_root}/examples/platform/${nxp_platform}" -common_example_dir = "${chip_root}/examples/platform/nxp/common" - -# Use NXP custom zap files for laundry-washer device-type -app_common_folder = "laundry-washer-app/nxp/zap" - -# Create here the SDK instance. -# Particular sources/defines/includes could be added/changed depending on the target application. -rt_sdk("sdk") { - defines = [] - - cflags = [] - public_deps = [] - public_configs = [] - sources = [] - include_dirs = [] - - # Indicate paths to default board files - include_dirs += [ "${example_platform_dir}/board/" ] - sources += [ "${example_platform_dir}/board/pin_mux.c" ] - sources += [ "${example_platform_dir}/board/hardware_init.c" ] - sources += [ "${example_platform_dir}/board/peripherals.c" ] - - if (board_version == "frdm") { - include_dirs += [ "${example_platform_dir}/board/frdmrw612/" ] - sources += [ "${example_platform_dir}/board/frdmrw612/clock_config.c" ] - sources += [ "${example_platform_dir}/board/frdmrw612/board.c" ] - } else { - include_dirs += [ "${example_platform_dir}/board/rdrw612bga/" ] - sources += [ "${example_platform_dir}/board/rdrw612bga/clock_config.c" ] - sources += [ "${example_platform_dir}/board/rdrw612bga/board.c" ] - } - - # Indicate the path to CHIPProjectConfig.h - include_dirs += [ "include/config" ] - - # Indicate the default path to FreeRTOSConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/freeRTOS" ] - - # Indicate the default path to OpenThreadConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/openthread" ] - - # For matter with BR feature, increase FreeRTOS heap size - if (chip_enable_wifi && chip_enable_openthread) { - defines += [ "configTOTAL_HEAP_SIZE=(size_t)(170 * 1024)" ] - } - - defines += [ - "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", - ] -} - -# Create the SDK driver instance. -# Particular sources/defines/includes could be added to add other drivers not available in the default sdk driver template -rw61x_sdk_drivers("sdk_driver") { -} - -rt_executable("laundry-washer") { - output_name = "chip-rw61x-laundry-washer-example" - - defines = [ - "CONFIG_RENDEZVOUS_MODE=7", - "CONFIG_APP_FREERTOS_OS=1", - ] - - if (chip_enable_openthread) { - defines += [ "CONFIG_NET_L2_OPENTHREAD=1" ] - } - - if (chip_with_diag_logs_demo) { - defines += [ - "CONFIG_DIAG_LOGS_DEMO=1", - "CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE=1024", - ] - } - - include_dirs = [ - "../../common/main/include", - "../../common/main", - "${chip_root}/examples/all-clusters-app/all-clusters-common/include", - "${chip_root}/examples/providers/", - ] - - sources = [ - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp", - "${chip_root}/examples/providers/DeviceInfoProviderImpl.cpp", - "../../common/main/AppTask.cpp", - "../../common/main/DeviceCallbacks.cpp", - "../../common/main/ZclCallbacks.cpp", - "../../common/main/include/AppEvent.h", - "../../common/main/include/AppTask.h", - "../../common/main/include/DeviceCallbacks.h", - "../../common/main/main.cpp", - ] - - if (chip_with_diag_logs_demo) { - include_dirs += [ - "${common_example_dir}/diagnostic_logs/include", - "${chip_root}", - ] - sources += [ - "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsDemo.cpp", - "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp", - ] - } - - if (nxp_enable_secure_whole_factory_data || - nxp_enable_secure_EL2GO_factory_data) { - sources += [ "${chip_root}/examples/platform/nxp/${nxp_platform}/factory_data/source/AppFactoryDataExample.cpp" ] - if (nxp_enable_secure_whole_factory_data) { - defines += [ "ENABLE_SECURE_WHOLE_FACTORY_DATA" ] - } - } else { - sources += [ - "${common_example_dir}/factory_data/source/AppFactoryDataDefaultImpl.cpp", - ] - } - - # App common files - include_dirs += [ - "${common_example_dir}/icd/include", - "${common_example_dir}/matter_button/include", - "${common_example_dir}/matter_cli/include", - "${common_example_dir}/device_manager/include", - "${common_example_dir}/device_callbacks/include", - "${common_example_dir}/app_task/include", - "${common_example_dir}/factory_data/include", - "${common_example_dir}/operational_keystore/include", - ] - - sources += [ - "${common_example_dir}/app_task/source/AppTaskBase.cpp", - "${common_example_dir}/app_task/source/AppTaskFreeRTOS.cpp", - "${common_example_dir}/device_callbacks/source/CommonDeviceCallbacks.cpp", - "${common_example_dir}/device_manager/source/CHIPDeviceManager.cpp", - "${common_example_dir}/icd/source/ICDUtil.cpp", - "${common_example_dir}/matter_button/source/ButtonRegistrationEmpty.cpp", - "${common_example_dir}/operational_keystore/source/OperationalKeystoreS50.cpp", - ] - - deps = [ - "${chip_root}/examples/${app_common_folder}", - "${chip_root}/src/app/clusters/network-commissioning:network-commissioning", - "${chip_root}/src/platform/logging:default", - "${chip_root}/src/setup_payload:onboarding-codes-utils", - ] - - # Operational key secure storage - defines += [ "CONFIG_OPERATIONAL_KEYSTORE=1" ] - - sources += [ - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/laundry-washer-controls-delegate-impl.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp", - "../../common/main/laundry-washer-mode.cpp", - ] - - if (nxp_enable_matter_cli) { - defines += [ "ENABLE_CHIP_SHELL" ] - deps += [ - "${chip_root}/examples/shell/shell_common:shell_common", - "${chip_root}/src/lib/shell:shell", - ] - sources += [ - "${common_example_dir}/matter_cli/source/AppCLIBase.cpp", - "${common_example_dir}/matter_cli/source/AppCLIFreeRTOS.cpp", - ] - } - - if (chip_enable_ota_requestor) { - include_dirs += [ "${common_example_dir}/ota_requestor/include" ] - sources += [ - "${common_example_dir}/ota_requestor/source/OTARequestorInitiator.cpp", - "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorCommon.cpp", - ] - } - - if (wifi_auto_connect_at_boot) { - assert(wifi_auto_connect_at_boot_ssid != "" && - wifi_auto_connect_at_boot_password != "", - "WiFi SSID and password must be specified at build time!") - - defines += [ - "CONFIG_CHIP_APP_WIFI_CONNECT_AT_BOOT=1", - "CONFIG_CHIP_APP_WIFI_SSID=\"${wifi_auto_connect_at_boot_ssid}\"", - "CONFIG_CHIP_APP_WIFI_PASSWORD=\"${wifi_auto_connect_at_boot_password}\"", - ] - - include_dirs += [ "${common_example_dir}/wifi_connect/include" ] - sources += [ "${common_example_dir}/wifi_connect/source/WifiConnect.cpp" ] - } - - # In case a dedicated assert function needs to be supported the flag sdk_fsl_assert_support should be set to false - # The would add to the build a dedicated application assert implementation. - if (!sdk_fsl_assert_support) { - sources += [ "${common_example_dir}/app_assert/source/AppAssert.cpp" ] - } - - cflags = [ "-Wconversion" ] - - ldscript = "${example_platform_dir}/app/ldscripts/RW610_flash.ld" - - inputs = [ ldscript ] - - ldflags = [ - "-T" + rebase_path(ldscript, root_build_dir), - "-fno-common", - "-Wl,--defsym=__stack_size__=2048", - "-ffreestanding", - "-fno-builtin", - "-mapcs", - "-u qspiflash_config", - "-u image_vector_table", - "-u boot_data", - "-u dcd_data", - "-Wl,-print-memory-usage", - "-Wl,--no-warn-rwx-segments", - ] - - if (chip_enable_ota_requestor) { - if (no_mcuboot) { - # If "no_mcuboot" is set to true, the application will be linked at the base of the flash. - print( - "Warning : The OTA Requestor is enabled without MCUBoot. This will prevent the application from applying software updates.") - } else { - # we need to reserve enough space for the bootloader (MCUBoot) - # MCUBoot requires 0x20000 Bytes to be reserved at the base of the flash - # Consequently, some sections will need to be shifted - ldflags += [ "-Wl,--defsym=__m_mcuboot_size__=0x20000" ] - } - } - - output_dir = root_out_dir -} - -group("rw61x") { - deps = [ ":laundry-washer" ] -} - -group("default") { - deps = [ ":rw61x" ] -} diff --git a/examples/laundry-washer-app/nxp/rt/rw61x/README.md b/examples/laundry-washer-app/nxp/rt/rw61x/README.md deleted file mode 100644 index 51329477133..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rw61x/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# CHIP RW61x Laundry washer Application - -All instructions describing how to use a Matter application on NXP RW61x can be -found in [README.md](../../../../../docs/platforms/nxp/nxp_rw61x_guide.md) root -readme diff --git a/examples/laundry-washer-app/nxp/rt/rw61x/args.gni b/examples/laundry-washer-app/nxp/rt/rw61x/args.gni deleted file mode 100644 index d65714c9287..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rw61x/args.gni +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2023 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") - -# SDK target definitions -nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") -nxp_sdk_driver_target = get_label_info(":sdk_driver", "label_no_toolchain") - -# ICDM -chip_enable_icd_server = true -chip_persist_subscriptions = true -chip_subscription_timeout_resumption = true -chip_enable_icd_checkin = true diff --git a/examples/laundry-washer-app/nxp/rt/rw61x/build_overrides b/examples/laundry-washer-app/nxp/rt/rw61x/build_overrides deleted file mode 120000 index f10867042f4..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rw61x/build_overrides +++ /dev/null @@ -1 +0,0 @@ -../../../../build_overrides \ No newline at end of file diff --git a/examples/laundry-washer-app/nxp/rt/rw61x/include/config/CHIPProjectConfig.h b/examples/laundry-washer-app/nxp/rt/rw61x/include/config/CHIPProjectConfig.h deleted file mode 100644 index 33a42909f46..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rw61x/include/config/CHIPProjectConfig.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2020 Google LLC. - * Copyright 2023 NXP - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Example project configuration file for CHIP. - * - * This is a place to put application or project-specific overrides - * to the default configuration values for general CHIP features. - * - */ - -#pragma once - -/* - * Tells to the platform Factory Data Provider whether to use the example configuration or real/provisioned data. - */ -#ifndef CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -#define CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA 0 -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID - * - * 0xFFF1: Test vendor. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1 - -/** - * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID - * - */ -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8005 - -#if !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -// Use a default pairing code if one hasn't been provisioned in flash. -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 -#endif - -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 -#endif - -// Use a default pairing code if one hasn't been provisioned in flash. -#define CHIP_DEVICE_CONFIG_USE_TEST_PAIRING_CODE "CHIPUS" - -/** - * CHIP_DEVICE_CONFIG_USE_TEST_SERIAL_NUMBER - * - * Enables the use of a hard-coded default serial number if none - * is found in CHIP NV storage. - */ -#define CHIP_DEVICE_CONFIG_USE_TEST_SERIAL_NUMBER "DUMMY_SN" - -#endif /* !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA */ - -/** - * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION - * - * The hardware version number assigned to device or product by the device vendor. This - * number is scoped to the device product id, and typically corresponds to a revision of the - * physical device, a change to its packaging, and/or a change to its marketing presentation. - * This value is generally *not* incremented for device software versions. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 100 - -#ifndef CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING "v0.1.0" -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING - * - * A string identifying the software version running on the device. - * CHIP currently expects the software version to be in the format - * {MAJOR_VERSION}.0d{MINOR_VERSION} - */ -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION NXP_CONFIG_DEVICE_SOFTWARE_VERSION -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "NXP Semiconductors" -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "NXP Demo App" -#endif - -#ifndef CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION -//-> format_version = 1 -//-> vendor_id = 0xFFF1 -//-> product_id_array = [ 0x8000, 0x8001, 0x8002, 0x8003, 0x8004, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009, 0x800A, 0x800B, -// 0x800C, 0x800D, 0x800E, 0x800F, 0x8010, 0x8011, 0x8012, 0x8013, 0x8014, 0x8015, 0x8016, 0x8017, 0x8018, 0x8019, 0x801A, -// 0x801B, 0x801C, 0x801D, 0x801E, 0x801F, 0x8020, 0x8021, 0x8022, 0x8023, 0x8024, 0x8025, 0x8026, 0x8027, 0x8028, 0x8029, -// 0x802A, 0x802B, 0x802C, 0x802D, 0x802E, 0x802F, 0x8030, 0x8031, 0x8032, 0x8033, 0x8034, 0x8035, 0x8036, 0x8037, 0x8038, -// 0x8039, 0x803A, 0x803B, 0x803C, 0x803D, 0x803E, 0x803F, 0x8040, 0x8041, 0x8042, 0x8043, 0x8044, 0x8045, 0x8046, 0x8047, -// 0x8048, 0x8049, 0x804A, 0x804B, 0x804C, 0x804D, 0x804E, 0x804F, 0x8050, 0x8051, 0x8052, 0x8053, 0x8054, 0x8055, 0x8056, -// 0x8057, 0x8058, 0x8059, 0x805A, 0x805B, 0x805C, 0x805D, 0x805E, 0x805F, 0x8060, 0x8061, 0x8062, 0x8063 ] -//-> device_type_id = 0x0016 -//-> certificate_id = "ZIG20142ZB330003-24" -//-> security_level = 0 -//-> security_information = 0 -//-> version_number = 0x2694 -//-> certification_type = 0 -//-> dac_origin_vendor_id is not present -//-> dac_origin_product_id is not present -#define CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION \ - { \ - 0x30, 0x82, 0x02, 0x19, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0x0a, 0x30, \ - 0x82, 0x02, 0x06, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, \ - 0x02, 0x01, 0x30, 0x82, 0x01, 0x71, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, \ - 0x01, 0x62, 0x04, 0x82, 0x01, 0x5e, 0x15, 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, \ - 0x05, 0x01, 0x80, 0x05, 0x02, 0x80, 0x05, 0x03, 0x80, 0x05, 0x04, 0x80, 0x05, 0x05, 0x80, 0x05, 0x06, 0x80, 0x05, \ - 0x07, 0x80, 0x05, 0x08, 0x80, 0x05, 0x09, 0x80, 0x05, 0x0a, 0x80, 0x05, 0x0b, 0x80, 0x05, 0x0c, 0x80, 0x05, 0x0d, \ - 0x80, 0x05, 0x0e, 0x80, 0x05, 0x0f, 0x80, 0x05, 0x10, 0x80, 0x05, 0x11, 0x80, 0x05, 0x12, 0x80, 0x05, 0x13, 0x80, \ - 0x05, 0x14, 0x80, 0x05, 0x15, 0x80, 0x05, 0x16, 0x80, 0x05, 0x17, 0x80, 0x05, 0x18, 0x80, 0x05, 0x19, 0x80, 0x05, \ - 0x1a, 0x80, 0x05, 0x1b, 0x80, 0x05, 0x1c, 0x80, 0x05, 0x1d, 0x80, 0x05, 0x1e, 0x80, 0x05, 0x1f, 0x80, 0x05, 0x20, \ - 0x80, 0x05, 0x21, 0x80, 0x05, 0x22, 0x80, 0x05, 0x23, 0x80, 0x05, 0x24, 0x80, 0x05, 0x25, 0x80, 0x05, 0x26, 0x80, \ - 0x05, 0x27, 0x80, 0x05, 0x28, 0x80, 0x05, 0x29, 0x80, 0x05, 0x2a, 0x80, 0x05, 0x2b, 0x80, 0x05, 0x2c, 0x80, 0x05, \ - 0x2d, 0x80, 0x05, 0x2e, 0x80, 0x05, 0x2f, 0x80, 0x05, 0x30, 0x80, 0x05, 0x31, 0x80, 0x05, 0x32, 0x80, 0x05, 0x33, \ - 0x80, 0x05, 0x34, 0x80, 0x05, 0x35, 0x80, 0x05, 0x36, 0x80, 0x05, 0x37, 0x80, 0x05, 0x38, 0x80, 0x05, 0x39, 0x80, \ - 0x05, 0x3a, 0x80, 0x05, 0x3b, 0x80, 0x05, 0x3c, 0x80, 0x05, 0x3d, 0x80, 0x05, 0x3e, 0x80, 0x05, 0x3f, 0x80, 0x05, \ - 0x40, 0x80, 0x05, 0x41, 0x80, 0x05, 0x42, 0x80, 0x05, 0x43, 0x80, 0x05, 0x44, 0x80, 0x05, 0x45, 0x80, 0x05, 0x46, \ - 0x80, 0x05, 0x47, 0x80, 0x05, 0x48, 0x80, 0x05, 0x49, 0x80, 0x05, 0x4a, 0x80, 0x05, 0x4b, 0x80, 0x05, 0x4c, 0x80, \ - 0x05, 0x4d, 0x80, 0x05, 0x4e, 0x80, 0x05, 0x4f, 0x80, 0x05, 0x50, 0x80, 0x05, 0x51, 0x80, 0x05, 0x52, 0x80, 0x05, \ - 0x53, 0x80, 0x05, 0x54, 0x80, 0x05, 0x55, 0x80, 0x05, 0x56, 0x80, 0x05, 0x57, 0x80, 0x05, 0x58, 0x80, 0x05, 0x59, \ - 0x80, 0x05, 0x5a, 0x80, 0x05, 0x5b, 0x80, 0x05, 0x5c, 0x80, 0x05, 0x5d, 0x80, 0x05, 0x5e, 0x80, 0x05, 0x5f, 0x80, \ - 0x05, 0x60, 0x80, 0x05, 0x61, 0x80, 0x05, 0x62, 0x80, 0x05, 0x63, 0x80, 0x18, 0x24, 0x03, 0x16, 0x2c, 0x04, 0x13, \ - 0x5a, 0x49, 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x34, \ - 0x24, 0x05, 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x94, 0x26, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7d, 0x30, 0x7b, 0x02, \ - 0x01, 0x03, 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, \ - 0xf5, 0x04, 0xf3, 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, \ - 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x24, 0xe5, \ - 0xd1, 0xf4, 0x7a, 0x7d, 0x7b, 0x0d, 0x20, 0x6a, 0x26, 0xef, 0x69, 0x9b, 0x7c, 0x97, 0x57, 0xb7, 0x2d, 0x46, 0x90, \ - 0x89, 0xde, 0x31, 0x92, 0xe6, 0x78, 0xc7, 0x45, 0xe7, 0xf6, 0x0c, 0x02, 0x21, 0x00, 0xf8, 0xaa, 0x2f, 0xa7, 0x11, \ - 0xfc, 0xb7, 0x9b, 0x97, 0xe3, 0x97, 0xce, 0xda, 0x66, 0x7b, 0xae, 0x46, 0x4e, 0x2b, 0xd3, 0xff, 0xdf, 0xc3, 0xcc, \ - 0xed, 0x7a, 0xa8, 0xca, 0x5f, 0x4c, 0x1a, 0x7c \ - } -#endif - -/** - * CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC - * - * Enables synchronizing the device's real time clock with a remote CHIP Time service - * using the CHIP Time Sync protocol. - */ -// #define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 1 - -/** - * CHIP_CONFIG_EVENT_LOGGING_WDM_OFFLOAD - * - * Select the ability to offload event logs to any interested subscribers using WDM. - */ -#define CHIP_CONFIG_EVENT_LOGGING_WDM_OFFLOAD 1 - -/** - * CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS - * - * Enable recording UTC timestamps. - */ -#define CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1 - -/** - * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE - * - * A size, in bytes, of the individual debug event logging buffer. - */ -#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512) - -/** - * CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE - * - * For a development build, set the default importance of events to be logged as Debug. - * Since debug is the lowest importance level, this means all standard, critical, info and - * debug importance level vi events get logged. - */ -#if BUILD_RELEASE -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Production -#else -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug -#endif // BUILD_RELEASE - -/* Increasing the retransmission interval of the MRP messages after subsequent failures */ -#ifndef CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL -#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32) -#endif diff --git a/examples/laundry-washer-app/nxp/rt/rw61x/third_party/connectedhomeip b/examples/laundry-washer-app/nxp/rt/rw61x/third_party/connectedhomeip deleted file mode 120000 index 305f2077ffe..00000000000 --- a/examples/laundry-washer-app/nxp/rt/rw61x/third_party/connectedhomeip +++ /dev/null @@ -1 +0,0 @@ -../../../../../.. \ No newline at end of file diff --git a/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter b/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter index 41dc29c01c0..86e00b4b0ad 100644 --- a/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter +++ b/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/laundry-washer-app/nxp/zephyr/CMakeLists.txt b/examples/laundry-washer-app/nxp/zephyr/CMakeLists.txt index 0646e503d3d..10cb922e9b4 100644 --- a/examples/laundry-washer-app/nxp/zephyr/CMakeLists.txt +++ b/examples/laundry-washer-app/nxp/zephyr/CMakeLists.txt @@ -90,6 +90,13 @@ if(CONFIG_CHIP_OTA_REQUESTOR) ) endif() +if (CONFIG_CHIP_FACTORY_DATA) + target_sources(app PRIVATE + ${CHIP_ROOT}/src/platform/nxp/zephyr/FactoryDataProviderImpl.cpp + ${CHIP_ROOT}/src/platform/nxp/common/factory_data/legacy/FactoryDataProvider.cpp + ) +endif() + chip_configure_data_model(app ZAP_FILE ${ALL_CLUSTERS_COMMON_DIR}/../../laundry-washer-app/nxp/zap/laundry-washer-app.zap ) diff --git a/examples/light-switch-app/ameba/main/chipinterface.cpp b/examples/light-switch-app/ameba/main/chipinterface.cpp index 4ecb6c00608..f0497a6e274 100755 --- a/examples/light-switch-app/ameba/main/chipinterface.cpp +++ b/examples/light-switch-app/ameba/main/chipinterface.cpp @@ -109,9 +109,9 @@ static void InitServer(intptr_t context) static AmebaObserver sAmebaObserver; initParams.appDelegate = &sAmebaObserver; + chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); - chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); NetWorkCommissioningInstInit(); diff --git a/examples/light-switch-app/light-switch-common/icd-lit-light-switch-app.matter b/examples/light-switch-app/light-switch-common/icd-lit-light-switch-app.matter index e50480dbdca..b6371c7b2cb 100644 --- a/examples/light-switch-app/light-switch-common/icd-lit-light-switch-app.matter +++ b/examples/light-switch-app/light-switch-common/icd-lit-light-switch-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } 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 2e6aaea045c..98ccf79561b 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 @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/light-switch-app/qpg/zap/switch.matter b/examples/light-switch-app/qpg/zap/switch.matter index 1f788453ea5..32f2d3027ac 100644 --- a/examples/light-switch-app/qpg/zap/switch.matter +++ b/examples/light-switch-app/qpg/zap/switch.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/light-switch-app/realtek/data_model/light-switch-app-1_to_11.matter b/examples/light-switch-app/realtek/data_model/light-switch-app-1_to_11.matter index e6f3e735d02..bc40d676960 100644 --- a/examples/light-switch-app/realtek/data_model/light-switch-app-1_to_11.matter +++ b/examples/light-switch-app/realtek/data_model/light-switch-app-1_to_11.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/light-switch-app/realtek/data_model/light-switch-app-1_to_2.matter b/examples/light-switch-app/realtek/data_model/light-switch-app-1_to_2.matter index b649d8ff98e..f34f92c49a4 100644 --- a/examples/light-switch-app/realtek/data_model/light-switch-app-1_to_2.matter +++ b/examples/light-switch-app/realtek/data_model/light-switch-app-1_to_2.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/light-switch-app/realtek/data_model/light-switch-app-1_to_8.matter b/examples/light-switch-app/realtek/data_model/light-switch-app-1_to_8.matter index 694afd60e50..e2d009ce0b2 100644 --- a/examples/light-switch-app/realtek/data_model/light-switch-app-1_to_8.matter +++ b/examples/light-switch-app/realtek/data_model/light-switch-app-1_to_8.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/light-switch-app/realtek/data_model/light-switch-app.matter b/examples/light-switch-app/realtek/data_model/light-switch-app.matter index 40d6a14277a..b4b501b353b 100644 --- a/examples/light-switch-app/realtek/data_model/light-switch-app.matter +++ b/examples/light-switch-app/realtek/data_model/light-switch-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/lighting-app-data-mode-no-unique-id/lighting-common/lighting-app.matter b/examples/lighting-app-data-mode-no-unique-id/lighting-common/lighting-app.matter index 02f4bc1388c..a252f590d27 100644 --- a/examples/lighting-app-data-mode-no-unique-id/lighting-common/lighting-app.matter +++ b/examples/lighting-app-data-mode-no-unique-id/lighting-common/lighting-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/lighting-app/ameba/main/chipinterface.cpp b/examples/lighting-app/ameba/main/chipinterface.cpp index 6a5a5a649bb..bc585b1cc77 100755 --- a/examples/lighting-app/ameba/main/chipinterface.cpp +++ b/examples/lighting-app/ameba/main/chipinterface.cpp @@ -136,9 +136,9 @@ static void InitServer(intptr_t context) static AmebaObserver sAmebaObserver; initParams.appDelegate = &sAmebaObserver; + chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); - chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); #if CHIP_ENABLE_AMEBA_TERMS_AND_CONDITION const Optional termsAndConditions = Optional( diff --git a/examples/lighting-app/bouffalolab/data_model/lighting-app-ethernet.matter b/examples/lighting-app/bouffalolab/data_model/lighting-app-ethernet.matter index b36d9233b68..8f10ec7c679 100644 --- a/examples/lighting-app/bouffalolab/data_model/lighting-app-ethernet.matter +++ b/examples/lighting-app/bouffalolab/data_model/lighting-app-ethernet.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/lighting-app/bouffalolab/data_model/lighting-app-thread.matter b/examples/lighting-app/bouffalolab/data_model/lighting-app-thread.matter index b714182cb78..abfbaba2f20 100644 --- a/examples/lighting-app/bouffalolab/data_model/lighting-app-thread.matter +++ b/examples/lighting-app/bouffalolab/data_model/lighting-app-thread.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/lighting-app/bouffalolab/data_model/lighting-app-wifi.matter b/examples/lighting-app/bouffalolab/data_model/lighting-app-wifi.matter index d975eb2a54c..66d39ecf0bf 100644 --- a/examples/lighting-app/bouffalolab/data_model/lighting-app-wifi.matter +++ b/examples/lighting-app/bouffalolab/data_model/lighting-app-wifi.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/lighting-app/esp32/data_model/lighting-app.matter b/examples/lighting-app/esp32/data_model/lighting-app.matter index 460edb9de96..4de076290e2 100644 --- a/examples/lighting-app/esp32/data_model/lighting-app.matter +++ b/examples/lighting-app/esp32/data_model/lighting-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/lighting-app/lighting-common/lighting-app.matter b/examples/lighting-app/lighting-common/lighting-app.matter index 50de7a0262b..6412408b75e 100644 --- a/examples/lighting-app/lighting-common/lighting-app.matter +++ b/examples/lighting-app/lighting-common/lighting-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/lighting-app/nxp/README.md b/examples/lighting-app/nxp/README.md index 9d6fb2ca7cf..5211aa2f6d9 100644 --- a/examples/lighting-app/nxp/README.md +++ b/examples/lighting-app/nxp/README.md @@ -1,138 +1,99 @@ # Matter NXP Lighting Example Application -This reference application implements an On/Off Light device type. It uses board -buttons or `matter-cli` for user input and LEDs for state feedback. You can use -this example as a reference for creating your own application. - -The example is based on: - -- [Matter](https://github.com/project-chip/connectedhomeip) -- [NXP github SDK](https://github.com/nxp-mcuxpresso/mcux-sdk) +- [Overview](#overview) +- [Supported Platforms](#supported-platforms) +- [Environment Setup, Building, and Testing](#build) +- [Data Model](#data-model) +- [Manufacturing Data](#factory-data) -- [Matter NXP Lighting Example Application](#matter-nxp-lighting-example-application) - - [Supported devices](#supported-devices) - - [Introduction](#introduction) - - [Device UI](#device-ui) - - [Prerequisites for building](#prerequisites-for-building) - - [Building](#building) - - [Data model](#data-model) - - [Manufacturing data](#manufacturing-data) - - [Flashing and debugging](#flashing-and-debugging) + -## Supported devices +## Overview -- [mcxw71](mcxw71/README.md) -- [mcxw72](mcxw72/README.md) - -## Introduction +This reference application implements an On/Off Light device type. It uses board +buttons or `matter-cli` for user input and LEDs for state feedback. You can use +this example as a reference for creating your own application. -The application showcases a light bulb device that communicates with clients -over a low-power, 802.15.4 Thread network. +The example is based on +[Project CHIP](https://github.com/project-chip/connectedhomeip) and NXP SDK, and +provides a prototype application that demonstrates device commissioning and +different cluster control. -It can be commissioned into an existing Matter network using a controller such -as `chip-tool`. +The light bulb device communicates with clients over a low-power, 802.15.4 +Thread network. It can be commissioned into an existing Matter network using a +controller such as `chip-tool`. -This example implements a `User-Intent Commissioning Flow`, meaning the user has -to press a button in order for the device to be ready for commissioning. The -initial commissioning is done through `ble-thread` pairing method. +This example implements a `User-Intent Commissioning Flow`, meaning that the +user is required to press a button on the device in order to get it ready for +commissioning. The initial commissioning is usually performed using the +`ble-thread` pairing method. The Thread network dataset will be transferred on the device using a secure session over Bluetooth LE. In order to start the commissioning process, the user must enable BLE advertising on the device manually. To pair successfully, the commissioner must know the commissioning information corresponding to the -device: setup passcode and discriminator. This data is usually encoded within a -QR code or printed to the UART console. - -## Device UI +device: setup passcode and/or discriminator. This data is usually encoded within +a QR code or printed to the device's UART console. -The example application provides a simple UI that depicts the state of the -device and offers basic user control. This UI is implemented via the -general-purpose LEDs and buttons built in the evaluation boards. Please see each -supported device readme file for details. + -## Prerequisites for building +## Supported Platforms -In order to build the example, it is recommended to use a Linux distribution. -Please visit the supported Operating Systems list in -[BUILDING.md](../../../docs/guides/BUILDING.md#prerequisites). +The On/Off Light example is supported on the following platforms: -- Make sure that below prerequisites are correctly installed (as described in - [BUILDING.md](../../../docs/guides/BUILDING.md#prerequisites)) +| NXP platform | Dedicated readme | +| ------------ | ------------------------------------------------------------------- | +| MCXW71 | [NXP MCXW71 Guide](../../../docs/platforms/nxp/nxp_mcxw71_guide.md) | +| MCXW72 | [NXP MCXW72 Guide](../../../docs/platforms/nxp/nxp_mcxw72_guide.md) | -``` -sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev -``` +For details on platform-specific requirements and configurations, please refer +to the respective platform's readme. -- Step 1: checkout NXP specific submodules only +A list of popular standard lighting app targets is presented below. These +targets can be used with the `build_example.py` tool. - ``` - user@ubuntu:~/Desktop/git/connectedhomeip$ scripts/checkout_submodules.py --shallow --platform nxp --recursive - ``` +| Target name | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------------------- | +| `nxp--freertos-lighting-thread-frdm` | Default lighting app | +| `nxp--freertos-lighting-thread-factory-frdm` | Default lighting app with factory data | +| `nxp--freertos-lighting-thread-rotating-id-frdm` | Lighting app with rotating device id support | +| `nxp--freertos-lighting-thread-factory-dac-conversion-frdm` | Lighting app that leverages a secure enclave to secure the DAC private key | +| `nxp--freertos-lighting-thread-sw-v2-frdm` | Lighting app with software version 2 (can be used to test OTA) | +| `nxp--freertos-lighting-thread-factory-sw-v2-frdm` | Lighting app with factory data and software version 2 (can be used to test OTA) | -- Step 2: activate local environment +where `device` is be one of the [supported platforms](#supported-platforms). - ``` - user@ubuntu:~/Desktop/git/connectedhomeip$ source scripts/activate.sh - ``` + - If the script says the environment is out of date, you can update it by - running the following command: +## Environment Setup, Building, and Testing - ``` - user@ubuntu:~/Desktop/git/connectedhomeip$ source scripts/bootstrap.sh - ``` +All the information required to set up the environment, build the application, +and test it can be found in the common readme for NXP platforms: -- Step 3: Init NXP SDK(s) +- NXP FreeRTOS Platforms : Refer to the + [CHIP NXP Examples Guide for FreeRTOS platforms](../../../docs/platforms/nxp/nxp_examples_freertos_platforms.md) - ``` - user@ubuntu:~/Desktop/git/connectedhomeip$ third_party/nxp/nxp_matter_support/scripts/update_nxp_sdk.py --platform common - ``` + -Note: By default, `update_nxp_sdk.py` will try to initialize all NXP SDKs. -Please run the script with arg `--help` to view all available options. - -## Building - -There are two options for building this reference app: - -- Using `build_examples.py` framework. -- Manually generating `ninja` files using `gn`. - -For manual generation and building, please see the specific readme file for your -device. - -A list of all available contact sensor targets can be viewed in the following -table: - -| target name | description | -| --------------------------------------------------- | ------------------------------------------------------------------------------- | -| nxp-device-freertos-lighting | Default lighting app | -| nxp-device-freertos-lighting-factory | Default lighting app with factory data | -| nxp-device-freertos-lighting-rotating-id | Lighting app with rotating device id support | -| nxp-device-freertos-lighting-factory-dac-conversion | Lighting app that leverages a secure enclave to secure the DAC private key | -| nxp-device-freertos-lighting-sw-v2 | Lighting app with software version 2 (can be used to test OTA) | -| nxp-device-freertos-lighting-factory-sw-v2 | Lighting app with factory data and software version 2 (can be used to test OTA) | - -where `device` can be one of the [Supported devices](#supported-devices). - -### Data model +## Data Model The application uses an NXP specific data model file: -| path | description | +| Path | Description | | ------------------------- | --------------------------------------- | | `zap/lighting-on-off.zap` | Data model for On/Off Light device type | -The data model can be changed by simply replacing the gn `deps` statement -corresponding to data model target. + -### Manufacturing data +## Manufacturing Data -Use `nxp_use_factory_data=true` in the gn build command to enable factory data. +The support for manufacturing data is enabled at build time when you use the +appropriate build configuration files for this feature. Please refer to the +[NXP Matter examples guide for FreeRTOS](../../../docs/platforms/nxp/nxp_examples_freertos_platforms.md) +for details on the build process and available build configurations. +Manufacturing data can also be forced in the build command line by using the +`CONFIG_CHIP_FACTORY_DATA=y` build option or by using the appropriate +`build_examples.py` [targets](#supported-platforms). -For a full guide on manufacturing flow, please see +For a full guide on the manufacturing flow, please refer to the [Guide for writing manufacturing data on NXP devices](../../../docs/platforms/nxp/nxp_manufacturing_flow.md). - -## Flashing and debugging - -Please see the device specific readme file. diff --git a/examples/lighting-app/nxp/mcxw71/.gn b/examples/lighting-app/nxp/mcxw71/.gn deleted file mode 100644 index ece782b1bb7..00000000000 --- a/examples/lighting-app/nxp/mcxw71/.gn +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2020-2024 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") - -# The location of the build configuration file. -buildconfig = "${build_root}/config/BUILDCONFIG.gn" - -# CHIP uses angle bracket includes. -check_system_includes = true - -default_args = { - target_cpu = "arm" - target_os = "freertos" - - import("//args.gni") - - # Import default platform configs - import("${chip_root}/src/platform/nxp/mcxw71/args.gni") -} diff --git a/examples/lighting-app/nxp/mcxw71/BUILD.gn b/examples/lighting-app/nxp/mcxw71/BUILD.gn deleted file mode 100644 index f48ce46e1d1..00000000000 --- a/examples/lighting-app/nxp/mcxw71/BUILD.gn +++ /dev/null @@ -1,280 +0,0 @@ -# Copyright (c) 2024 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") -import("//build_overrides/nxp_sdk.gni") -import("//build_overrides/openthread.gni") - -import("${nxp_sdk_build_root}/nxp_sdk.gni") - -import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") - -import("${nxp_sdk_build_root}/${nxp_sdk_name}/${nxp_sdk_name}.gni") - -import("${chip_root}/src/crypto/crypto.gni") -import("${chip_root}/src/platform/device.gni") -import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") - -import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") - -if (chip_enable_pw_rpc) { - import("//build_overrides/pigweed.gni") - import("$dir_pw_build/target_types.gni") - import("${chip_root}/examples/platform/nxp/pw_rpc_server.gni") -} - -declare_args() { - # Setup discriminator as argument - setup_discriminator = 3840 -} - -assert(current_os == "freertos") -assert(target_os == "freertos") - -example_platform_dir = "${chip_root}/examples/platform/nxp/${nxp_platform}" -common_example_dir = "${chip_root}/examples/platform/nxp/common" -support_common_platform_dir = - "${nxp_sdk_matter_support_root}/examples/platform/common" - -mcxw71_sdk("sdk") { - defines = [] - include_dirs = [] - sources = [] - - # Indicate the path to CHIPProjectConfig.h - include_dirs += [ "include/config" ] - - # Indicate the default path to FreeRTOSConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/freeRTOS" ] - - # Indicate the default path to OpenThreadConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/openthread" ] - - # Indicate the default path to GATT database - include_dirs += [ "${support_common_platform_dir}/ble" ] - - include_dirs += [ - "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/app_common", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/components", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/dcdc", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/ext_flash", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/low_power", - ] - - sources += [ - "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples/clock_config.c", - "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples/pin_mux.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/app_common/app_services_init.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/app_common/hardware_init.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/board.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/components/board_comp.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/dcdc/board_dcdc.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/ext_flash/board_extflash.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/low_power/board_lp.c", - "${support_common_platform_dir}/ble/ble_function_mux.c", - ] - - if (is_debug) { - defines += [ "BUILD_RELEASE=0" ] - } else { - defines += [ "BUILD_RELEASE=1" ] - } - - if (chip_enable_pw_rpc) { - defines += [ - "CONFIG_ENABLE_PW_RPC", - "STREAMER_UART_FLUSH_DELAY_MS=0", - "STREAMER_UART_SERIAL_MANAGER_RING_BUFFER_SIZE=512", - "BOARD_APP_UART_CLK_FREQ=96000000", - ] - } - - defines += [ - "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", - ] -} - -mcxw71_executable("light_app") { - output_name = "chip-mcxw71-light-example" - - defines = [] - deps = [] - sources = [] - - if (chip_enable_pw_rpc) { - forward_variables_from(pw_rpc_server, "*") - } else { - include_dirs = [] - cflags = [ "-Wconversion" ] - } - - # Defines used by common code - defines += [ - "CONFIG_NET_L2_OPENTHREAD=1", - "CONFIG_NETWORK_LAYER_BLE=1", - "CONFIG_OPERATIONAL_KEYSTORE=1", - "CONFIG_ENABLE_FEEDBACK=1", - "APP_QUEUE_TICKS_TO_WAIT=pdMS_TO_TICKS(10)", - "EXTERNAL_FACTORY_DATA_PROVIDER_HEADER=\"platform/nxp/common/factory_data/legacy/FactoryDataProvider.h\"", - "CONFIG_APP_FREERTOS_OS=1", - ] - - # App common files - include_dirs += [ - "${common_example_dir}/app_task/include", - "${common_example_dir}/matter_button/include", - "${common_example_dir}/clusters/include", - "${common_example_dir}/device_callbacks/include", - "${common_example_dir}/device_manager/include", - "${common_example_dir}/factory_data/include", - "${common_example_dir}/led_widget/include", - "${common_example_dir}/operational_keystore/include", - "${common_example_dir}/rpc/include", - "${common_example_dir}/ui_feedback/include", - "${common_example_dir}/app_ble/include", - ] - - sources += [ - "${common_example_dir}/app_ble/source/BLEApplicationManagerEmpty.cpp", - "${common_example_dir}/app_task/source/AppTaskBase.cpp", - "${common_example_dir}/app_task/source/AppTaskFreeRTOS.cpp", - "${common_example_dir}/clusters/source/ZclCallbacks.cpp", - "${common_example_dir}/device_callbacks/source/CommonDeviceCallbacks.cpp", - "${common_example_dir}/device_manager/source/CHIPDeviceManager.cpp", - "${common_example_dir}/matter_button/source/ButtonApp.cpp", - "${common_example_dir}/matter_button/source/ButtonBle.cpp", - "${common_example_dir}/matter_button/source/ButtonManager.cpp", - "${common_example_dir}/matter_button/source/ButtonRegistrationAppAndBle.cpp", - "${common_example_dir}/matter_button/source/ButtonWithTimer.cpp", - "${common_example_dir}/operational_keystore/source/OperationalKeystoreS200.cpp", - "${example_platform_dir}/factory_data/source/AppFactoryDataExample.cpp", - ] - - if (chip_enable_ota_requestor) { - defines += [ - "CONFIG_CHIP_OTA_IMAGE_PROCESSOR_HEADER=\"platform/nxp/common/ota/OTAImageProcessorImpl.h\"", - - # The status LED and the external flash CS pin are wired together. The OTA image writing may fail if used together. - "LED_MANAGER_ENABLE_STATUS_LED=0", - ] - - include_dirs += [ - "${common_example_dir}/ota_requestor/include", - "${chip_root}/src/platform/nxp/common/ota", - ] - sources += [ "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorMultiImage.cpp" ] - deps += [ "${chip_root}/src/platform/nxp:nxp_ota" ] - } - - # Platform specific files - include_dirs += [ - "${example_platform_dir}/util", - "${example_platform_dir}/app/support", - "${example_platform_dir}/button", - ] - - sources += [ "${example_platform_dir}/clusters/Identify.cpp" ] - - if (chip_enable_ota_requestor) { - sources += [ "${example_platform_dir}/ota/OtaUtils.cpp" ] - } - - if (chip_enable_pw_rpc) { - sources += [ "${example_platform_dir}/rpc/AppRpc.cpp" ] - } - - if (nxp_use_factory_data) { - # Custom factory data files can be added here - } - - sources += [ - "../common/AppTask.cpp", - "../common/DeviceCallbacks.cpp", - "../common/main.cpp", - ] - - include_dirs += [ - "../common", - "../common/include", - "include/config", - ] - - deps += [ - "${chip_root}/examples/providers:device_info_provider_please_do_not_reuse_as_is", - "${chip_root}/src/app/clusters/network-commissioning:network-commissioning", - "${chip_root}/src/platform/logging:default", - "${chip_root}/src/setup_payload:onboarding-codes-utils", - ] - - if (nxp_config_dimmable_led) { - defines += [ "LIGHTING_MANAGER_ENABLE_DIMMABLE_LED=1" ] - sources += [ - "${common_example_dir}/led_widget/include/LedDimmer.h", - "${example_platform_dir}/util/LedDimmer.cpp", - "${example_platform_dir}/util/LightingManagerDimmable.cpp", - ] - deps += [ "${chip_root}/examples/lighting-app/lighting-common/" ] - } else { - sources += [ - "${common_example_dir}/ui_feedback/source/LedManager.cpp", - "${example_platform_dir}/util/LedOnOff.cpp", - ] - deps += [ "${chip_root}/examples/lighting-app/nxp/zap/" ] - } - - if (chip_openthread_ftd) { - deps += [ - "${openthread_root}:libopenthread-cli-ftd", - "${openthread_root}:libopenthread-ftd", - ] - } else { - deps += [ - "${openthread_root}:libopenthread-cli-mtd", - "${openthread_root}:libopenthread-mtd", - ] - } - - if (nxp_use_smu2_static) { - ldscript = "${example_platform_dir}/app/ldscripts/app.ld" - base_ldscript_dir = "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples/linker/gcc/" - } else { - ldscript = "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples/linker/gcc/connectivity.ld" - } - - inputs = [ ldscript ] - - ldflags = [ - "-Wl,--defsym=__heap_size__=0", - "-Wl,--defsym=__stack_size__=0x480", - "-Wl,-print-memory-usage", - "-Wl,--no-warn-rwx-segments", - "-T" + rebase_path(ldscript, root_build_dir), - ] - - if (nxp_use_factory_data) { - ldflags += [ "-Wl,--defsym=gUseFactoryData_d=1" ] - } - - if (nxp_use_smu2_static) { - ldflags += [ "-L" + rebase_path(base_ldscript_dir, root_build_dir) ] - } - - output_dir = root_out_dir -} - -group("default") { - deps = [ ":light_app" ] -} diff --git a/examples/lighting-app/nxp/mcxw71/README.md b/examples/lighting-app/nxp/mcxw71/README.md deleted file mode 100644 index 9dc7ad3cbc4..00000000000 --- a/examples/lighting-app/nxp/mcxw71/README.md +++ /dev/null @@ -1,270 +0,0 @@ -# Matter `MCXW71` Lighting Example Application - -For generic information related to on/off light application, please see the -[common README](../README.md). - -- [Matter `MCXW71` Lighting Example Application](#matter-mcxw71-lighting-example-application) - - [Introduction](#introduction) - - [Device UI](#device-ui) - - [Building](#building) - - [`SMU2` Memory](#smu2-memory) - - [LED PWM](#led-pwm) - - [Flashing](#flashing) - - [Flashing the `NBU` image](#flashing-the-nbu-image) - - [Flashing the host image](#flashing-the-host-image) - - [Debugging](#debugging) - - [Running RPC console](#running-rpc-console) - - [OTA](#ota) - -## Introduction - -This is an on/off lighting application implemented for an `mcxw71` device. - -The following board was used when testing this Matter reference app for a -`mcxw71` device: -![FRDM-MCXW71](../../../platform/nxp/mcxw71/doc/images/frdm-mcxw71.jpg) - -## Device UI - -The state feedback is provided through LED effects: - -| widget | effect | description | -| ------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------- | -| LED2 | short flash on (50ms on/950ms off) | The device is in an unprovisioned (unpaired) state and is waiting for a commissioner to connect. | -| LED2 | rapid even flashing (100ms period) | The device is in an unprovisioned state and a commissioner is connected via BLE. | -| LED2 | short flash off (950ms on/50ms off) | The device is fully provisioned, but does not yet have full network (Thread) or service connectivity. | -| LED2 | solid on | The device is fully provisioned and has full network and service connectivity. | -| RGB LED | on | The `OnOff` attribute of the `On/Off` cluster is `true` (simulating device turned on). | -| RGB LED | off | The `OnOff` attribute of the `On/Off` cluster is `false` (simulating device turned off). | - -NOTE: `LED2` will be disabled when OTA is used. On `FRDM-MCXW71` board, `PTB0` -is wired to both `LED2` and CS (Chip Select) of the External Flash Memory. Since -the OTA image is stored in external memory, `LED2` operations will affect OTA -operation by corrupting packages and OTA will not work. - -The user actions are summarized below: - -| button | action | output | -| ------ | ----------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| SW2 | short press | Enable BLE advertising | -| SW2 | long press | Initiate a factory reset (can be cancelled by pressing the button again within the factory reset timeout limit - 6 seconds by default) | -| SW3 | short press | Toggle attribute `OnOff` value | -| SW3 | long press | Clean soft reset of the device (takes into account proper Matter shutdown procedure) | - -The example application provides a simple UI that depicts the state of the -device and offers basic user control. This UI is implemented via the -general-purpose LEDs and buttons built in the `MCXW71` board. - -## Building - -Manually building requires running the following commands: - -``` -user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/lighting-app/nxp/mcxw71 -user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/mcxw71$ gn gen out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/mcxw71$ ninja -C out/debug -``` - -Please note that running `gn gen out/debug` without `--args` option will use the -default gn args values found in `args.gni`. - -After a successful build, the `elf` and `srec` files are found in `out/debug/`. -See the files prefixed with `chip-mcxw71-light-example`. - -### `SMU2` Memory - -Additional memory is provided to the application by moving some Matter instances -and global variables in the shared memory area from `NBU` domain. - -Note: These instances and global variables are placed in `SMU2` memory through -name matching in the application linker script. They should not be changed or, -if changed, the names must be updated in `app.ld`. See -[app.ld](../../../platform/nxp/mcxw71/app/ldscripts/app.ld) for names and `SMU2` -memory range size. - -When compiling the application as an OT Full Thread Device -(`chip_openthread_ftd=true`), using `nxp_use_smu2_static=true` gn arg will cause -the following symbols to be moved to `SMU2` area: - -| symbol name | file | -| ----------------------------------- | ---------------------------- | -| `gImageProcessor` | `OTAImageProcessorImpl.cpp` | -| `gApplicationProcessor` | `OTAHooks.cpp` | -| `Server::sServer` | `Server.cpp` | -| `ThreadStackManagerImpl::sInstance` | `ThreadStackManagerImpl.cpp` | - -Additionally, using `nxp_use_smu2_dynamic=true` will cause the OpenThread -buffers to be dynamically allocated from a 13KB `SMU2` range after a successful -commissioning process. - -`nxp_use_smu2_static` and `nxp_use_smu2_dynamic` are set to `true` in the -default example. - -### LED PWM - -In the default configuration, the onboard RGB LED pins are configured as GPIO -pins. In order to enable the dimming feature, the pins need to be configured in -PWM mode and synced with channels of the `TPM` (Timer PWM Module). To enable -this feature, compile the application with: `nxp_config_dimmable_led=true` - -If the feature is enabled, the LED brightness can be controlled using -`LevelControl` cluster -[commands](../../../../docs/development_controllers/chip-tool/chip_tool_guide.md#step-7-control-application-data-model-clusters). - -## Flashing - -Two images must be written to the board: one for the host (CM33) and one for the -`NBU` (CM3). - -The image needed on the host side is the one generated in `out/debug/` while the -one needed on the `NBU` side can be found in the downloaded NXP-SDK package at -path - -`middleware\wireless\ieee-802.15.4\bin\k32w1_mcxw71\k32w1_mcxw71_nbu_ble_15_4_dyn_matter.sb3`. - -### Flashing the `NBU` image - -`NBU` image should be written only when a new NXP SDK is released. - -1. Install - [Secure Provisioning SDK tool](https://www.nxp.com/design/design-center/software/development-software/secure-provisioning-sdk-spsdk:SPSDK) - using Python: - - ``` - pip install spsdk - ``` - - Note: There might be some dependencies that cause conflicts with already - installed Python modules. However, `blhost` tool is still installed and can - be used. - -2. Updating `NBU` for Wireless examples - - It is necessary to work with the matching `NBU` image for the SDK version of - the application you are working with. This means that when you download your - SDK, prior to loading any wireless SDK example, update your `NBU` image with - the SDK provided binaries. For `FRDM` users, please write the following - binary: - - `middleware\wireless\ieee-802.15.4\bin\mcxw71\mcxw71_nbu_ble_15_4_dyn_matter_.sb3` - - Please note that `` may vary depending on the SDK version. - - 1. Place your device in `ISP` mode. - - - Make sure a jumper is placed on `JP25` - - Press and hold `SW4`, press and release Reset, then release `SW4` - - 2. Once the device is connected, you may find the assigned port by running: - - ``` - nxpdevscan - ``` - - 3. Run the `blhost` command to write the `sb3` file: - - ``` - blhost -p receive-sb-file \middleware\wireless\ieee-802.15.4\bin\mcxw71\mcxw71_nbu_ble_15_4_dyn_matter_.sb3 - ``` - -### Flashing the host image - -Host image is the one found under `out/debug/`. It should be written after each -build process. - -If debugging is needed then jump directly to the [Debugging](#debugging) -section. Otherwise, if only flashing is needed then -[JLink](https://www.segger.com/downloads/jlink/) can be used: - -- Plug `MCXW71` to the USB port (no need to keep the `SW4` button pressed - while doing this, e.g. ISP mode is not needed for host flashing) - -- Connect JLink to the device: - - ```bash - JLinkExe -device MCXW71 -if SWD -speed 4000 -autoconnect 1 - ``` - -- Run the following commands: - ```bash - reset - halt - loadfile chip-mcxw71-light-example.srec - reset - go - quit - ``` - -## Debugging - -One option for debugging would be to use MCUXpresso IDE. - -- Drag-and-drop the zip file containing the NXP SDK in the "Installed SDKs" - tab: - -![Installed SDKs](../../../platform/nxp/mcxw71/doc/images/mcxw71_installed_sdks.jpg) - -- Import any demo application from the installed SDK: - -``` -Import SDK example(s).. -> choose a demo app (demo_apps -> hello_world) -> Finish -``` - -![Import demo](../../../platform/nxp/mcxw71/doc/images/import_demo.jpg) - -- Flash the previously imported demo application on the board: - -``` -Right click on the application (from Project Explorer) -> Debug as -> JLink/CMSIS-DAP -``` - -After this step, a debug configuration specific for the `MCXW71` board was -created. This debug configuration will be used later on for debugging the -application resulted after ot-nxp compilation. - -- Import Matter repo in MCUXpresso IDE as Makefile Project. Use _none_ as - _Toolchain for Indexer Settings_: - -``` -File -> Import -> C/C++ -> Existing Code as Makefile Project -``` - -![New Project](../../../platform/nxp/mcxw71/doc/images/new_project.jpg) - -- Replace the path of the existing demo application with the path of the - `MCXW71` application: - -``` -Run -> Debug Configurations... -> C/C++ Application -``` - -![Debug MCXW71](../../../platform/nxp/mcxw71/doc/images/mcxw71_debug.jpg) - -## Running RPC console - -To build example with RPC enabled, use the following gn command: -`gn gen out/debug --args='import("//with_pw_rpc.gni") treat_warnings_as_errors=false'` - -The application runs an RPC server and processes events coming from an RPC -client. An example of an RPC client is the `chip-console`, which can be accessed -by running: -`chip-console --device /dev/tty. -b 115200 -o pw_log.out` - -The console should have already been installed in the virtual environment. From -the `chip-console`, a user can send specific commands to the device. - -For button commands, please run `rpcs.chip.rpc.Button.Event(index)` based on the -table below: - -| index | action | -| ----- | --------------------------------------------- | -| 0 | Start/stop BLE advertising | -| 1 | Factory reset the device | -| 2 | Application specific action (e.g. toggle LED) | -| 3 | Soft reset the device | - -To reboot the device, please run `rpcs.chip.rpc.Device.Reboot()`. - -## OTA - -Please see -[mcxw71 OTA guide](../../../../docs/platforms/nxp/nxp_mcxw71_ota_guide.md). diff --git a/examples/lighting-app/nxp/mcxw71/args.gni b/examples/lighting-app/nxp/mcxw71/args.gni deleted file mode 100644 index 1807c7e3135..00000000000 --- a/examples/lighting-app/nxp/mcxw71/args.gni +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2020-2024 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") -import("${chip_root}/config/standalone/args.gni") - -# SDK target. This is overridden to add our SDK app_config.h & defines. -nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") -nxp_device = "MCXW716C" -nxp_board = "frdmmcxw71" - -nxp_config_dimmable_led = false -chip_enable_ota_requestor = true -chip_stack_lock_tracking = "fatal" -chip_enable_ble = true -chip_generate_link_map_file = true - -is_debug = false - -chip_crypto = "platform" -chip_openthread_ftd = true -nxp_enable_ot_cli = false - -chip_system_config_provide_statistics = false -chip_system_config_use_openthread_inet_endpoints = true -chip_with_lwip = false -#nxp_use_smu2_static = true -#nxp_use_smu2_dynamic = true diff --git a/examples/lighting-app/nxp/mcxw71/build_overrides b/examples/lighting-app/nxp/mcxw71/build_overrides deleted file mode 120000 index ee19c065d61..00000000000 --- a/examples/lighting-app/nxp/mcxw71/build_overrides +++ /dev/null @@ -1 +0,0 @@ -../../../build_overrides/ \ No newline at end of file diff --git a/examples/lighting-app/nxp/mcxw71/include/config/AppConfig.h b/examples/lighting-app/nxp/mcxw71/include/config/AppConfig.h deleted file mode 100644 index 89f4bf9333c..00000000000 --- a/examples/lighting-app/nxp/mcxw71/include/config/AppConfig.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 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 - -/* ---- App Config ---- */ - -/* ---- Button Manager Config ---- */ -#define BUTTON_MANAGER_FACTORY_RESET_TIMEOUT_MS 6000 - -/* ---- LED Manager Config ---- */ -#define LED_MANAGER_STATUS_LED_INDEX 0 -#define LED_MANAGER_LIGHT_LED_INDEX 1 diff --git a/examples/lighting-app/nxp/mcxw71/include/config/CHIPProjectConfig.h b/examples/lighting-app/nxp/mcxw71/include/config/CHIPProjectConfig.h deleted file mode 100644 index 8cf72c9006c..00000000000 --- a/examples/lighting-app/nxp/mcxw71/include/config/CHIPProjectConfig.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2020 Google LLC. - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Example project configuration file for CHIP. - * - * This is a place to put application or project-specific overrides - * to the default configuration values for general CHIP features. - * - */ - -#pragma once - -// Security and Authentication disabled for development build. -// For convenience, enable CHIP Security Test Mode and disable the requirement for -// authentication in various protocols. -// WARNING: These options make it possible to circumvent basic CHIP security functionality, -// including message encryption. Because of this they MUST NEVER BE ENABLED IN PRODUCTION BUILDS. -#define CHIP_CONFIG_SECURITY_TEST_MODE 0 - -// Use hard-coded test certificates already embedded in generic chip code => set it to 0 -// Use real/development certificates => set it to 1 + file the provisioning section from -// the internal flash -#ifndef CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -#define CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA 0 -#endif - -#if CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA - -// VID/PID for product => will be used by Basic Information Cluster -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0x1037 -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0xA401 - -// Set the following define to use the Certification Declaration from below and not use it stored in factory data section -#ifndef CHIP_USE_DEVICE_CONFIG_CERTIFICATION_DECLARATION -#define CHIP_USE_DEVICE_CONFIG_CERTIFICATION_DECLARATION 0 -#endif - -#ifndef CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION -//-> format_version = 1 -//-> vendor_id = 0x1037 -//-> product_id_array = [ 0xA401 ] -//-> device_type_id = 0x0100 -//-> certificate_id = "ZIG20142ZB330003-24" -//-> security_level = 0 -//-> security_information = 0 -//-> version_number = 0x2694 -//-> certification_type = 1 -//-> dac_origin_vendor_id is not present -//-> dac_origin_product_id is not present -#define CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION \ - { \ - 0x30, 0x81, 0xe8, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x81, 0xda, 0x30, 0x81, 0xd7, \ - 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, \ - 0x45, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x38, 0x04, 0x36, 0x15, 0x24, 0x00, \ - 0x01, 0x25, 0x01, 0x37, 0x10, 0x36, 0x02, 0x05, 0x01, 0xa4, 0x18, 0x25, 0x03, 0x00, 0x01, 0x2c, 0x04, 0x13, 0x5a, \ - 0x49, 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x34, 0x24, \ - 0x05, 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x76, 0x98, 0x24, 0x08, 0x01, 0x18, 0x31, 0x7c, 0x30, 0x7a, 0x02, 0x01, \ - 0x03, 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, \ - 0x04, 0xf3, 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0a, \ - 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x46, 0x30, 0x44, 0x02, 0x20, 0x11, 0xc4, 0xe4, \ - 0x54, 0xcc, 0xdb, 0x09, 0xa9, 0x31, 0xd7, 0xbd, 0x6e, 0x28, 0x95, 0x9b, 0xab, 0x3e, 0xec, 0x76, 0x09, 0x8c, 0x39, \ - 0x93, 0x43, 0x6e, 0x89, 0x07, 0x7d, 0x8b, 0xe9, 0x3a, 0x0a, 0x02, 0x20, 0x71, 0xc6, 0xac, 0x09, 0x11, 0x7b, 0x1a, \ - 0x61, 0x5e, 0x3a, 0xc6, 0x4a, 0x4f, 0xf3, 0xd4, 0x3b, 0x62, 0x54, 0x3a, 0xf3, 0x60, 0xeb, 0x47, 0xd4, 0x8f, 0x18, \ - 0x0d, 0xa3, 0xd1, 0xef, 0xd0, 0x70 \ - } - -// All remaining data will be pulled from the provisioning region of flash. -#endif - -#else - -/** - * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID - * - * 0xFFF1: Test vendor. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1 - -/** - * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID - * - * 0x8005: example lighting-app - */ -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8005 - -// Use a default setup PIN code if one hasn't been provisioned in flash. -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 -#endif - -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 -#endif - -// Use a default pairing code if one hasn't been provisioned in flash. -#define CHIP_DEVICE_CONFIG_USE_TEST_PAIRING_CODE "CHIPUS" - -/** - * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER - * - * Enables the use of a hard-coded default serial number if none - * is found in CHIP NV storage. - */ -#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN" - -#endif // CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA - -/** - * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION - * - * The hardware version number assigned to device or product by the device vendor. This - * number is scoped to the device product id, and typically corresponds to a revision of the - * physical device, a change to its packaging, and/or a change to its marketing presentation. - * This value is generally *not* incremented for device software versions. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 100 - -#ifndef CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING "v0.1.0" -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING - * - * A string identifying the software version running on the device. - * CHIP currently expects the software version to be in the format - * {MAJOR_VERSION}.0d{MINOR_VERSION} - */ -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION NXP_CONFIG_DEVICE_SOFTWARE_VERSION -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "NXP Semiconductors" -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "NXP Demo App" -#endif - -/** - * CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC - * - * Enables synchronizing the device's real time clock with a remote CHIP Time service - * using the CHIP Time Sync protocol. - */ -// #define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 1 - -/** - * CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_TIMEOUT - * - * The amount of time in miliseconds after which BLE should change his advertisements - * from fast interval to slow interval. - * - * 30000 (30 secondes). - */ -#define CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_TIMEOUT (30 * 1000) - -/** - * CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT - * - * The amount of time in miliseconds after which BLE advertisement should be disabled, counting - * from the moment of slow advertisement commencement. - * - * Defaults to 9000000 (15 minutes). - */ -#define CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT (15 * 60 * 1000) - -/** - * CONFIG_CHIP_NFC_ONBOARDING_PAYLOAD, CHIP_DEVICE_CONFIG_ENABLE_NFC_ONBOARDING_PAYLOAD - * - * NFC onboarding payload is not supported - */ -#define CONFIG_CHIP_NFC_ONBOARDING_PAYLOAD 0 -#define CHIP_DEVICE_CONFIG_ENABLE_NFC_ONBOARDING_PAYLOAD 0 - -/** - * @def CHIP_CONFIG_MAX_FABRICS - * - * @brief - * Maximum number of fabrics the device can participate in. Each fabric can - * provision the device with its unique operational credentials and manage - * its own access control lists. - */ -#define CHIP_CONFIG_MAX_FABRICS 5 // 5 is the minimum number of supported fabrics - -/** - * @def CHIP_IM_MAX_NUM_COMMAND_HANDLER - * - * @brief Defines the maximum number of CommandHandler, limits the number of active commands transactions on server. - */ -#define CHIP_IM_MAX_NUM_COMMAND_HANDLER 2 - -/** - * @def CHIP_IM_MAX_NUM_WRITE_HANDLER - * - * @brief Defines the maximum number of WriteHandler, limits the number of active write transactions on server. - */ -#define CHIP_IM_MAX_NUM_WRITE_HANDLER 2 - -/** - * CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE - * - * For a development build, set the default importance of events to be logged as Debug. - * Since debug is the lowest importance level, this means all standard, critical, info and - * debug importance level vi events get logged. - */ -#if BUILD_RELEASE -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Production -#else -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug -#endif // BUILD_RELEASE - -#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1 diff --git a/examples/lighting-app/nxp/mcxw71/third_party/connectedhomeip b/examples/lighting-app/nxp/mcxw71/third_party/connectedhomeip deleted file mode 120000 index 59307833b4f..00000000000 --- a/examples/lighting-app/nxp/mcxw71/third_party/connectedhomeip +++ /dev/null @@ -1 +0,0 @@ -../../../../.. \ No newline at end of file diff --git a/examples/lighting-app/nxp/mcxw71/with_pw_rpc.gni b/examples/lighting-app/nxp/mcxw71/with_pw_rpc.gni deleted file mode 100644 index 99447aa5d5f..00000000000 --- a/examples/lighting-app/nxp/mcxw71/with_pw_rpc.gni +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (c) 2023 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# add this gni as import in your build args to use pigweed in the example -# 'import("//with_pw_rpc.gni")' - -import("//build_overrides/chip.gni") -import("${chip_root}/config/nxp/lib/pw_rpc/pw_rpc.gni") - -nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") - -chip_crypto = "platform" -chip_enable_ble = true -chip_enable_ota_requestor = true -chip_enable_pw_rpc = true -chip_openthread_ftd = true -chip_stack_lock_tracking = "fatal" - -chip_system_config_provide_statistics = false -chip_system_config_use_openthread_inet_endpoints = true - -chip_with_lwip = false -nxp_enable_ot_cli = false - -cpp_standard = "gnu++17" -is_debug = false diff --git a/examples/lighting-app/nxp/mcxw72/.gn b/examples/lighting-app/nxp/mcxw72/.gn deleted file mode 100644 index 365c97cf355..00000000000 --- a/examples/lighting-app/nxp/mcxw72/.gn +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2020-2024 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") - -# The location of the build configuration file. -buildconfig = "${build_root}/config/BUILDCONFIG.gn" - -# CHIP uses angle bracket includes. -check_system_includes = true - -default_args = { - target_cpu = "arm" - target_os = "freertos" - - import("//args.gni") - - # Import default platform configs - import("${chip_root}/src/platform/nxp/mcxw72/args.gni") -} diff --git a/examples/lighting-app/nxp/mcxw72/BUILD.gn b/examples/lighting-app/nxp/mcxw72/BUILD.gn deleted file mode 100644 index 95fd7e1f4e2..00000000000 --- a/examples/lighting-app/nxp/mcxw72/BUILD.gn +++ /dev/null @@ -1,242 +0,0 @@ -# Copyright (c) 2024 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") -import("//build_overrides/nxp_sdk.gni") -import("//build_overrides/openthread.gni") - -import("${nxp_sdk_build_root}/nxp_sdk.gni") - -import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") - -import("${nxp_sdk_build_root}/${nxp_sdk_name}/${nxp_sdk_name}.gni") - -import("${chip_root}/src/crypto/crypto.gni") -import("${chip_root}/src/platform/device.gni") -import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") - -import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") - -declare_args() { - # Setup discriminator as argument - setup_discriminator = 3840 -} - -assert(current_os == "freertos") -assert(target_os == "freertos") - -example_platform_dir = - "${nxp_sdk_matter_support_root}/examples/platform/${nxp_platform}" -common_example_dir = "${chip_root}/examples/platform/nxp/common" -support_common_platform_dir = - "${nxp_sdk_matter_support_root}/examples/platform/common" - -mcxw72_sdk("sdk") { - defines = [] - include_dirs = [] - sources = [] - - # Indicate the path to CHIPProjectConfig.h - include_dirs += [ "include/config" ] - - # Indicate the default path to FreeRTOSConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/freeRTOS" ] - - # Indicate the default path to OpenThreadConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/openthread" ] - - # Indicate the default path to GATT database - include_dirs += [ "${support_common_platform_dir}/ble" ] - - include_dirs += [ - "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/app_common", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/components", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/dcdc", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/ext_flash", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/low_power", - ] - - sources += [ - "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples/clock_config.c", - "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples/pin_mux.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/app_common/app_services_init.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/app_common/hardware_init.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/board.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/components/board_comp.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/dcdc/board_dcdc.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/ext_flash/board_extflash.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/low_power/board_lp.c", - "${support_common_platform_dir}/ble/ble_function_mux.c", - ] - - if (is_debug) { - defines += [ "BUILD_RELEASE=0" ] - } else { - defines += [ "BUILD_RELEASE=1" ] - } - - defines += [ - "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", - ] - - if (nxp_enable_matter_cli) { - defines += [ "gAppUseSerialManager_c=1" ] - } -} - -mcxw72_executable("light_app") { - output_name = "chip-mcxw72-light-example" - - defines = [] - deps = [] - sources = [] - include_dirs = [] - cflags = [ "-Wconversion" ] - - # Defines used by common code - defines += [ - "CONFIG_NET_L2_OPENTHREAD=1", - "CONFIG_NETWORK_LAYER_BLE=1", - "CONFIG_ENABLE_FEEDBACK=1", - "LED_MANAGER_ENABLE_STATUS_LED=1", - "APP_QUEUE_TICKS_TO_WAIT=pdMS_TO_TICKS(10)", - "EXTERNAL_FACTORY_DATA_PROVIDER_HEADER=\"platform/nxp/common/factory_data/legacy/FactoryDataProvider.h\"", - "CONFIG_APP_FREERTOS_OS=1", - ] - - # App common files - include_dirs += [ - "${common_example_dir}/app_task/include", - "${common_example_dir}/app_ble/include", - "${common_example_dir}/matter_button/include", - "${common_example_dir}/clusters/include", - "${common_example_dir}/device_callbacks/include", - "${common_example_dir}/device_manager/include", - "${common_example_dir}/factory_data/include", - "${common_example_dir}/led_widget/include", - "${common_example_dir}/matter_cli/include", - "${common_example_dir}/operational_keystore/include", - "${common_example_dir}/rpc/include", - "${common_example_dir}/ui_feedback/include", - ] - - sources += [ - "${common_example_dir}/app_ble/source/BLEApplicationManagerEmpty.cpp", - "${common_example_dir}/app_task/source/AppTaskBase.cpp", - "${common_example_dir}/app_task/source/AppTaskFreeRTOS.cpp", - "${common_example_dir}/clusters/source/ZclCallbacks.cpp", - "${common_example_dir}/device_callbacks/source/CommonDeviceCallbacks.cpp", - "${common_example_dir}/device_manager/source/CHIPDeviceManager.cpp", - "${common_example_dir}/factory_data/source/AppFactoryDataDefaultImpl.cpp", - "${common_example_dir}/matter_button/source/ButtonApp.cpp", - "${common_example_dir}/matter_button/source/ButtonBle.cpp", - "${common_example_dir}/matter_button/source/ButtonManager.cpp", - "${common_example_dir}/matter_button/source/ButtonRegistrationAppAndBle.cpp", - "${common_example_dir}/matter_button/source/ButtonWithTimer.cpp", - ] - - if (chip_enable_ota_requestor) { - defines += [ "CONFIG_CHIP_OTA_IMAGE_PROCESSOR_HEADER=\"platform/nxp/common/ota/OTAImageProcessorImpl.h\"" ] - include_dirs += [ "${common_example_dir}/ota_requestor/include" ] - sources += [ - "${common_example_dir}/../mcxw71/ota/OtaUtils.cpp", - "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorMultiImage.cpp", - ] - deps += [ "${chip_root}/src/platform/nxp:nxp_ota" ] - } - - # Platform specific files - if (chip_crypto == "platform") { - defines += [ "CONFIG_OPERATIONAL_KEYSTORE=1" ] - sources += [ "${common_example_dir}/operational_keystore/source/OperationalKeystoreS200.cpp" ] - } - - if (nxp_use_factory_data) { - # Custom factory data files can be added here - } - - sources += [ - "../common/AppTask.cpp", - "../common/DeviceCallbacks.cpp", - "../common/main.cpp", - ] - - sources += [ - "${common_example_dir}/../mcxw71/clusters/Identify.cpp", - "${common_example_dir}/../mcxw71/util/LedOnOff.cpp", - "${common_example_dir}/ui_feedback/source/LedManager.cpp", - ] - - include_dirs += [ - "../common", - "../common/include", - "include/config", - "${common_example_dir}/../mcxw71/util", - "${common_example_dir}/../mcxw71/app/support", - "${common_example_dir}/../mcxw71/button", - ] - - deps += [ - "${chip_root}/examples/lighting-app/nxp/zap", - "${chip_root}/examples/providers:device_info_provider_please_do_not_reuse_as_is", - "${chip_root}/src/platform/logging:default", - "${chip_root}/src/setup_payload:onboarding-codes-utils", - ] - - if (chip_openthread_ftd) { - deps += [ - "${openthread_root}:libopenthread-cli-ftd", - "${openthread_root}:libopenthread-ftd", - ] - } else { - deps += [ - "${openthread_root}:libopenthread-cli-mtd", - "${openthread_root}:libopenthread-mtd", - ] - } - - if (nxp_enable_matter_cli) { - defines += [ "ENABLE_CHIP_SHELL" ] - - deps += [ - "${chip_root}/examples/shell/shell_common:shell_common", - "${chip_root}/src/lib/shell:shell", - ] - sources += [ - "${common_example_dir}/matter_cli/source/AppCLIBase.cpp", - "${common_example_dir}/matter_cli/source/AppCLIFreeRTOS.cpp", - ] - } - - ldscript = "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples/linker/gcc/connectivity.ld" - - inputs = [ ldscript ] - - ldflags = [ - "-Wl,--defsym=__heap_size__=0", - "-Wl,--defsym=__stack_size__=0x480", - "-Wl,-print-memory-usage", - "-Wl,--no-warn-rwx-segments", - "-Wl,--defsym=gUseNVMLink_d=1", - "-T" + rebase_path(ldscript, root_build_dir), - ] - - output_dir = root_out_dir -} - -group("default") { - deps = [ ":light_app" ] -} diff --git a/examples/lighting-app/nxp/mcxw72/README.md b/examples/lighting-app/nxp/mcxw72/README.md deleted file mode 100644 index 360c91d0814..00000000000 --- a/examples/lighting-app/nxp/mcxw72/README.md +++ /dev/null @@ -1,217 +0,0 @@ -# Matter `MCXW72` Lighting Example Application - -For generic information related to on/off light application, please see the -[common README](../README.md). - -- [Matter `MCXW72` Lighting Example Application](#matter-mcxw72-lighting-example-application) - - [Introduction](#introduction) - - [Device UI](#device-ui) - - [Configure `matter-cli`](#configure-matter-cli) - - [Building](#building) - - [Flashing](#flashing) - - [Flashing the `NBU` image with `blhost`](#flashing-the-nbu-image-with-blhost) - - [Flashing the `NBU` image with `JLink`](#flashing-the-nbu-image-with-jlink) - - [Flashing the host image](#flashing-the-host-image) - - [Factory data](#factory-data) - - [OTA](#ota) - -## Introduction - -This is an on/off lighting application implemented for an `mcxw72` device. - -The following board was used when testing this Matter reference app for a -`mcxw72` device: - -![MCXW72-EVK](../../../platform/nxp/mcxw72/doc/images/mcxw72evk.png) - -Please see -[`MCXW72` product page](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/mcx-arm-cortex-m/mcx-w-series-microcontrollers/mcx-w72x-secure-and-ultra-low-power-mcus-for-matter-thread-zigbee-and-bluetooth-le:MCX-W72X) -for more information. - -## Device UI - -This reference app is using `matter-cli` to send commands to the board through a -UART interface. - -| interface | role | -| --------- | ---------------------------------- | -| UART0 | Used for logs | -| UART1 | Used for `matter-cli` and flashing | - -The user actions are summarized below: - -| matter-cli command | output | -| ------------------------- | ------------------------ | -| `mattercommissioning on` | Enable BLE advertising | -| `mattercommissioning off` | Disable BLE advertising | -| `matterfactoryreset` | Initiate a factory reset | -| `matterreset` | Reset the device | - -### Additional UART interface - -You need a `USB-UART` bridge to make use of the second UART interface. The pin -configuration is the following: - -- `JP11 pin 1` (UART0 TX) -- `JP12 pin 1` (UART0 RX) -- `J11 pin 4` (GND) - -The state feedback is also provided through LED effects: - -| widget | effect | description | -| ------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------- | -| LED2 | short flash on (50ms on/950ms off) | The device is in an unprovisioned (unpaired) state and is waiting for a commissioner to connect. | -| LED2 | rapid even flashing (100ms period) | The device is in an unprovisioned state and a commissioner is connected via BLE. | -| LED2 | short flash off (950ms on/50ms off) | The device is fully provisioned, but does not yet have full network (Thread) or service connectivity. | -| LED2 | solid on | The device is fully provisioned and has full network and service connectivity. | -| RGB LED | on | The `OnOff` attribute of the `On/Off` cluster is `true` (simulating device turned on). | -| RGB LED | off | The `OnOff` attribute of the `On/Off` cluster is `false` (simulating device turned off). | - -The user actions are summarized below: - -| button | action | output | -| ------ | ----------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| SW2 | short press | Enable BLE advertising | -| SW2 | long press | Initiate a factory reset (can be cancelled by pressing the button again within the factory reset timeout limit - 6 seconds by default) | -| SW3 | short press | Toggle attribute `OnOff` value | -| SW3 | long press | Clean soft reset of the device (takes into account proper Matter shutdown procedure) | - -The example application provides a simple UI that depicts the state of the -device and offers basic user control. This UI is implemented via the -general-purpose LEDs and buttons built in the `MCXW72 EVK` board. - -## Building - -Manually building requires running the following commands: - -``` -user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_SDK_ROOT= -user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/lighting-app/nxp/mcxw72 -user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/mcxw72$ gn gen out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/mcxw72$ ninja -C out/debug -``` - -Please note that running `gn gen out/debug` without `--args` option will use the -default gn args values found in `args.gni`. - -After a successful build, the `elf` and `srec` files are found in `out/debug/`. -See the files prefixed with `chip-mcxw72-light-example`. - -## Flashing - -We recommend using [JLink](https://www.segger.com/downloads/jlink/) to flash -both host and `NBU` cores. To support this device, a `JLink` patch shall be -applied, so please contact your NXP liaison for guidance. - -| core | JLink target | -| ----- | ------------------ | -| host | `KW47B42ZB7_M33_0` | -| `NBU` | `KW47B42ZB7_M33_1` | - -Note: `NBU` image should be written only when a new NXP SDK is released. - -### Flashing the `NBU` image with `blhost` - -1. Install - [Secure Provisioning SDK tool](https://www.nxp.com/design/design-center/software/development-software/secure-provisioning-sdk-spsdk:SPSDK) - using Python: - - ``` - pip install spsdk - ``` - - Note: There might be some dependencies that cause conflicts with already - installed Python modules. However, `blhost` tool is still installed and can - be used. - -2. Updating `NBU` Firmware for Wireless examples - - It is necessary to work with the matching `NBU` image for the SDK version of - the application you are working with. This means that when you download your - SDK, prior to loading any wireless SDK example, update your `NBU` image with - the SDK provided binaries: - - `middleware\wireless\ieee-802.15.4\bin\mcxw72\mcxw72_nbu_ble_15_4_dyn.bin` - - 1. Place your device in `ISP` mode: - - - Press and hold `SW4` (`BOOT_CONFIG`) - - Press and hold `SW1` (`RST`) - - Relax `SW1` - - Relax `SW4` - - 2. Once the device is connected, you may find the assigned port by running: - - ``` - nxpdevscan - ``` - - 3. Run the `blhost` command to write the `bin` file: - - ``` - blhost -p write-memory 0x48800000 /middleware/wireless/ieee-802.15.4/bin/mcxw72/mcxw72_nbu_ble_15_4_dyn.bin - - ``` - -### Flashing the `NBU` image with `JLink` - -Steps: - -- Plug `MCXW72-EVK` board into the USB port -- Connect JLink to the device: - ```bash - JLinkExe -device KW47B42ZB7_M33_1 -if SWD -speed 4000 -autoconnect 1 - ``` -- Run the following commands: - ```bash - reset - halt - loadbin /middleware/wireless/ieee-802.15.4/bin/mcxw72/mcxw72_nbu_ble_15_4_dyn.bin 0 - reset - go - quit - ``` - -Note: If running into issues related to board connection, please refer to -[Flashing the `NBU` image with `blhost`](#flashing-the-nbu-image-with-blhost). -This might be needed when the `NBU` core is empty. - -### Flashing the host image - -Host image is the one found under `out/debug/`. It should be written after each -build process. - -Steps: - -- Plug `MCXW72-EVK` board into the USB port -- Connect JLink to the device: - ```bash - JLinkExe -device KW47B42ZB7_M33_0 -if SWD -speed 4000 -autoconnect 1 - ``` -- Run the following commands: - ```bash - reset - halt - loadfile chip-mcxw72-light-example.srec - reset - go - quit - ``` - -## Factory data - -Factory data is written in `IFR0, sector 1` at a predefined offset, using -`blhost`. The expanded address is `0x2002680`: - -``` -blhost --port flash-erase-region 0x2002680 -blhost --port write-memory 0x2002680 -``` - -where `` is the OS assigned port, `` the length -of factory data binary in bytes and `` the path to the factory -data binary. - -## OTA - -Please see [OTA guide](../../../../docs/guides/nxp/nxp_mcxw71_ota_guide.md). diff --git a/examples/lighting-app/nxp/mcxw72/args.gni b/examples/lighting-app/nxp/mcxw72/args.gni deleted file mode 100644 index f312c9eeb32..00000000000 --- a/examples/lighting-app/nxp/mcxw72/args.gni +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2020-2024 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") -import("${chip_root}/config/standalone/args.gni") - -# SDK target. This is overridden to add our SDK app_config.h & defines. -nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") -nxp_device = "MCXW727C" -nxp_board = "mcxw72evk" - -nxp_config_dimmable_led = false -chip_enable_ota_requestor = true -chip_stack_lock_tracking = "fatal" -chip_enable_ble = true - -is_debug = false -treat_warnings_as_errors = false - -chip_crypto = "platform" -chip_openthread_ftd = true -nxp_enable_ot_cli = false -nxp_enable_matter_cli = true - -chip_system_config_provide_statistics = false -chip_system_config_use_openthread_inet_endpoints = true -chip_with_lwip = false diff --git a/examples/lighting-app/nxp/mcxw72/build_overrides b/examples/lighting-app/nxp/mcxw72/build_overrides deleted file mode 120000 index ee19c065d61..00000000000 --- a/examples/lighting-app/nxp/mcxw72/build_overrides +++ /dev/null @@ -1 +0,0 @@ -../../../build_overrides/ \ No newline at end of file diff --git a/examples/lighting-app/nxp/mcxw72/include/config/AppConfig.h b/examples/lighting-app/nxp/mcxw72/include/config/AppConfig.h deleted file mode 100644 index 6dcccf749bb..00000000000 --- a/examples/lighting-app/nxp/mcxw72/include/config/AppConfig.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 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 - -/* ---- App Config ---- */ -#define APP_DEVICE_TYPE_ENDPOINT 1 -#define APP_CLUSTER_ATTRIBUTE chip::app::Clusters::OnOff::Attributes::OnOff - -/* ---- Button Manager Config ---- */ -#define BUTTON_MANAGER_FACTORY_RESET_TIMEOUT_MS 6000 - -/* ---- LED Manager Config ---- */ -#define LED_MANAGER_STATUS_LED_INDEX 0 -#define LED_MANAGER_LIGHT_LED_INDEX 1 diff --git a/examples/lighting-app/nxp/mcxw72/include/config/CHIPProjectConfig.h b/examples/lighting-app/nxp/mcxw72/include/config/CHIPProjectConfig.h deleted file mode 100644 index accdf735e32..00000000000 --- a/examples/lighting-app/nxp/mcxw72/include/config/CHIPProjectConfig.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2020 Google LLC. - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Example project configuration file for CHIP. - * - * This is a place to put application or project-specific overrides - * to the default configuration values for general CHIP features. - * - */ - -#pragma once - -// Security and Authentication disabled for development build. -// For convenience, enable CHIP Security Test Mode and disable the requirement for -// authentication in various protocols. -// WARNING: These options make it possible to circumvent basic CHIP security functionality, -// including message encryption. Because of this they MUST NEVER BE ENABLED IN PRODUCTION BUILDS. -#define CHIP_CONFIG_SECURITY_TEST_MODE 0 - -// Use hard-coded test certificates already embedded in generic chip code => set it to 0 -// Use real/development certificates => set it to 1 + file the provisioning section from -// the internal flash -#ifndef CONFIG_CHIP_LOAD_REAL_FACTORY_DATA -#define CONFIG_CHIP_LOAD_REAL_FACTORY_DATA 0 -#endif - -#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA - -// VID/PID for product => will be used by Basic Information Cluster -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0x1037 -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0xA221 // TBD - -// Set the following define to use the Certification Declaration from below and not use it stored in factory data section -#ifndef CHIP_USE_DEVICE_CONFIG_CERTIFICATION_DECLARATION -#define CHIP_USE_DEVICE_CONFIG_CERTIFICATION_DECLARATION 0 -#endif - -#ifndef CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION -//-> format_version = 1 -//-> vendor_id = 0x1037 -//-> product_id_array = [ 0xA221 ] // TBD -//-> device_type_id = 0x0100 -//-> certificate_id = "ZIG20142ZB330003-24" -//-> security_level = 0 -//-> security_information = 0 -//-> version_number = 0x2694 -//-> certification_type = 1 -//-> dac_origin_vendor_id is not present -//-> dac_origin_product_id is not present -#define CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION \ - { \ - 0x30, 0x81, 0xe9, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x81, 0xdb, 0x30, 0x81, 0xd8, \ - 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, \ - 0x45, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x38, 0x04, 0x36, 0x15, 0x24, 0x00, \ - 0x01, 0x25, 0x01, 0x37, 0x10, 0x36, 0x02, 0x05, 0x21, 0xa2, 0x18, 0x25, 0x03, 0x00, 0x01, 0x2c, 0x04, 0x13, 0x5a, \ - 0x49, 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x34, 0x24, \ - 0x05, 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x76, 0x98, 0x24, 0x08, 0x01, 0x18, 0x31, 0x7d, 0x30, 0x7b, 0x02, 0x01, \ - 0x03, 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, \ - 0x04, 0xf3, 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0a, \ - 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0x93, 0x77, \ - 0x28, 0xd2, 0xd5, 0x36, 0xea, 0x09, 0xe4, 0xc5, 0xbc, 0x87, 0xa5, 0xa2, 0x44, 0x57, 0xf0, 0xed, 0x24, 0x66, 0xe7, \ - 0x50, 0x61, 0x1b, 0xe1, 0x17, 0x7c, 0x55, 0x0a, 0x83, 0xfa, 0xc3, 0x02, 0x20, 0x21, 0x6c, 0x60, 0x67, 0x4e, 0x3f, \ - 0xbe, 0x30, 0x38, 0xd4, 0x5e, 0x86, 0x1d, 0xe1, 0xe7, 0x6f, 0x7b, 0x1d, 0xd4, 0xfe, 0xbf, 0x79, 0x5a, 0x4e, 0x07, \ - 0x83, 0x46, 0xca, 0x94, 0x92, 0x5f, 0x14 \ - } - -// All remaining data will be pulled from the provisioning region of flash. -#endif - -#else - -/** - * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID - * - * 0xFFF1: Test vendor. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1 - -/** - * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID - * - * 0x8005: example lighting-app - */ -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8005 - -// Use a default setup PIN code if one hasn't been provisioned in flash. -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 -#endif - -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 -#endif - -// Use a default pairing code if one hasn't been provisioned in flash. -#define CHIP_DEVICE_CONFIG_USE_TEST_PAIRING_CODE "CHIPUS" - -/** - * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER - * - * Enables the use of a hard-coded default serial number if none - * is found in CHIP NV storage. - */ -#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN" - -#endif // CONFIG_CHIP_LOAD_REAL_FACTORY_DATA - -/** - * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION - * - * The hardware version number assigned to device or product by the device vendor. This - * number is scoped to the device product id, and typically corresponds to a revision of the - * physical device, a change to its packaging, and/or a change to its marketing presentation. - * This value is generally *not* incremented for device software versions. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 100 - -#ifndef CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING "v0.1.0" -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING - * - * A string identifying the software version running on the device. - * CHIP currently expects the software version to be in the format - * {MAJOR_VERSION}.0d{MINOR_VERSION} - */ -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION NXP_CONFIG_DEVICE_SOFTWARE_VERSION -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "NXP Semiconductors" -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "NXP Demo App" -#endif - -/** - * CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC - * - * Enables synchronizing the device's real time clock with a remote CHIP Time service - * using the CHIP Time Sync protocol. - */ -// #define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 1 - -/** - * CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_TIMEOUT - * - * The amount of time in miliseconds after which BLE should change his advertisements - * from fast interval to slow interval. - * - * 30000 (30 secondes). - */ -#define CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_TIMEOUT (30 * 1000) - -/** - * CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT - * - * The amount of time in miliseconds after which BLE advertisement should be disabled, counting - * from the moment of slow advertisement commencement. - * - * Defaults to 9000000 (15 minutes). - */ -#define CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT (15 * 60 * 1000) - -/** - * CONFIG_CHIP_NFC_COMMISSIONING, CHIP_DEVICE_CONFIG_ENABLE_NFC - * - * NFC commissioning is not supported - */ -#define CONFIG_CHIP_NFC_COMMISSIONING 0 -#define CHIP_DEVICE_CONFIG_ENABLE_NFC 0 - -/** - * @def CHIP_CONFIG_MAX_FABRICS - * - * @brief - * Maximum number of fabrics the device can participate in. Each fabric can - * provision the device with its unique operational credentials and manage - * its own access control lists. - */ -#define CHIP_CONFIG_MAX_FABRICS 5 // 5 is the minimum number of supported fabrics - -/** - * @def CHIP_IM_MAX_NUM_COMMAND_HANDLER - * - * @brief Defines the maximum number of CommandHandler, limits the number of active commands transactions on server. - */ -#define CHIP_IM_MAX_NUM_COMMAND_HANDLER 2 - -/** - * @def CHIP_IM_MAX_NUM_WRITE_HANDLER - * - * @brief Defines the maximum number of WriteHandler, limits the number of active write transactions on server. - */ -#define CHIP_IM_MAX_NUM_WRITE_HANDLER 2 - -/** - * CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE - * - * For a development build, set the default importance of events to be logged as Debug. - * Since debug is the lowest importance level, this means all standard, critical, info and - * debug importance level vi events get logged. - */ -#if BUILD_RELEASE -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Production -#else -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug -#endif // BUILD_RELEASE - -#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1 diff --git a/examples/lighting-app/nxp/mcxw72/third_party/connectedhomeip b/examples/lighting-app/nxp/mcxw72/third_party/connectedhomeip deleted file mode 120000 index 59307833b4f..00000000000 --- a/examples/lighting-app/nxp/mcxw72/third_party/connectedhomeip +++ /dev/null @@ -1 +0,0 @@ -../../../../.. \ No newline at end of file diff --git a/examples/lighting-app/nxp/zap/lighting-on-off.matter b/examples/lighting-app/nxp/zap/lighting-on-off.matter index e95160f2291..bdb2c682db9 100644 --- a/examples/lighting-app/nxp/zap/lighting-on-off.matter +++ b/examples/lighting-app/nxp/zap/lighting-on-off.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/lighting-app/qpg/zap/light.matter b/examples/lighting-app/qpg/zap/light.matter index a7bd3d6c071..2894102ca52 100644 --- a/examples/lighting-app/qpg/zap/light.matter +++ b/examples/lighting-app/qpg/zap/light.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/lighting-app/realtek/data_model/lighting-app.matter b/examples/lighting-app/realtek/data_model/lighting-app.matter index 57e6c1932c2..67e51c4eb7d 100644 --- a/examples/lighting-app/realtek/data_model/lighting-app.matter +++ b/examples/lighting-app/realtek/data_model/lighting-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/lighting-app/silabs/data_model/lighting-thread-app.matter b/examples/lighting-app/silabs/data_model/lighting-thread-app.matter index 19eab2253a5..2bf64f289c2 100644 --- a/examples/lighting-app/silabs/data_model/lighting-thread-app.matter +++ b/examples/lighting-app/silabs/data_model/lighting-thread-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/lighting-app/silabs/data_model/lighting-wifi-app.matter b/examples/lighting-app/silabs/data_model/lighting-wifi-app.matter index 194f372d5bd..9658ac57513 100644 --- a/examples/lighting-app/silabs/data_model/lighting-wifi-app.matter +++ b/examples/lighting-app/silabs/data_model/lighting-wifi-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } 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 52438f7965b..7673c8b876a 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 @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/lock-app/lock-common/lock-app.matter b/examples/lock-app/lock-common/lock-app.matter index 2d22c41b8b8..461d846fb97 100644 --- a/examples/lock-app/lock-common/lock-app.matter +++ b/examples/lock-app/lock-common/lock-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } @@ -3257,7 +3259,7 @@ endpoint 0 { } endpoint 1 { device type ma_powersource = 17, version 1; - device type ma_doorlock = 10, version 3; + device type ma_doorlock = 10, version 4; server cluster Identify { @@ -3347,7 +3349,7 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0x7DB3; - ram attribute clusterRevision default = 8; + ram attribute clusterRevision default = 10; handle command LockDoor; handle command UnlockDoor; diff --git a/examples/lock-app/lock-common/lock-app.zap b/examples/lock-app/lock-common/lock-app.zap index 8c1bcac8f3f..83e600601e4 100644 --- a/examples/lock-app/lock-common/lock-app.zap +++ b/examples/lock-app/lock-common/lock-app.zap @@ -4543,7 +4543,7 @@ } ], "deviceVersions": [ - 3, + 4, 1 ], "deviceIdentifiers": [ @@ -5942,7 +5942,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "8", + "defaultValue": "10", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -6008,4 +6008,4 @@ "parentEndpointIdentifier": null } ] -} \ No newline at end of file +} diff --git a/examples/lock-app/nxp/README.md b/examples/lock-app/nxp/README.md index bad2681f5fc..bbd71530e82 100644 --- a/examples/lock-app/nxp/README.md +++ b/examples/lock-app/nxp/README.md @@ -1,132 +1,96 @@ # Matter NXP Door Lock Example Application -This reference application implements an Door Lock device type. It uses board -buttons or `matter-cli` for user input and LEDs for state feedback. You can use -this example as a reference for creating your own application. - -The example is based on: - -- [Matter](https://github.com/project-chip/connectedhomeip) -- [NXP github SDK](https://github.com/nxp-mcuxpresso/mcux-sdk) - -- [Matter NXP Door Lock Example Application](#matter-nxp-door-lock-example-application) - - [Supported devices](#supported-devices) - - [Introduction](#introduction) - - [Device UI](#device-ui) - - [Prerequisites for building](#prerequisites-for-building) - - [Building](#building) - - [Data model](#data-model) - - [Manufacturing data](#manufacturing-data) - - [Flashing and debugging](#flashing-and-debugging) +- [Overview](#overview) +- [Supported Platforms](#supported-platforms) +- [Environment Setup, Building, and Testing](#build) +- [Data Model](#data-model) +- [Manufacturing Data](#factory-data) -## Supported devices + -- [mcxw71](mcxw71/README.md) +## Overview -## Introduction +This reference application implements a Door Lock device type. It uses board +buttons or `matter-cli` for user input and LEDs for state feedback. You can use +this example as a reference for creating your own application. -The application showcases a door lock device that communicates with clients over -a low-power, 802.15.4 Thread network. +The example is based on +[Project CHIP](https://github.com/project-chip/connectedhomeip) and NXP SDK, and +provides a prototype application that demonstrates device commissioning and +different cluster control. -It can be commissioned into an existing Matter network using a controller such -as `chip-tool`. +The door lock device communicates with clients over a low-power, 802.15.4 Thread +network. It can be commissioned into an existing Matter network using a +controller such as `chip-tool`. -This example implements a `User-Intent Commissioning Flow`, meaning the user has -to press a button in order for the device to be ready for commissioning. The -initial commissioning is done through `ble-thread` pairing method. +This example implements a `User-Intent Commissioning Flow`, meaning that the +user is required to press a button in order for the device to be ready for +commissioning. The initial commissioning is usually performed using the +`ble-thread` pairing method. The Thread network dataset will be transferred on the device using a secure session over Bluetooth LE. In order to start the commissioning process, the user must enable BLE advertising on the device manually. To pair successfully, the commissioner must know the commissioning information corresponding to the -device: setup passcode and discriminator. This data is usually encoded within a -QR code or printed to the UART console. - -## Device UI - -The example application provides a simple UI that depicts the state of the -device and offers basic user control. This UI is implemented via the -general-purpose LEDs and buttons built in the evaluation boards. Please see each -supported device readme file for details. +device: setup passcode and/or discriminator. This data is usually encoded within +a QR code or printed to the device's UART console. -## Prerequisites for building + -In order to build the example, it is recommended to use a Linux distribution. -Please visit the supported Operating Systems list in -[BUILDING.md](../../../docs/guides/BUILDING.md#prerequisites). +## Supported Platforms -- Make sure that below prerequisites are correctly installed (as described in - [BUILDING.md](../../../docs/guides/BUILDING.md#prerequisites)) +The Door Lock example is supported on the following platforms : -``` -sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev -``` +| NXP platform | Dedicated readme | +| ------------ | ------------------------------------------------------------------- | +| MCXW71 | [NXP MCXW71 Guide](../../../docs/platforms/nxp/nxp_mcxw71_guide.md) | +| MCXW72 | [NXP MCXW72 Guide](../../../docs/platforms/nxp/nxp_mcxw72_guide.md) | -- Step 1: checkout NXP specific submodules only +For details on platform-specific requirements and configurations, please refer +to the respective platform's readme. - ``` - user@ubuntu:~/Desktop/git/connectedhomeip$ scripts/checkout_submodules.py --shallow --platform nxp --recursive - ``` +A list of popular standard door lock app targets is presented below. These +targets can be used with the `build_example.py` tool. -- Step 2: activate local environment +| Target name | Description | +| ------------------------------------------------------------------ | --------------------------------------------- | +| `nxp--freertos-lock-app-thread-mtd-frdm` | Default door lock | +| `nxp--freertos-lock-app-thread-mtd-low-power-frdm` | Default low-power door lock | +| `nxp--freertos-lock-app-thread-mtd-low-power-factory-frdm` | Default low-power door lock with factory data | - ``` - user@ubuntu:~/Desktop/git/connectedhomeip$ source scripts/activate.sh - ``` +where `device` is one of the [supported platforms](#supported-platforms). - If the script says the environment is out of date, you can update it by - running the following command: + - ``` - user@ubuntu:~/Desktop/git/connectedhomeip$ source scripts/bootstrap.sh - ``` +## Environment Setup, Building, and Testing -- Step 3: Init NXP SDK(s) +All the information required to set up the environment, build the application, +and test it can be found in the common readme for NXP platforms: - ``` - user@ubuntu:~/Desktop/git/connectedhomeip$ third_party/nxp/nxp_matter_support/scripts/update_nxp_sdk.py --platform common - ``` +- NXP FreeRTOS Platforms : Refer to the + [CHIP NXP Examples Guide for FreeRTOS platforms](../../../docs/platforms/nxp/nxp_examples_freertos_platforms.md) -Note: By default, `update_nxp_sdk.py` will try to initialize all NXP SDKs. -Please run the script with arg `--help` to view all available options. + -## Building - -There are two options for building this reference app: - -- Using `build_examples.py` framework. -- Manually generating `ninja` files using `gn`. - -For manual generation and building, please see the specific readme file for your -device. - -A list of all available contact sensor targets can be viewed in the following -table: - -| target name | description | -| ---------------------------- | ---------------- | -| nxp-device-freertos-lock-app | Default lock app | - -where `device` can be one of the [Supported devices](#supported-devices). - -### Data model +## Data Model The application uses an NXP specific data model file: -| path | description | +| Path | Description | | ------------------ | ------------------------------------ | | `zap/lock-app.zap` | Data model for Door Lock device type | -The data model can be changed by simply replacing the gn `deps` statement -corresponding to data model target. + -### Manufacturing data +## Manufacturing Data -Use `nxp_use_factory_data=true` in the gn build command to enable factory data. +The support for manufacturing data is enabled at build time when you use the +appropriate build configuration files for this feature. Please refer to the +[NXP Matter examples guide for FreeRTOS](../../../docs/platforms/nxp/nxp_examples_freertos_platforms.md) +for details on the build process and available build configurations. +Manufacturing data can also be forced in the build command line by using the +`CONFIG_CHIP_FACTORY_DATA=y` build option or by using the appropriate +`build_examples.py` [targets](#supported-platforms). -For a full guide on manufacturing flow, please see +For a full guide on the manufacturing flow, please refer to the [Guide for writing manufacturing data on NXP devices](../../../docs/platforms/nxp/nxp_manufacturing_flow.md). - -## Flashing and debugging - -Please see the device specific readme file. diff --git a/examples/lock-app/nxp/common/main/AppTask.cpp b/examples/lock-app/nxp/common/main/AppTask.cpp index d2a983e68d3..d2fb2bc6e34 100644 --- a/examples/lock-app/nxp/common/main/AppTask.cpp +++ b/examples/lock-app/nxp/common/main/AppTask.cpp @@ -168,7 +168,9 @@ LockApp::AppTask & LockApp::AppTask::GetDefaultInstance() return sAppTask; } +#ifndef CONFIG_APP_TASK_CUSTOM_SINGLETON_IMPL chip::NXP::App::AppTaskBase & chip::NXP::App::GetAppTask() { return LockApp::AppTask::GetDefaultInstance(); } +#endif diff --git a/examples/lock-app/nxp/common/main/DeviceCallbacks.cpp b/examples/lock-app/nxp/common/main/DeviceCallbacks.cpp index b1ae6a4baaf..0b47f7bacb7 100644 --- a/examples/lock-app/nxp/common/main/DeviceCallbacks.cpp +++ b/examples/lock-app/nxp/common/main/DeviceCallbacks.cpp @@ -93,7 +93,9 @@ LockApp::DeviceCallbacks & LockApp::DeviceCallbacks::GetDefaultInstance() return sDeviceCallbacks; } +#ifndef CONFIG_APP_DEVICE_CALLBACKS_CUSTOM_SINGLETON_IMPL chip::DeviceManager::CHIPDeviceManagerCallbacks & chip::NXP::App::GetDeviceCallbacks() { return LockApp::DeviceCallbacks::GetDefaultInstance(); } +#endif diff --git a/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp deleted file mode 100644 index bdb4af82020..00000000000 --- a/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp +++ /dev/null @@ -1,793 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2020 Google LLC. - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "AppTask.h" -#include "AppEvent.h" -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "Keyboard.h" -#include "LED.h" -#include "LEDWidget.h" -#include "PWR_Interface.h" -#include "app_config.h" - -#if CHIP_CRYPTO_HSM -#include -#endif -#ifdef ENABLE_HSM_DEVICE_ATTESTATION -#include "DeviceAttestationSe05xCredsExample.h" -#endif - -constexpr uint32_t kFactoryResetTriggerTimeout = 6000; -constexpr uint8_t kAppEventQueueSize = 10; - -TimerHandle_t sFunctionTimer; // FreeRTOS app sw timer. - -static QueueHandle_t sAppEventQueue; - -#if !defined(chip_with_low_power) || (chip_with_low_power == 0) -static LEDWidget sStatusLED; -static LEDWidget sLockLED; -#endif - -static bool sIsThreadProvisioned = false; -static bool sHaveBLEConnections = false; - -static uint32_t eventMask = 0; - -#if CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI -extern "C" void K32WUartProcess(void); -#endif - -using namespace ::chip::Credentials; -using namespace ::chip::DeviceLayer; - -AppTask AppTask::sAppTask; -#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA -static chip::DeviceLayer::FactoryDataProviderImpl sFactoryDataProvider; -#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER -static chip::DeviceLayer::CustomFactoryDataProvider sCustomFactoryDataProvider; -#endif -#endif - -CHIP_ERROR AppTask::StartAppTask() -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - sAppEventQueue = xQueueCreate(kAppEventQueueSize, sizeof(AppEvent)); - if (sAppEventQueue == NULL) - { - K32W_LOG("Failed to allocate app event queue"); - assert(false); - } - - return err; -} - -CHIP_ERROR AppTask::Init() -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - // Init ZCL Data Model and start server - PlatformMgr().ScheduleWork(InitServer, 0); - -// Initialize device attestation config -#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA - // Initialize factory data provider - ReturnErrorOnFailure(sFactoryDataProvider.Init()); - SetDeviceInstanceInfoProvider(&sFactoryDataProvider); - SetDeviceAttestationCredentialsProvider(&sFactoryDataProvider); - SetCommissionableDataProvider(&sFactoryDataProvider); -#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER - sCustomFactoryDataProvider.ParseFunctionExample(); -#endif -#else -#ifdef ENABLE_HSM_DEVICE_ATTESTATION - SetDeviceAttestationCredentialsProvider(Examples::GetExampleSe05xDACProvider()); -#else - SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); -#endif -#endif // CONFIG_CHIP_LOAD_REAL_FACTORY_DATA - - // QR code will be used with CHIP Tool - AppTask::PrintOnboardingInfo(); - - /* HW init leds */ -#if !defined(chip_with_low_power) || (chip_with_low_power == 0) - LED_Init(); - - /* start with all LEDS turnedd off */ - sStatusLED.Init(SYSTEM_STATE_LED); - - sLockLED.Init(LOCK_STATE_LED); - sLockLED.Set(!BoltLockMgr().IsUnlocked()); -#endif - UpdateClusterState(); - - /* intialize the Keyboard and button press calback */ - KBD_Init(KBD_Callback); - - // Create FreeRTOS sw timer for Function Selection. - sFunctionTimer = xTimerCreate("FnTmr", // Just a text name, not used by the RTOS kernel - 1, // == default timer period (mS) - false, // no timer reload (==one-shot) - (void *) this, // init timer id = app task obj context - TimerEventHandler // timer callback handler - ); - if (sFunctionTimer == NULL) - { - K32W_LOG("app_timer_create() failed"); - assert(err == CHIP_NO_ERROR); - } - - int status = BoltLockMgr().Init(); - if (status != 0) - { - K32W_LOG("BoltLockMgr().Init() failed"); - assert(status == 0); - } - - BoltLockMgr().SetCallbacks(ActionInitiated, ActionCompleted); - - // Print the current software version - char currentSoftwareVer[ConfigurationManager::kMaxSoftwareVersionStringLength + 1] = { 0 }; - err = ConfigurationMgr().GetSoftwareVersionString(currentSoftwareVer, sizeof(currentSoftwareVer)); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("Get version error"); - assert(err == CHIP_NO_ERROR); - } - - PlatformMgr().AddEventHandler(MatterEventHandler, 0); - - K32W_LOG("Current Software Version: %s", currentSoftwareVer); - return err; -} - -void LockOpenThreadTask(void) -{ - PWR_DisallowDeviceToSleep(); - chip::DeviceLayer::ThreadStackMgr().LockThreadStack(); -} - -void UnlockOpenThreadTask(void) -{ - chip::DeviceLayer::ThreadStackMgr().UnlockThreadStack(); - PWR_AllowDeviceToSleep(); -} - -void AppTask::InitServer(intptr_t arg) -{ - static chip::CommonCaseDeviceServerInitParams initParams; - (void) initParams.InitializeStaticResourcesBeforeServerInit(); - initParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(initParams.persistentStorageDelegate); - - auto & infoProvider = chip::DeviceLayer::DeviceInfoProviderImpl::GetDefaultInstance(); - infoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); - chip::DeviceLayer::SetDeviceInfoProvider(&infoProvider); - - // Init ZCL Data Model and start server - chip::Inet::EndPointStateOpenThread::OpenThreadEndpointInitParam nativeParams; - nativeParams.lockCb = LockOpenThreadTask; - nativeParams.unlockCb = UnlockOpenThreadTask; - nativeParams.openThreadInstancePtr = chip::DeviceLayer::ThreadStackMgrImpl().OTInstance(); - initParams.endpointNativeParams = static_cast(&nativeParams); - VerifyOrDie((chip::Server::GetInstance().Init(initParams)) == CHIP_NO_ERROR); -} - -void AppTask::PrintOnboardingInfo() -{ - chip::PayloadContents payload; - CHIP_ERROR err = GetPayloadContents(payload, chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); - if (err != CHIP_NO_ERROR) - { - ChipLogError(AppServer, "GetPayloadContents() failed: %" CHIP_ERROR_FORMAT, err.Format()); - } - payload.commissioningFlow = chip::CommissioningFlow::kUserActionRequired; - PrintOnboardingCodes(payload); -} - -void AppTask::AppTaskMain(void * pvParameter) -{ - AppEvent event; - - CHIP_ERROR err = sAppTask.Init(); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("AppTask.Init() failed"); - assert(err == CHIP_NO_ERROR); - } - - while (true) - { - TickType_t xTicksToWait = pdMS_TO_TICKS(10); - -#if defined(chip_with_low_power) && (chip_with_low_power == 1) - xTicksToWait = portMAX_DELAY; -#endif - - BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, xTicksToWait); - while (eventReceived == pdTRUE) - { - sAppTask.DispatchEvent(&event); - eventReceived = xQueueReceive(sAppEventQueue, &event, 0); - } - - // Collect connectivity and configuration state from the CHIP stack. Because the - // CHIP event loop is being run in a separate task, the stack must be locked - // while these values are queried. However we use a non-blocking lock request - // (TryLockChipStack()) to avoid blocking other UI activities when the CHIP - // task is busy (e.g. with a long crypto operation). - if (PlatformMgr().TryLockChipStack()) - { -#if CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI - K32WUartProcess(); -#endif - sHaveBLEConnections = (ConnectivityMgr().NumBLEConnections() != 0); - PlatformMgr().UnlockChipStack(); - } - - // Update the status LED if factory reset has not been initiated. - // - // If system has "full connectivity", keep the LED On constantly. - // - // If thread and service provisioned, but not attached to the thread network yet OR no - // connectivity to the service OR subscriptions are not fully established - // THEN blink the LED Off for a short period of time. - // - // If the system has ble connection(s) uptill the stage above, THEN blink the LEDs at an even - // rate of 100ms. - // - // Otherwise, blink the LED ON for a very short time. - -#if !defined(chip_with_low_power) || (chip_with_low_power == 0) - if (sAppTask.mFunction != kFunction_FactoryReset) - { - if (sIsThreadProvisioned) - { - sStatusLED.Blink(950, 50); - } - else if (sHaveBLEConnections) - { - sStatusLED.Blink(100, 100); - } - else - { - sStatusLED.Blink(50, 950); - } - } - - sStatusLED.Animate(); - sLockLED.Animate(); -#endif - } -} - -void AppTask::ButtonEventHandler(uint8_t pin_no, uint8_t button_action) -{ - if ((pin_no != RESET_BUTTON) && (pin_no != LOCK_BUTTON) && (pin_no != JOIN_BUTTON) && (pin_no != BLE_BUTTON)) - { - return; - } - - AppEvent button_event; - button_event.Type = AppEvent::kEventType_Button; - button_event.ButtonEvent.PinNo = pin_no; - button_event.ButtonEvent.Action = button_action; - - if (pin_no == RESET_BUTTON) - { - button_event.Handler = ResetActionEventHandler; - } - else if (pin_no == LOCK_BUTTON) - { - button_event.Handler = LockActionEventHandler; - } - else if (pin_no == JOIN_BUTTON) - { - button_event.Handler = JoinHandler; - } - else if (pin_no == BLE_BUTTON) - { - button_event.Handler = BleHandler; - -#if !(defined OM15082) - if (button_action == RESET_BUTTON_PUSH) - { - button_event.Handler = ResetActionEventHandler; - } -#endif - } - sAppTask.PostEvent(&button_event); -} - -void AppTask::KBD_Callback(uint8_t events) -{ - eventMask = eventMask | (uint32_t) (1 << events); - - HandleKeyboard(); -} - -void AppTask::HandleKeyboard(void) -{ - uint8_t keyEvent = 0xFF; - uint8_t pos = 0; - - while (eventMask) - { - for (pos = 0; pos < (8 * sizeof(eventMask)); pos++) - { - if (eventMask & (1 << pos)) - { - keyEvent = pos; - eventMask = eventMask & ~(1 << pos); - break; - } - } - - switch (keyEvent) - { - case gKBD_EventPB1_c: - K32W_LOG("pb1 short press"); - -#if (defined OM15082) - ButtonEventHandler(RESET_BUTTON, RESET_BUTTON_PUSH); - break; -#else - if (sAppTask.mResetTimerActive) - { - ButtonEventHandler(BLE_BUTTON, RESET_BUTTON_PUSH); - } - else - { - ButtonEventHandler(BLE_BUTTON, BLE_BUTTON_PUSH); - } - break; -#endif - case gKBD_EventPB2_c: - ButtonEventHandler(LOCK_BUTTON, LOCK_BUTTON_PUSH); - break; - case gKBD_EventPB3_c: - ButtonEventHandler(JOIN_BUTTON, JOIN_BUTTON_PUSH); - break; - case gKBD_EventPB4_c: - ButtonEventHandler(BLE_BUTTON, BLE_BUTTON_PUSH); - break; -#if !(defined OM15082) - case gKBD_EventLongPB1_c: - K32W_LOG("pb1 long press"); - ButtonEventHandler(BLE_BUTTON, RESET_BUTTON_PUSH); - break; -#endif - default: - break; - } - } -} - -void AppTask::TimerEventHandler(TimerHandle_t xTimer) -{ - AppEvent event; - event.Type = AppEvent::kEventType_Timer; - event.TimerEvent.Context = (void *) xTimer; - event.Handler = FunctionTimerEventHandler; - sAppTask.PostEvent(&event); -} - -void AppTask::FunctionTimerEventHandler(void * aGenericEvent) -{ - AppEvent * aEvent = (AppEvent *) aGenericEvent; - - if (aEvent->Type != AppEvent::kEventType_Timer) - return; - - K32W_LOG("Device will factory reset..."); - - // Actually trigger Factory Reset - chip::Server::GetInstance().ScheduleFactoryReset(); -} - -void AppTask::ResetActionEventHandler(void * aGenericEvent) -{ - AppEvent * aEvent = (AppEvent *) aGenericEvent; - - if (aEvent->ButtonEvent.PinNo != RESET_BUTTON && aEvent->ButtonEvent.PinNo != BLE_BUTTON) - return; - - if (sAppTask.mResetTimerActive) - { - sAppTask.CancelTimer(); - sAppTask.mFunction = kFunction_NoneSelected; - -#if !defined(chip_with_low_power) || (chip_with_low_power == 0) - /* restore initial state for the LED indicating Lock state */ - if (BoltLockMgr().IsUnlocked()) - { - sLockLED.Set(false); - } - else - { - sLockLED.Set(true); - } -#endif - - K32W_LOG("Factory Reset was cancelled!"); - } - else - { - uint32_t resetTimeout = kFactoryResetTriggerTimeout; - - if (sAppTask.mFunction != kFunction_NoneSelected) - { - K32W_LOG("Another function is scheduled. Could not initiate Factory Reset!"); - return; - } - - K32W_LOG("Factory Reset Triggered. Push the RESET button within %u ms to cancel!", resetTimeout); - sAppTask.mFunction = kFunction_FactoryReset; - - /* LEDs will start blinking to signal that a Factory Reset was scheduled */ -#if !defined(chip_with_low_power) || (chip_with_low_power == 0) - sStatusLED.Set(false); - sLockLED.Set(false); - - sStatusLED.Blink(500); - sLockLED.Blink(500); -#endif - - sAppTask.StartTimer(kFactoryResetTriggerTimeout); - } -} - -void AppTask::LockActionEventHandler(void * aGenericEvent) -{ - AppEvent * aEvent = (AppEvent *) aGenericEvent; - BoltLockManager::Action_t action; - CHIP_ERROR err = CHIP_NO_ERROR; - int32_t actor = 0; - bool initiated = false; - - if (sAppTask.mFunction != kFunction_NoneSelected) - { - K32W_LOG("Another function is scheduled. Could not initiate Lock/Unlock!"); - return; - } - - if (aEvent->Type == AppEvent::kEventType_Lock) - { - action = static_cast(aEvent->LockEvent.Action); - actor = aEvent->LockEvent.Actor; - } - else if (aEvent->Type == AppEvent::kEventType_Button) - { - if (BoltLockMgr().IsUnlocked()) - { - action = BoltLockManager::LOCK_ACTION; - } - else - { - action = BoltLockManager::UNLOCK_ACTION; - } - } - else - { - err = CHIP_ERROR_INTERNAL; - action = BoltLockManager::INVALID_ACTION; - } - - if (err == CHIP_NO_ERROR) - { - initiated = BoltLockMgr().InitiateAction(actor, action); - - if (!initiated) - { - K32W_LOG("Action is already in progress or active."); - } - } -} - -void AppTask::ThreadStart() -{ - chip::Thread::OperationalDataset dataset{}; - - constexpr uint8_t xpanid[] = { 0xde, 0xad, 0x00, 0xbe, 0xef, 0x00, 0xca, 0xfe }; - constexpr uint8_t masterkey[] = { - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF - }; - constexpr uint16_t panid = 0xabcd; - constexpr uint16_t channel = 15; - - dataset.SetNetworkName("OpenThread"); - dataset.SetExtendedPanId(xpanid); - dataset.SetMasterKey(masterkey); - dataset.SetPanId(panid); - dataset.SetChannel(channel); - - ThreadStackMgr().SetThreadEnabled(false); - ThreadStackMgr().SetThreadProvision(dataset.AsByteSpan()); - ThreadStackMgr().SetThreadEnabled(true); -} - -void AppTask::JoinHandler(void * aGenericEvent) -{ - AppEvent * aEvent = (AppEvent *) aGenericEvent; - - if (aEvent->ButtonEvent.PinNo != JOIN_BUTTON) - return; - - if (sAppTask.mFunction != kFunction_NoneSelected) - { - K32W_LOG("Another function is scheduled. Could not initiate Thread Join!"); - return; - } - - /* hard-code Thread Commissioning Parameters for the moment. - * In a future PR, these parameters will be sent via BLE. - */ - ThreadStart(); -} - -void AppTask::BleHandler(void * aGenericEvent) -{ - AppEvent * aEvent = (AppEvent *) aGenericEvent; - - if (aEvent->ButtonEvent.PinNo != BLE_BUTTON) - return; - - if (sAppTask.mFunction != kFunction_NoneSelected) - { - K32W_LOG("Another function is scheduled. Could not toggle BLE state!"); - return; - } - PlatformMgr().ScheduleWork(AppTask::BleStartAdvertising, 0); -} - -void AppTask::BleStartAdvertising(intptr_t arg) -{ - if (ConnectivityMgr().IsBLEAdvertisingEnabled()) - { - ConnectivityMgr().SetBLEAdvertisingEnabled(false); - K32W_LOG("Stopped BLE Advertising!"); - } - else - { - ConnectivityMgr().SetBLEAdvertisingEnabled(true); - - if (chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow() == CHIP_NO_ERROR) - { - K32W_LOG("Started BLE Advertising!"); - } - else - { - K32W_LOG("OpenBasicCommissioningWindow() failed"); - } - } -} - -void AppTask::MatterEventHandler(const ChipDeviceEvent * event, intptr_t) -{ - if (event->Type == DeviceEventType::kServiceProvisioningChange && event->ServiceProvisioningChange.IsServiceProvisioned) - { - if (event->ServiceProvisioningChange.IsServiceProvisioned) - { - sIsThreadProvisioned = TRUE; - } - else - { - sIsThreadProvisioned = FALSE; - } - } - -#if CONFIG_CHIP_NFC_ONBOARDING_PAYLOAD - if (event->Type == DeviceEventType::kCHIPoBLEAdvertisingChange && event->CHIPoBLEAdvertisingChange.Result == kActivity_Stopped) - { - if (!NFCOnboardingPayloadMgr().IsTagEmulationStarted()) - { - K32W_LOG("NFC Tag emulation is already stopped!"); - } - else - { - NFCOnboardingPayloadMgr().StopTagEmulation(); - K32W_LOG("Stopped NFC Tag Emulation!"); - } - } - else if (event->Type == DeviceEventType::kCHIPoBLEAdvertisingChange && - event->CHIPoBLEAdvertisingChange.Result == kActivity_Started) - { - if (NFCOnboardingPayloadMgr().IsTagEmulationStarted()) - { - K32W_LOG("NFC Tag emulation is already started!"); - } - else - { - ShareQRCodeOverNFC(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); - K32W_LOG("Started NFC Tag Emulation!"); - } - } -#endif -} - -void AppTask::CancelTimer() -{ - if (xTimerStop(sFunctionTimer, 0) == pdFAIL) - { - K32W_LOG("app timer stop() failed"); - } - - mResetTimerActive = false; -} - -void AppTask::StartTimer(uint32_t aTimeoutInMs) -{ - if (xTimerIsTimerActive(sFunctionTimer)) - { - K32W_LOG("app timer already started!"); - CancelTimer(); - } - - // timer is not active, change its period to required value (== restart). - // FreeRTOS- Block for a maximum of 100 ticks if the change period command - // cannot immediately be sent to the timer command queue. - if (xTimerChangePeriod(sFunctionTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS) - { - K32W_LOG("app timer start() failed"); - } - - mResetTimerActive = true; -} - -void AppTask::ActionInitiated(BoltLockManager::Action_t aAction, int32_t aActor) -{ - // If the action has been initiated by the lock, update the bolt lock trait - // and start flashing the LEDs rapidly to indicate action initiation. - if (aAction == BoltLockManager::LOCK_ACTION) - { - K32W_LOG("Lock Action has been initiated") - } - else if (aAction == BoltLockManager::UNLOCK_ACTION) - { - K32W_LOG("Unlock Action has been initiated") - } - - if (aActor == AppEvent::kEventType_Button) - { - sAppTask.mSyncClusterToButtonAction = true; - } - - sAppTask.mFunction = kFunctionLockUnlock; - -#if !defined(chip_with_low_power) || (chip_with_low_power == 0) - sLockLED.Blink(50, 50); -#endif -} - -void AppTask::ActionCompleted(BoltLockManager::Action_t aAction) -{ - // if the action has been completed by the lock, update the bolt lock trait. - // Turn on the lock LED if in a LOCKED state OR - // Turn off the lock LED if in an UNLOCKED state. - if (aAction == BoltLockManager::LOCK_ACTION) - { - K32W_LOG("Lock Action has been completed") -#if !defined(chip_with_low_power) || (chip_with_low_power == 0) - sLockLED.Set(true); -#endif - } - else if (aAction == BoltLockManager::UNLOCK_ACTION) - { - K32W_LOG("Unlock Action has been completed") -#if !defined(chip_with_low_power) || (chip_with_low_power == 0) - sLockLED.Set(false); -#endif - } - - if (sAppTask.mSyncClusterToButtonAction) - { - sAppTask.UpdateClusterState(); - sAppTask.mSyncClusterToButtonAction = false; - } - - sAppTask.mFunction = kFunction_NoneSelected; -} - -void AppTask::PostLockActionRequest(int32_t aActor, BoltLockManager::Action_t aAction) -{ - AppEvent event; - event.Type = AppEvent::kEventType_Lock; - event.LockEvent.Actor = aActor; - event.LockEvent.Action = aAction; - event.Handler = LockActionEventHandler; - PostEvent(&event); -} - -void AppTask::PostEvent(const AppEvent * aEvent) -{ - if (sAppEventQueue != NULL) - { - if (!xQueueSend(sAppEventQueue, aEvent, 0)) - { - K32W_LOG("Failed to post event to app task event queue"); - } - } -} - -void AppTask::DispatchEvent(AppEvent * aEvent) -{ -#if defined(chip_with_low_power) && (chip_with_low_power == 1) - /* specific processing for events sent from App_PostCallbackMessage (see main.cpp) */ - if (aEvent->Type == AppEvent::kEventType_Lp) - { - aEvent->Handler(aEvent->param); - } - else -#endif - - if (aEvent->Handler) - { - aEvent->Handler(aEvent); - } - else - { - K32W_LOG("Event received with no handler. Dropping event."); - } -} - -void AppTask::UpdateClusterState(void) -{ - PlatformMgr().ScheduleWork(UpdateClusterStateInternal, 0); -} -void AppTask::UpdateClusterStateInternal(intptr_t arg) -{ - using namespace chip::app::Clusters::DoorLock; - - DlLockState newValue; - if (BoltLockMgr().IsUnlocked()) - { - newValue = DlLockState::kUnlocked; - } - else - { - newValue = DlLockState::kLocked; - } - - // write the new door lock state - chip::Protocols::InteractionModel::Status status = Attributes::LockState::Set(1, newValue); - - if (status != chip::Protocols::InteractionModel::Status::Success) - { - ChipLogError(NotSpecified, "ERR: updating door lock state %x", chip::to_underlying(status)); - } -} - -extern "C" void OTAIdleActivities(void) {} diff --git a/examples/lock-app/nxp/mcxw71/.gn b/examples/lock-app/nxp/mcxw71/.gn deleted file mode 100644 index b1fc1fc77a1..00000000000 --- a/examples/lock-app/nxp/mcxw71/.gn +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2020 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") - -# The location of the build configuration file. -buildconfig = "${build_root}/config/BUILDCONFIG.gn" - -# CHIP uses angle bracket includes. -check_system_includes = true - -default_args = { - target_cpu = "arm" - target_os = "freertos" - - import("//args.gni") - - # Import default platform configs - import("${chip_root}/src/platform/nxp/mcxw71/args.gni") -} diff --git a/examples/lock-app/nxp/mcxw71/BUILD.gn b/examples/lock-app/nxp/mcxw71/BUILD.gn deleted file mode 100644 index d1df2927cd3..00000000000 --- a/examples/lock-app/nxp/mcxw71/BUILD.gn +++ /dev/null @@ -1,302 +0,0 @@ -# Copyright (c) 2021 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") -import("//build_overrides/nxp_sdk.gni") -import("//build_overrides/openthread.gni") - -import("${nxp_sdk_build_root}/nxp_sdk.gni") - -import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") - -import("${nxp_sdk_build_root}/${nxp_sdk_name}/${nxp_sdk_name}.gni") - -import("${chip_root}/src/crypto/crypto.gni") -import("${chip_root}/src/platform/device.gni") -import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") - -declare_args() { - # Setup discriminator as argument - setup_discriminator = 3840 - chip_with_diag_logs_demo = true -} - -assert(current_os == "freertos") -assert(target_os == "freertos") - -example_platform_dir = "${chip_root}/examples/platform/nxp/${nxp_platform}" -common_example_dir = "${chip_root}/examples/platform/nxp/common" -support_common_platform_dir = - "${nxp_sdk_matter_support_root}/examples/platform/common" - -mcxw71_sdk("sdk") { - defines = [] - include_dirs = [] - sources = [] - - # Indicate the path to CHIPProjectConfig.h - include_dirs += [ "include/config" ] - - # Indicate the default path to FreeRTOSConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/freeRTOS" ] - - # Indicate the default path to OpenThreadConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/openthread" ] - - # Indicate the default path to GATT database - include_dirs += [ "${support_common_platform_dir}/ble" ] - - include_dirs += [ - "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/app_common", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/components", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/dcdc", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/ext_flash", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/low_power", - ] - - sources += [ - "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples/clock_config.c", - "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples/pin_mux.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/app_common/app_services_init.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/app_common/hardware_init.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/board.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/components/board_comp.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/dcdc/board_dcdc.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/ext_flash/board_extflash.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/low_power/board_lp.c", - "${support_common_platform_dir}/ble/ble_function_mux.c", - ] - - if (is_debug) { - defines += [ "BUILD_RELEASE=0" ] - } else { - defines += [ "BUILD_RELEASE=1" ] - } - - defines += [ - "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", - ] - - if (nxp_multiple_ble_connections) { - include_dirs += [ "${example_platform_dir}/app_ble/include" ] - defines += [ - "CONFIG_CHIP_APP_EXTRA_GATT_DB_HEADER=\"extra_gatt_db.h\"", - "CONFIG_CHIP_APP_EXTRA_GATT_UUID_HEADER=\"extra_gatt_uuid128.h\"", - ] - sources += [ "${support_common_platform_dir}/ble/ble_nvm_bonding.c" ] - } -} - -mcxw71_executable("lock_app") { - output_name = "chip-mcxw71-lock-example" - - defines = [] - deps = [] - include_dirs = [] - sources = [] - - # Defines used by common code - defines += [ - "CONFIG_NET_L2_OPENTHREAD=1", - "CONFIG_NETWORK_LAYER_BLE=1", - "CONFIG_THREAD_DEVICE_TYPE=kThreadDeviceType_SleepyEndDevice", - "CONFIG_OPERATIONAL_KEYSTORE=1", - "EXTERNAL_FACTORY_DATA_PROVIDER_HEADER=\"platform/nxp/common/factory_data/legacy/FactoryDataProvider.h\"", - "CONFIG_APP_FREERTOS_OS=1", - ] - - if (chip_with_diag_logs_demo) { - defines += [ "CONFIG_DIAG_LOGS_DEMO=1" ] - } - - if (nxp_use_low_power) { - defines += [ "CONFIG_LOW_POWER=1" ] - } else { - defines += [ - "CONFIG_ENABLE_FEEDBACK=1", - "APP_QUEUE_TICKS_TO_WAIT=pdMS_TO_TICKS(10)", - ] - } - - # App common files - include_dirs += [ - "${common_example_dir}/icd/include", - "${common_example_dir}/app_task/include", - "${common_example_dir}/matter_button/include", - "${common_example_dir}/matter_cli/include", - "${common_example_dir}/clusters/include", - "${common_example_dir}/device_callbacks/include", - "${common_example_dir}/device_manager/include", - "${common_example_dir}/diagnostic_logs/include", - "${common_example_dir}/factory_data/include", - "${common_example_dir}/led_widget/include", - "${common_example_dir}/low_power/include", - "${common_example_dir}/operational_keystore/include", - "${common_example_dir}/ui_feedback/include", - "${common_example_dir}/app_ble/include", - ] - - sources += [ - "${common_example_dir}/app_task/source/AppTaskBase.cpp", - "${common_example_dir}/app_task/source/AppTaskFreeRTOS.cpp", - "${common_example_dir}/matter_button/source/ButtonApp.cpp", - "${common_example_dir}/matter_button/source/ButtonBle.cpp", - "${common_example_dir}/matter_button/source/ButtonManager.cpp", - "${common_example_dir}/matter_button/source/ButtonRegistrationAppAndBle.cpp", - "${common_example_dir}/matter_button/source/ButtonWithTimer.cpp", - - #"${common_example_dir}/clusters/source/ZclCallbacks.cpp", - "${common_example_dir}/device_callbacks/source/CommonDeviceCallbacks.cpp", - "${common_example_dir}/device_manager/source/CHIPDeviceManager.cpp", - "${common_example_dir}/icd/source/ICDUtil.cpp", - "${common_example_dir}/operational_keystore/source/OperationalKeystoreS200.cpp", - "${example_platform_dir}/factory_data/source/AppFactoryDataExample.cpp", - ] - - if (nxp_use_low_power) { - sources += [ "${common_example_dir}/low_power/source/LowPower.cpp" ] - } - - if (nxp_use_factory_data) { - # Custom factory data files can be added here - } - - if (nxp_enable_matter_cli) { - defines += [ "ENABLE_CHIP_SHELL" ] - deps += [ - "${chip_root}/examples/shell/shell_common:shell_common", - "${chip_root}/src/lib/shell:shell", - ] - sources += [ - "${common_example_dir}/matter_cli/source/AppCLIBase.cpp", - "${common_example_dir}/matter_cli/source/AppCLIFreeRTOS.cpp", - ] - } - - if (chip_enable_ota_requestor) { - defines += [ - "CONFIG_CHIP_OTA_IMAGE_PROCESSOR_HEADER=\"platform/nxp/common/ota/OTAImageProcessorImpl.h\"", - - # The status LED and the external flash CS pin are wired together. The OTA image writing may fail if used together. - "LED_MANAGER_ENABLE_STATUS_LED=0", - ] - - include_dirs += [ "${common_example_dir}/ota_requestor/include" ] - sources += [ "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorMultiImage.cpp" ] - deps += [ "${chip_root}/src/platform/nxp:nxp_ota" ] - } - - if (nxp_multiple_ble_connections) { - sources += [ - "${common_example_dir}/app_ble/source/NXPHostBLEApplicationManager.cpp", - ] - } else { - sources += [ - "${common_example_dir}/app_ble/source/BLEApplicationManagerEmpty.cpp", - ] - } - - if (chip_with_diag_logs_demo) { - sources += [ - "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsDemo.cpp", - "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp", - ] - } - - # Platform specific files - include_dirs += [ - "${example_platform_dir}/util", - "${example_platform_dir}/app/support", - "${example_platform_dir}/button", - ] - - sources += [ "${example_platform_dir}/clusters/Identify.cpp" ] - - if (chip_enable_ota_requestor) { - sources += [ "${example_platform_dir}/ota/OtaUtils.cpp" ] - } - - include_dirs += [ - "include/config", - "../common/main", - "../common/main/include", - "${chip_root}/examples/lock-app/lock-common/include", - ] - - sources += [ - "${chip_root}/examples/lock-app/lock-common/src/LockEndpoint.cpp", - "${chip_root}/examples/lock-app/lock-common/src/LockManager.cpp", - "../common/main/AppTask.cpp", - "../common/main/DeviceCallbacks.cpp", - "../common/main/ZclCallbacks.cpp", - "../common/main/main.cpp", - ] - - if (!nxp_use_low_power) { - sources += [ - "${common_example_dir}/ui_feedback/source/LedManager.cpp", - "${example_platform_dir}/util/LedOnOff.cpp", - ] - } - - deps += [ - "${chip_root}/examples/providers:device_info_provider_please_do_not_reuse_as_is", - "${chip_root}/src/app/clusters/network-commissioning:network-commissioning", - "${chip_root}/src/platform/logging:default", - "${chip_root}/src/setup_payload:onboarding-codes-utils", - ] - - deps += [ "${chip_root}/examples/lock-app/nxp/zap:zap" ] - - if (chip_openthread_ftd) { - deps += [ - "${openthread_root}:libopenthread-cli-ftd", - "${openthread_root}:libopenthread-ftd", - ] - } else { - deps += [ - "${openthread_root}:libopenthread-cli-mtd", - "${openthread_root}:libopenthread-mtd", - ] - } - - cflags = [ - "-Wconversion", - "-Wno-error=format=", - ] - - ldscript = "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples/linker/gcc/connectivity.ld" - - inputs = [ ldscript ] - - ldflags = [ - "-Wl,--defsym=__heap_size__=0", - "-Wl,--defsym=__stack_size__=0x480", - "-Wl,-print-memory-usage", - "-Wl,--no-warn-rwx-segments", - "-T" + rebase_path(ldscript, root_build_dir), - ] - - if (nxp_use_factory_data) { - ldflags += [ "-Wl,--defsym=gUseFactoryData_d=1" ] - } - - output_dir = root_out_dir -} - -group("default") { - deps = [ ":lock_app" ] -} diff --git a/examples/lock-app/nxp/mcxw71/README.md b/examples/lock-app/nxp/mcxw71/README.md deleted file mode 100644 index 237f0026f72..00000000000 --- a/examples/lock-app/nxp/mcxw71/README.md +++ /dev/null @@ -1,210 +0,0 @@ -# Matter `MCXW71` Door Lock Example Application - -For generic information related to door lock application, please see the -[common README](../README.md). - -- [Matter `MCXW71` Door Lock Example Application](#matter-mcxw71-door-lock-example-application) - - [Introduction](#introduction) - - [Device UI](#device-ui) - - [Building](#building) - - [Flashing](#flashing) - - [Flashing the `NBU` image](#flashing-the-nbu-image) - - [Flashing the host image](#flashing-the-host-image) - - [Debugging](#debugging) - - [OTA](#ota) - - [Multiple BLE connections](#multiple-ble-connections) - -## Introduction - -The following board was used when testing this Matter reference app for an -`mcxw71` device: -![FRDM-MCXW71](../../../platform/nxp/mcxw71/doc/images/frdm-mcxw71.jpg) - -## Device UI - -The state feedback is provided through LED effects: - -| widget | effect | description | -| ------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------- | -| LED2 | short flash on (50ms on/950ms off) | The device is in an unprovisioned (unpaired) state and is waiting for a commissioner to connect. | -| LED2 | rapid even flashing (100ms period) | The device is in an unprovisioned state and a commissioner is connected via BLE. | -| LED2 | short flash off (950ms on/50ms off) | The device is fully provisioned, but does not yet have full network (Thread) or service connectivity. | -| LED2 | solid on | The device is fully provisioned and has full network and service connectivity. | -| RGB LED | on | The `LockState` attribute of the `DoorLock` cluster is `Unlocked`. | -| RGB LED | off | The `LockState` attribute of the `DoorLock` cluster is `Locked`. | - -NOTE: `LED2` will be disabled when OTA is used. On `MCXW71` board, `PTB0` is -wired to both `LED2` and CS (Chip Select) of the External Flash Memory. Since -the OTA image is stored in external memory, `LED2` operations will affect OTA -operation by corrupting packages and OTA will not work. - -The user actions are summarized below: - -| button | action | state | output | -| ------ | ----------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| SW2 | short press | not commissioned | Enable BLE advertising | -| SW2 | short press | commissioned + device is LIT | Enable Active Mode | -| SW2 | long press | NA | Initiate a factory reset (can be cancelled by pressing the button again within the factory reset timeout limit - 6 seconds by default) | -| SW3 | short press | NA | Toggle attribute `LockState` value | -| SW3 | long press | NA | Clean soft reset of the device (takes into account proper Matter shutdown procedure) | - -## Building - -Manually building requires running the following commands: - -``` -user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/lock-app/nxp/mcxw71 -user@ubuntu:~/Desktop/git/connectedhomeip/examples/lock-app/nxp/mcxw71$ gn gen out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/lock-app/nxp/mcxw71$ ninja -C out/debug -``` - -Please note that running `gn gen out/debug` without `--args` option will use the -default gn args values found in `args.gni`. - -After a successful build, the `elf` and `srec` files are found in `out/debug/`. -See the files prefixed with `chip-mcxw71-lock-example`. - -## Flashing - -Two images must be written to the board: one for the host (CM33) and one for the -`NBU` (CM3). - -The image needed on the host side is the one generated in `out/debug/` while the -one needed on the `NBU` side can be found in the downloaded NXP-SDK package at -path - -`middleware\wireless\ieee-802.15.4\bin\k32w1_mcxw71\k32w1_mcxw71_nbu_ble_15_4_dyn_matter.sb3`. - -### Flashing the `NBU` image - -`NBU` image should be written only when a new NXP SDK is released. - -1. Install - [Secure Provisioning SDK tool](https://www.nxp.com/design/design-center/software/development-software/secure-provisioning-sdk-spsdk:SPSDK) - using Python: - - ``` - pip install spsdk - ``` - - Note: There might be some dependencies that cause conflicts with already - installed Python modules. However, `blhost` tool is still installed and can - be used. - -2. Updating `NBU` for Wireless examples - - It is necessary to work with the matching `NBU` image for the SDK version of - the application you are working with. This means that when you download your - SDK, prior to loading any wireless SDK example, update your `NBU` image with - the SDK provided binaries. For `FRDM` users, please write the following - binary: - - `middleware\wireless\ieee-802.15.4\bin\mcxw71\mcxw71_nbu_ble_15_4_dyn_matter_.sb3` - - Please note that `` may vary depending on the SDK version. - - 1. Place your device in `ISP` mode. - - - Make sure a jumper is placed on `JP25` - - Press and hold `SW4`, press and release Reset, then release `SW4` - - 2. Once the device is connected, you may find the assigned port by running: - - ``` - nxpdevscan - ``` - - 3. Run the `blhost` command to write the `sb3` file: - - ``` - blhost -p receive-sb-file \middleware\wireless\ieee-802.15.4\bin\mcxw71\mcxw71_nbu_ble_15_4_dyn_matter_.sb3 - ``` - -### Flashing the host image - -Host image is the one found under `out/debug/`. It should be written after each -build process. - -If debugging is needed then jump directly to the [Debugging](#debugging) -section. Otherwise, if only flashing is needed then -[JLink 7.84b or greater](https://www.segger.com/downloads/jlink/) can be used: - -- Plug `MCXW71` to the USB port (no need to keep the `SW4` button pressed - while doing this, e.g. ISP mode is not needed for host flashing) - -- Connect JLink to the device: - - ```bash - JLinkExe -device MCXW71 -if SWD -speed 4000 -autoconnect 1 - ``` - -- Run the following commands: - ```bash - reset - halt - loadfile chip-mcxw71-lock-example.srec - reset - go - quit - ``` - -## Debugging - -One option for debugging would be to use MCUXpresso IDE. - -- Drag-and-drop the zip file containing the NXP SDK in the "Installed SDKs" - tab: - -![Installed SDKs](../../../platform/nxp/mcxw71/doc/images/mcxw71_installed_sdks.jpg) - -- Import any demo application from the installed SDK: - -``` -Import SDK example(s).. -> choose a demo app (demo_apps -> hello_world) -> Finish -``` - -![Import demo](../../../platform/nxp/mcxw71/doc/images/import_demo.jpg) - -- Flash the previously imported demo application on the board: - -``` -Right click on the application (from Project Explorer) -> Debug as -> JLink/CMSIS-DAP -``` - -After this step, a debug configuration specific for the `MCXW71` board was -created. This debug configuration will be used later on for debugging the -application resulted after ot-nxp compilation. - -- Import Matter repo in MCUXpresso IDE as Makefile Project. Use _none_ as - _Toolchain for Indexer Settings_: - -``` -File -> Import -> C/C++ -> Existing Code as Makefile Project -``` - -![New Project](../../../platform/nxp/mcxw71/doc/images/new_project.jpg) - -- Replace the path of the existing demo application with the path of the - `MCXW71` application: - -``` -Run -> Debug Configurations... -> C/C++ Application -``` - -![Debug MCXW71](../../../platform/nxp/mcxw71/doc/images/mcxw71_debug.jpg) - -## OTA - -Please see -[mcxw71 OTA guide](../../../../docs/platforms/nxp/nxp_mcxw71_ota_guide.md). - -## Multiple BLE connections - -To compile with the Multiple BLE connections support demo example add the gn -argument `nxp_multiple_ble_connections=true`. - -The application will accept multiple BLE connections after commissioning, by -pressing the BLE advertise button again. Once discovered by a BLE central, a -custom GATT service will be visible on the device. - -The user can change the default behavior by implementing the class defined in -[BLEApplicationManager.h](../../../platform/nxp/common/app_ble/include/BLEApplicationManager.h) diff --git a/examples/lock-app/nxp/mcxw71/args.gni b/examples/lock-app/nxp/mcxw71/args.gni deleted file mode 100644 index 31c27f5b047..00000000000 --- a/examples/lock-app/nxp/mcxw71/args.gni +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2020 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") -import("${chip_root}/config/standalone/args.gni") - -# SDK target. This is overridden to add our SDK app_config.h & defines. -nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") -nxp_device = "MCXW716C" -nxp_board = "frdmmcxw71" - -chip_enable_ota_requestor = true -chip_stack_lock_tracking = "fatal" -chip_enable_ble = true -chip_generate_link_map_file = true - -chip_system_config_provide_statistics = false -chip_system_config_use_openthread_inet_endpoints = true -chip_with_lwip = false - -chip_enable_icd_server = true -chip_enable_icd_lit = false -chip_persist_subscriptions = true -chip_subscription_timeout_resumption = true - -is_debug = false - -chip_crypto = "platform" -chip_openthread_ftd = false -nxp_enable_ot_cli = false - -chip_with_diag_logs_demo = true -nxp_use_low_power = false diff --git a/examples/lock-app/nxp/mcxw71/build_overrides b/examples/lock-app/nxp/mcxw71/build_overrides deleted file mode 120000 index ee19c065d61..00000000000 --- a/examples/lock-app/nxp/mcxw71/build_overrides +++ /dev/null @@ -1 +0,0 @@ -../../../build_overrides/ \ No newline at end of file diff --git a/examples/lock-app/nxp/mcxw71/include/config/AppConfig.h b/examples/lock-app/nxp/mcxw71/include/config/AppConfig.h deleted file mode 100644 index 89f4bf9333c..00000000000 --- a/examples/lock-app/nxp/mcxw71/include/config/AppConfig.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 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 - -/* ---- App Config ---- */ - -/* ---- Button Manager Config ---- */ -#define BUTTON_MANAGER_FACTORY_RESET_TIMEOUT_MS 6000 - -/* ---- LED Manager Config ---- */ -#define LED_MANAGER_STATUS_LED_INDEX 0 -#define LED_MANAGER_LIGHT_LED_INDEX 1 diff --git a/examples/lock-app/nxp/mcxw71/include/config/CHIPProjectConfig.h b/examples/lock-app/nxp/mcxw71/include/config/CHIPProjectConfig.h deleted file mode 100644 index cc7255da75b..00000000000 --- a/examples/lock-app/nxp/mcxw71/include/config/CHIPProjectConfig.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2020 Google LLC. - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Example project configuration file for CHIP. - * - * This is a place to put application or project-specific overrides - * to the default configuration values for general CHIP features. - * - */ - -#pragma once - -// Use hard-coded test certificates already embedded in generic chip code => set it to 0 -// Use real/development certificates => set it to 1 + file the provisioning section from -// the internal flash -#ifndef CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -#define CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA 0 -#endif - -#if CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA - -// VID/PID for product => will be used by Basic Information Cluster -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0x1037 -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0xA401 - -// Set the following define to use the Certification Declaration from below and not use it stored in factory data section -#ifndef CHIP_USE_DEVICE_CONFIG_CERTIFICATION_DECLARATION -#define CHIP_USE_DEVICE_CONFIG_CERTIFICATION_DECLARATION 0 -#endif - -#ifndef CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION -//-> format_version = 1 -//-> vendor_id = 0x1037 -//-> product_id_array = [ 0xA401 ] -//-> device_type_id = 0x0100 -//-> certificate_id = "ZIG20142ZB330003-24" -//-> security_level = 0 -//-> security_information = 0 -//-> version_number = 0x2694 -//-> certification_type = 1 -//-> dac_origin_vendor_id is not present -//-> dac_origin_product_id is not present -#define CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION \ - { \ - 0x30, 0x81, 0xe8, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x81, 0xda, 0x30, 0x81, 0xd7, \ - 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, \ - 0x44, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x37, 0x04, 0x35, 0x15, 0x24, 0x00, \ - 0x01, 0x25, 0x01, 0x37, 0x10, 0x36, 0x02, 0x05, 0x01, 0xa4, 0x18, 0x24, 0x03, 0x0a, 0x2c, 0x04, 0x13, 0x5a, 0x49, \ - 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x34, 0x24, 0x05, \ - 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x76, 0x98, 0x24, 0x08, 0x01, 0x18, 0x31, 0x7d, 0x30, 0x7b, 0x02, 0x01, 0x03, \ - 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04, \ - 0xf3, 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0a, 0x06, \ - 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xca, 0x6f, 0xf9, \ - 0xae, 0x3b, 0x2f, 0xc1, 0xf4, 0x07, 0x8f, 0x6d, 0x6e, 0x3b, 0x99, 0xff, 0x98, 0x18, 0x6b, 0x6b, 0xed, 0xa0, 0x27, \ - 0x88, 0xa4, 0x09, 0xc2, 0x0f, 0xc5, 0xa3, 0x21, 0xc2, 0x15, 0x02, 0x20, 0x67, 0x5a, 0xef, 0xe3, 0x0c, 0xcc, 0x9f, \ - 0xcb, 0x1e, 0x45, 0xe1, 0x20, 0xf2, 0xf1, 0x14, 0x19, 0x49, 0xf7, 0x2b, 0xdd, 0x34, 0x85, 0x16, 0xbd, 0x88, 0x9c, \ - 0xc8, 0xac, 0xd0, 0x70, 0x9e, 0x05 \ - } - -// All remaining data will be pulled from the provisioning region of flash. -#endif - -#else - -/** - * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID - * - * 0xFFF1: Test vendor. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1 - -/** - * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID - * - */ -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8005 - -// Use a default setup PIN code if one hasn't been provisioned in flash. -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 -#endif - -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 -#endif - -// Use a default pairing code if one hasn't been provisioned in flash. -#define CHIP_DEVICE_CONFIG_USE_TEST_PAIRING_CODE "CHIPUS" - -/** - * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER - * - * Enables the use of a hard-coded default serial number if none - * is found in CHIP NV storage. - */ -#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN" - -#endif // CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA - -/** - * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION - * - * The hardware version number assigned to device or product by the device vendor. This - * number is scoped to the device product id, and typically corresponds to a revision of the - * physical device, a change to its packaging, and/or a change to its marketing presentation. - * This value is generally *not* incremented for device software versions. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 100 - -#ifndef CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING "v0.1.0" -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING - * - * A string identifying the software version running on the device. - * CHIP currently expects the software version to be in the format - * {MAJOR_VERSION}.0d{MINOR_VERSION} - */ -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION NXP_CONFIG_DEVICE_SOFTWARE_VERSION -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "NXP Semiconductors" -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "NXP Demo App" -#endif - -/** - * CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_TIMEOUT - * - * The amount of time in miliseconds after which BLE should change his advertisements - * from fast interval to slow interval. - * - * 30000 (30 secondes). - */ -#define CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_TIMEOUT (30 * 1000) - -/** - * CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT - * - * The amount of time in miliseconds after which BLE advertisement should be disabled, counting - * from the moment of slow advertisement commencement. - * - * Defaults to 9000000 (15 minutes). - */ -#define CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT (15 * 60 * 1000) - -/** - * CONFIG_CHIP_NFC_ONBOARDING_PAYLOAD, CHIP_DEVICE_CONFIG_ENABLE_NFC_ONBOARDING_PAYLOAD - * - * NFC onboarding payload is not supporte - */ -#define CONFIG_CHIP_NFC_ONBOARDING_PAYLOAD 0 -#define CHIP_DEVICE_CONFIG_ENABLE_NFC_ONBOARDING_PAYLOAD 0 - -/** - * @def CHIP_CONFIG_MAX_FABRICS - * - * @brief - * Maximum number of fabrics the device can participate in. Each fabric can - * provision the device with its unique operational credentials and manage - * its own access control lists. - */ -#define CHIP_CONFIG_MAX_FABRICS 5 // 5 is the minimum number of supported fabrics - -#define CHIP_DEVICE_CONFIG_ENABLE_SED 1 - -/** - * @def CHIP_DEVICE_CONFIG_KVS_WEAR_STATS - * - * @brief Toggle support for key value store wear stats on or off. - */ -#define CHIP_DEVICE_CONFIG_KVS_WEAR_STATS 0 - -/** - * @def CHIP_IM_MAX_NUM_COMMAND_HANDLER - * - * @brief Defines the maximum number of CommandHandler, limits the number of active commands transactions on server. - */ -#define CHIP_IM_MAX_NUM_COMMAND_HANDLER 2 - -/** - * @def CHIP_IM_MAX_NUM_WRITE_HANDLER - * - * @brief Defines the maximum number of WriteHandler, limits the number of active write transactions on server. - */ -#define CHIP_IM_MAX_NUM_WRITE_HANDLER 2 - -/** - * CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE - * - * For a development build, set the default importance of events to be logged as Debug. - * Since debug is the lowest importance level, this means all standard, critical, info and - * debug importance level vi events get logged. - */ -#if BUILD_RELEASE -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Production -#else -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug -#endif // BUILD_RELEASE - -#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1 - -#if CONFIG_DIAG_LOGS_DEMO -#define CHIP_CONFIG_ENABLE_BDX_LOG_TRANSFER 1 -#define CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE 1024 -#endif - -// Enable `Extension` attribute of ACL Cluster as required by door locks -#define CHIP_CONFIG_ENABLE_ACL_EXTENSIONS 1 diff --git a/examples/lock-app/nxp/mcxw71/third_party/connectedhomeip b/examples/lock-app/nxp/mcxw71/third_party/connectedhomeip deleted file mode 120000 index 59307833b4f..00000000000 --- a/examples/lock-app/nxp/mcxw71/third_party/connectedhomeip +++ /dev/null @@ -1 +0,0 @@ -../../../../.. \ No newline at end of file diff --git a/examples/lock-app/nxp/mcxw72/.gn b/examples/lock-app/nxp/mcxw72/.gn deleted file mode 100644 index 365c97cf355..00000000000 --- a/examples/lock-app/nxp/mcxw72/.gn +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2020-2024 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") - -# The location of the build configuration file. -buildconfig = "${build_root}/config/BUILDCONFIG.gn" - -# CHIP uses angle bracket includes. -check_system_includes = true - -default_args = { - target_cpu = "arm" - target_os = "freertos" - - import("//args.gni") - - # Import default platform configs - import("${chip_root}/src/platform/nxp/mcxw72/args.gni") -} diff --git a/examples/lock-app/nxp/mcxw72/BUILD.gn b/examples/lock-app/nxp/mcxw72/BUILD.gn deleted file mode 100644 index 5d2a0fcd8c4..00000000000 --- a/examples/lock-app/nxp/mcxw72/BUILD.gn +++ /dev/null @@ -1,297 +0,0 @@ -# Copyright (c) 2021 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") -import("//build_overrides/nxp_sdk.gni") -import("//build_overrides/openthread.gni") - -import("${nxp_sdk_build_root}/nxp_sdk.gni") - -import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") - -import("${nxp_sdk_build_root}/${nxp_sdk_name}/${nxp_sdk_name}.gni") - -import("${chip_root}/src/crypto/crypto.gni") -import("${chip_root}/src/platform/device.gni") -import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") - -declare_args() { - # Setup discriminator as argument - setup_discriminator = 3840 - chip_with_diag_logs_demo = true -} - -assert(current_os == "freertos") -assert(target_os == "freertos") - -example_platform_dir = - "${nxp_sdk_matter_support_root}/examples/platform/${nxp_platform}" -common_example_dir = "${chip_root}/examples/platform/nxp/common" -support_common_platform_dir = - "${nxp_sdk_matter_support_root}/examples/platform/common" - -mcxw72_sdk("sdk") { - defines = [] - include_dirs = [] - sources = [] - - # Indicate the path to CHIPProjectConfig.h - include_dirs += [ "include/config" ] - - # Indicate the default path to FreeRTOSConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/freeRTOS" ] - - # Indicate the default path to OpenThreadConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/openthread" ] - - # Indicate the default path to GATT database - include_dirs += [ "${support_common_platform_dir}/ble" ] - - include_dirs += [ - "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/app_common", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/components", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/dcdc", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/ext_flash", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/low_power", - ] - - sources += [ - "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples/clock_config.c", - "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples/pin_mux.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/app_common/app_services_init.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/app_common/hardware_init.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/board.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/components/board_comp.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/dcdc/board_dcdc.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/ext_flash/board_extflash.c", - "${nxp_sdk_root}/examples/_common/project_segments/wireless/wireless_mcu/low_power/board_lp.c", - "${support_common_platform_dir}/ble/ble_function_mux.c", - ] - - if (is_debug) { - defines += [ "BUILD_RELEASE=0" ] - } else { - defines += [ "BUILD_RELEASE=1" ] - } - - defines += [ - "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", - ] - - if (nxp_enable_matter_cli) { - defines += [ "gAppUseSerialManager_c=1" ] - } - - if (nxp_multiple_ble_connections) { - include_dirs += [ "${common_example_dir}/../mcxw71/app_ble/include" ] - defines += [ - "EXTRA_GATT_DB_HEADER=\"extra_gatt_db.h\"", - "EXTRA_GATT_UUID_HEADER=\"extra_gatt_uuid128.h\"", - ] - } -} - -mcxw72_executable("lock_app") { - output_name = "chip-mcxw72-lock-example" - - defines = [] - deps = [] - sources = [] - include_dirs = [] - - # Defines used by common code - defines += [ - "CONFIG_NET_L2_OPENTHREAD=1", - "CONFIG_NETWORK_LAYER_BLE=1", - "CONFIG_THREAD_DEVICE_TYPE=kThreadDeviceType_SleepyEndDevice", - "CONFIG_APP_FREERTOS_OS=1", - "EXTERNAL_FACTORY_DATA_PROVIDER_HEADER=\"platform/nxp/common/factory_data/legacy/FactoryDataProvider.h\"", - ] - - if (chip_with_diag_logs_demo) { - defines += [ "CONFIG_DIAG_LOGS_DEMO=1" ] - } - - if (nxp_use_low_power) { - defines += [ "CONFIG_LOW_POWER=1" ] - } else { - defines += [ - "CONFIG_ENABLE_FEEDBACK=1", - "LED_MANAGER_ENABLE_STATUS_LED=1", - "APP_QUEUE_TICKS_TO_WAIT=pdMS_TO_TICKS(10)", - ] - } - - # App common files - include_dirs += [ - "${common_example_dir}/icd/include", - "${common_example_dir}/app_task/include", - "${common_example_dir}/matter_button/include", - "${common_example_dir}/clusters/include", - "${common_example_dir}/device_callbacks/include", - "${common_example_dir}/device_manager/include", - "${common_example_dir}/diagnostic_logs/include", - "${common_example_dir}/factory_data/include", - "${common_example_dir}/led_widget/include", - "${common_example_dir}/matter_cli/include", - "${common_example_dir}/operational_keystore/include", - "${common_example_dir}/ui_feedback/include", - "${common_example_dir}/app_ble/include", - "${common_example_dir}/low_power/include", - "${support_common_platform_dir}/low_power", - ] - - sources += [ - "${common_example_dir}/../mcxw71/clusters/Identify.cpp", - "${common_example_dir}/app_task/source/AppTaskBase.cpp", - "${common_example_dir}/app_task/source/AppTaskFreeRTOS.cpp", - "${common_example_dir}/device_callbacks/source/CommonDeviceCallbacks.cpp", - "${common_example_dir}/device_manager/source/CHIPDeviceManager.cpp", - "${common_example_dir}/factory_data/source/AppFactoryDataDefaultImpl.cpp", - "${common_example_dir}/icd/source/ICDUtil.cpp", - "${common_example_dir}/matter_button/source/ButtonApp.cpp", - "${common_example_dir}/matter_button/source/ButtonBle.cpp", - "${common_example_dir}/matter_button/source/ButtonManager.cpp", - "${common_example_dir}/matter_button/source/ButtonRegistrationAppAndBle.cpp", - "${common_example_dir}/matter_button/source/ButtonWithTimer.cpp", - ] - - if (nxp_use_low_power) { - sources += [ - "${common_example_dir}/low_power/source/LowPower.cpp", - "${support_common_platform_dir}/low_power/freertos_lp_hooks.c", - ] - } - - if (nxp_enable_matter_cli) { - defines += [ "ENABLE_CHIP_SHELL" ] - deps += [ - "${chip_root}/examples/shell/shell_common:shell_common", - "${chip_root}/src/lib/shell:shell", - ] - sources += [ - "${common_example_dir}/matter_cli/source/AppCLIBase.cpp", - "${common_example_dir}/matter_cli/source/AppCLIFreeRTOS.cpp", - ] - } - - if (chip_enable_ota_requestor) { - defines += [ "CONFIG_CHIP_OTA_IMAGE_PROCESSOR_HEADER=\"platform/nxp/common/ota/OTAImageProcessorImpl.h\"" ] - include_dirs += [ "${common_example_dir}/ota_requestor/include" ] - sources += [ - "${common_example_dir}/../mcxw71/ota/OtaUtils.cpp", - "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorMultiImage.cpp", - ] - deps += [ "${chip_root}/src/platform/nxp:nxp_ota" ] - } - - if (nxp_multiple_ble_connections) { - sources += [ "${common_example_dir}/../mcxw71/app_ble/source/BLEApplicationManager.cpp" ] - } else { - sources += [ - "${common_example_dir}/app_ble/source/BLEApplicationManagerEmpty.cpp", - ] - } - - if (chip_with_diag_logs_demo) { - sources += [ - "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsDemo.cpp", - "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp", - ] - } - - # Platform specific files - if (chip_crypto == "platform") { - defines += [ "CONFIG_OPERATIONAL_KEYSTORE=1" ] - sources += [ "${common_example_dir}/operational_keystore/source/OperationalKeystoreS200.cpp" ] - } - - if (nxp_use_factory_data) { - # Custom factory data files can be added here - } - - include_dirs += [ - "include/config", - "../common/main", - "../common/main/include", - "${chip_root}/examples/lock-app/lock-common/include", - "${common_example_dir}/../mcxw71/util", - "${common_example_dir}/../mcxw71/app/support", - "${common_example_dir}/../mcxw71/button", - ] - - sources += [ - "${chip_root}/examples/lock-app/lock-common/src/LockEndpoint.cpp", - "${chip_root}/examples/lock-app/lock-common/src/LockManager.cpp", - "../common/main/AppTask.cpp", - "../common/main/DeviceCallbacks.cpp", - "../common/main/ZclCallbacks.cpp", - "../common/main/main.cpp", - ] - - if (!nxp_use_low_power) { - sources += [ - "${common_example_dir}/../mcxw71/util/LedOnOff.cpp", - "${common_example_dir}/ui_feedback/source/LedManager.cpp", - ] - } - - deps += [ - "${chip_root}/examples/providers:device_info_provider_please_do_not_reuse_as_is", - "${chip_root}/src/platform/logging:default", - "${chip_root}/src/setup_payload:onboarding-codes-utils", - ] - - deps += [ "${chip_root}/examples/lock-app/nxp/zap:zap" ] - - if (chip_openthread_ftd) { - deps += [ - "${openthread_root}:libopenthread-cli-ftd", - "${openthread_root}:libopenthread-ftd", - ] - } else { - deps += [ - "${openthread_root}:libopenthread-cli-mtd", - "${openthread_root}:libopenthread-mtd", - ] - } - - cflags = [ - "-Wconversion", - "-Wno-error=format=", - ] - - ldscript = "${nxp_sdk_root}/examples/_boards/${nxp_board}/wireless_examples/linker/gcc/connectivity.ld" - - inputs = [ ldscript ] - - ldflags = [ - "-Wl,--defsym=__heap_size__=0", - "-Wl,--defsym=__stack_size__=0x480", - "-Wl,--defsym=lp_ram_lower_limit=0x04000000", - "-Wl,--defsym=lp_ram_upper_limit=0x2001C000", - "-Wl,-print-memory-usage", - "-Wl,--no-warn-rwx-segments", - "-Wl,--defsym=gUseNVMLink_d=1", - "-T" + rebase_path(ldscript, root_build_dir), - ] - - output_dir = root_out_dir -} - -group("default") { - deps = [ ":lock_app" ] -} diff --git a/examples/lock-app/nxp/mcxw72/README.md b/examples/lock-app/nxp/mcxw72/README.md deleted file mode 100644 index 3d95e163637..00000000000 --- a/examples/lock-app/nxp/mcxw72/README.md +++ /dev/null @@ -1,226 +0,0 @@ -# Matter `MCXW72` Door Lock Example Application - -For generic information related to door lock application, please see the -[common README](../README.md). - -- [Matter `MCXW72` Door Lock Example Application](#matter-mcxw72-door-lock-example-application) - - [Introduction](#introduction) - - [Device UI](#device-ui) - - [Configure `matter-cli`](#configure-matter-cli) - - [Building](#building) - - [Flashing](#flashing) - - [Flashing the `NBU` image with `blhost`](#flashing-the-nbu-image-with-blhost) - - [Flashing the `NBU` image with `JLink`](#flashing-the-nbu-image-with-jlink) - - [Flashing the host image](#flashing-the-host-image) - - [Factory data](#factory-data) - - [OTA](#ota) - - [Multiple BLE connections](#multiple-ble-connections) - -## Introduction - -This is a door lock application implemented for an `mcxw72` device. - -The following board was used when testing this Matter reference app for a -`mcxw72` device: - -![MCXW72-EVK](../../../platform/nxp/mcxw72/doc/images/mcxw72evk.png) - -Please see -[`MCXW72` product page](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/mcx-arm-cortex-m/mcx-w-series-microcontrollers/mcx-w72x-secure-and-ultra-low-power-mcus-for-matter-thread-zigbee-and-bluetooth-le:MCX-W72X) -for more information. - -## Device UI - -This reference app is using `matter-cli` to send commands to the board through a -UART interface. - -| interface | role | -| --------- | ---------------------------------- | -| UART0 | Used for logs | -| UART1 | Used for `matter-cli` and flashing | - -The user actions are summarized below: - -| matter-cli command | output | -| ------------------------- | ------------------------ | -| `mattercommissioning on` | Enable BLE advertising | -| `mattercommissioning off` | Disable BLE advertising | -| `matterfactoryreset` | Initiate a factory reset | -| `matterreset` | Reset the device | - -### Additional UART interface - -You need a `USB-UART` bridge to make use of the second UART interface. The pin -configuration is the following: - -- `JP11 pin 1` (UART0 TX) -- `JP12 pin 1` (UART0 RX) -- `J11 pin 4` (GND) - -The state feedback is also provided through LED effects: - -| widget | effect | description | -| ------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------- | -| LED2 | short flash on (50ms on/950ms off) | The device is in an unprovisioned (unpaired) state and is waiting for a commissioner to connect. | -| LED2 | rapid even flashing (100ms period) | The device is in an unprovisioned state and a commissioner is connected via BLE. | -| LED2 | short flash off (950ms on/50ms off) | The device is fully provisioned, but does not yet have full network (Thread) or service connectivity. | -| LED2 | solid on | The device is fully provisioned and has full network and service connectivity. | -| RGB LED | on | The `LockState` attribute of the `DoorLock` cluster is `Unlocked`. | -| RGB LED | off | The `LockState` attribute of the `DoorLock` cluster is `Locked`. | - -The user actions are summarized below: - -| button | action | state | output | -| ------ | ----------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| SW2 | short press | not commissioned | Enable BLE advertising | -| SW2 | long press | NA | Initiate a factory reset (can be cancelled by pressing the button again within the factory reset timeout limit - 6 seconds by default) | -| SW3 | short press | NA | Toggle attribute `LockState` value | -| SW3 | long press | NA | Clean soft reset of the device (takes into account proper Matter shutdown procedure) | - -## Building - -Manually building requires running the following commands: - -``` -user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_SDK_ROOT= -user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/lock-app/nxp/mcxw72 -user@ubuntu:~/Desktop/git/connectedhomeip/examples/lock-app/nxp/mcxw72$ gn gen out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/lock-app/nxp/mcxw72$ ninja -C out/debug -``` - -Please note that running `gn gen out/debug` without `--args` option will use the -default gn args values found in `args.gni`. - -After a successful build, the `elf` and `srec` files are found in `out/debug/`. -See the files prefixed with `chip-mcxw72-lock-example`. - -## Flashing - -We recommend using [JLink](https://www.segger.com/downloads/jlink/) to flash -both host and `NBU` cores. To support this device, a `JLink` patch shall be -applied, so please contact your NXP liaison for guidance. - -| core | JLink target | -| ----- | ------------------ | -| host | `KW47B42ZB7_M33_0` | -| `NBU` | `KW47B42ZB7_M33_1` | - -Note: `NBU` image should be written only when a new NXP SDK is released. - -### Flashing the `NBU` image with `blhost` - -1. Install - [Secure Provisioning SDK tool](https://www.nxp.com/design/design-center/software/development-software/secure-provisioning-sdk-spsdk:SPSDK) - using Python: - - ``` - pip install spsdk - ``` - - Note: There might be some dependencies that cause conflicts with already - installed Python modules. However, `blhost` tool is still installed and can - be used. - -2. Updating `NBU` Firmware for Wireless examples - - It is necessary to work with the matching `NBU` image for the SDK version of - the application you are working with. This means that when you download your - SDK, prior to loading any wireless SDK example, update your `NBU` image with - the SDK provided binaries: - - `middleware\wireless\ieee-802.15.4\bin\mcxw72\mcxw72_nbu_ble_15_4_dyn.bin` - - 1. Place your device in `ISP` mode: - - - Press and hold `SW4` (`BOOT_CONFIG`) - - Press and hold `SW1` (`RST`) - - Relax `SW1` - - Relax `SW4` - - 2. Once the device is connected, you may find the assigned port by running: - - ``` - nxpdevscan - ``` - - 3. Run the `blhost` command to write the `bin` file: - - ``` - blhost -p write-memory 0x48800000 /middleware/wireless/ieee-802.15.4/bin/mcxw72/mcxw72_nbu_ble_15_4_dyn.bin - - ``` - -### Flashing the `NBU` image with `JLink` - -Steps: - -- Plug `MCXW72-EVK` board into the USB port -- Connect JLink to the device: - ```bash - JLinkExe -device KW47B42ZB7_M33_1 -if SWD -speed 4000 -autoconnect 1 - ``` -- Run the following commands: - ```bash - reset - halt - loadbin /middleware/wireless/ieee-802.15.4/bin/mcxw72/mcxw72_nbu_ble_15_4_dyn.bin 0 - reset - go - quit - ``` - -Note: If running into issues related to board connection, please refer to -[Flashing the `NBU` image with `blhost`](#flashing-the-nbu-image-with-blhost). -This might be needed when the `NBU` core is empty. - -### Flashing the host image - -Host image is the one found under `out/debug/`. It should be written after each -build process. - -Steps: - -- Plug `MCXW72-EVK` board into the USB port -- Connect JLink to the device: - ```bash - JLinkExe -device KW47B42ZB7_M33_0 -if SWD -speed 4000 -autoconnect 1 - ``` -- Run the following commands: - ```bash - reset - halt - loadfile chip-mcxw72-lock-example.srec - reset - go - quit - ``` - -## Factory data - -Factory data is written in `IFR0, sector 1` at a predefined offset, using -`blhost`. The expanded address is `0x2002680`: - -``` -blhost --port flash-erase-region 0x2002680 -blhost --port write-memory 0x2002680 -``` - -where `` is the OS assigned port, `` the length -of factory data binary in bytes and `` the path to the factory -data binary. - -## OTA - -Please see [OTA guide](../../../../docs/guides/nxp/nxp_mcxw71_ota_guide.md). - -## Multiple BLE connections - -To compile with the Multiple BLE connections support demo example add the gn -argument `nxp_multiple_ble_connections=true`. - -The application will accept multiple BLE connections after commissioning, by -pressing the BLE advertise button again. Once discovered by a BLE central, a -custom GATT service will be visible on the device. - -The user can change the default behavior by implementing the class defined in -[BLEApplicationManager.h](../../../platform/nxp/common/app_ble/include/BLEApplicationManager.h) diff --git a/examples/lock-app/nxp/mcxw72/args.gni b/examples/lock-app/nxp/mcxw72/args.gni deleted file mode 100644 index cfcdd232cae..00000000000 --- a/examples/lock-app/nxp/mcxw72/args.gni +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2020-2024 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") -import("${chip_root}/config/standalone/args.gni") - -# SDK target. This is overridden to add our SDK app_config.h & defines. -nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") -nxp_device = "MCXW727C" -nxp_board = "mcxw72evk" - -chip_config_dimmable_led = false -chip_enable_ota_requestor = true -chip_stack_lock_tracking = "fatal" -chip_enable_ble = true -chip_generate_link_map_file = true - -chip_system_config_provide_statistics = false -chip_system_config_use_openthread_inet_endpoints = true -chip_with_lwip = false - -chip_enable_icd_server = true -chip_enable_icd_lit = false -icd_enforce_sit_slow_poll_limit = true -chip_persist_subscriptions = true -chip_subscription_timeout_resumption = true - -is_debug = false -treat_warnings_as_errors = false - -chip_crypto = "platform" -chip_openthread_ftd = false -nxp_enable_ot_cli = false diff --git a/examples/lock-app/nxp/mcxw72/build_overrides b/examples/lock-app/nxp/mcxw72/build_overrides deleted file mode 120000 index ee19c065d61..00000000000 --- a/examples/lock-app/nxp/mcxw72/build_overrides +++ /dev/null @@ -1 +0,0 @@ -../../../build_overrides/ \ No newline at end of file diff --git a/examples/lock-app/nxp/mcxw72/include/config/AppConfig.h b/examples/lock-app/nxp/mcxw72/include/config/AppConfig.h deleted file mode 100644 index 89f4bf9333c..00000000000 --- a/examples/lock-app/nxp/mcxw72/include/config/AppConfig.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 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 - -/* ---- App Config ---- */ - -/* ---- Button Manager Config ---- */ -#define BUTTON_MANAGER_FACTORY_RESET_TIMEOUT_MS 6000 - -/* ---- LED Manager Config ---- */ -#define LED_MANAGER_STATUS_LED_INDEX 0 -#define LED_MANAGER_LIGHT_LED_INDEX 1 diff --git a/examples/lock-app/nxp/mcxw72/include/config/CHIPProjectConfig.h b/examples/lock-app/nxp/mcxw72/include/config/CHIPProjectConfig.h deleted file mode 100644 index 4183f835e37..00000000000 --- a/examples/lock-app/nxp/mcxw72/include/config/CHIPProjectConfig.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2020 Google LLC. - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Example project configuration file for CHIP. - * - * This is a place to put application or project-specific overrides - * to the default configuration values for general CHIP features. - * - */ - -#pragma once - -// Use hard-coded test certificates already embedded in generic chip code => set it to 0 -// Use real/development certificates => set it to 1 + file the provisioning section from -// the internal flash -#ifndef CONFIG_CHIP_LOAD_REAL_FACTORY_DATA -#define CONFIG_CHIP_LOAD_REAL_FACTORY_DATA 0 -#endif - -#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA - -// VID/PID for product => will be used by Basic Information Cluster -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0x1037 -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0xA401 - -// Set the following define to use the Certification Declaration from below and not use it stored in factory data section -#ifndef CHIP_USE_DEVICE_CONFIG_CERTIFICATION_DECLARATION -#define CHIP_USE_DEVICE_CONFIG_CERTIFICATION_DECLARATION 0 -#endif - -#ifndef CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION -//-> format_version = 1 -//-> vendor_id = 0x1037 -//-> product_id_array = [ 0xA401 ] -//-> device_type_id = 0x000A -//-> certificate_id = "ZIG20142ZB330003-24" -//-> security_level = 0 -//-> security_information = 0 -//-> version_number = 0x2694 -//-> certification_type = 1 -//-> dac_origin_vendor_id is not present -//-> dac_origin_product_id is not present -#define CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION \ - { \ - 0x30, 0x81, 0xe8, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x81, 0xda, 0x30, 0x81, 0xd7, \ - 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, \ - 0x44, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x37, 0x04, 0x35, 0x15, 0x24, 0x00, \ - 0x01, 0x25, 0x01, 0x37, 0x10, 0x36, 0x02, 0x05, 0x21, 0xa2, 0x18, 0x24, 0x03, 0x0a, 0x2c, 0x04, 0x13, 0x5a, 0x49, \ - 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x34, 0x24, 0x05, \ - 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x76, 0x98, 0x24, 0x08, 0x01, 0x18, 0x31, 0x7d, 0x30, 0x7b, 0x02, 0x01, 0x03, \ - 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04, \ - 0xf3, 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0a, 0x06, \ - 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0x94, 0xea, 0x03, \ - 0xe1, 0x95, 0xdc, 0xad, 0x43, 0x99, 0xa5, 0x94, 0x68, 0x1e, 0x62, 0x5f, 0x82, 0xfa, 0x6f, 0x61, 0x9e, 0x71, 0x79, \ - 0x63, 0x5f, 0xe5, 0x5e, 0x5d, 0xaf, 0x33, 0x91, 0xf0, 0x72, 0x02, 0x20, 0x16, 0xd1, 0x0c, 0x6f, 0x83, 0xbe, 0xbd, \ - 0x45, 0xa5, 0x59, 0xa7, 0x13, 0x8c, 0x5c, 0xd0, 0xd1, 0x68, 0x90, 0x9b, 0x6c, 0x40, 0x12, 0x9b, 0xc3, 0x3e, 0x6e, \ - 0x3c, 0xa6, 0x80, 0xbf, 0x7c, 0xd9 \ - } - -// All remaining data will be pulled from the provisioning region of flash. -#endif - -#else - -/** - * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID - * - * 0xFFF1: Test vendor. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1 - -/** - * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID - * - */ -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8002 - -// Use a default setup PIN code if one hasn't been provisioned in flash. -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 -#endif - -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 -#endif - -// Use a default pairing code if one hasn't been provisioned in flash. -#define CHIP_DEVICE_CONFIG_USE_TEST_PAIRING_CODE "CHIPUS" - -/** - * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER - * - * Enables the use of a hard-coded default serial number if none - * is found in CHIP NV storage. - */ -#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN" - -#endif // CONFIG_CHIP_LOAD_REAL_FACTORY_DATA - -/** - * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION - * - * The hardware version number assigned to device or product by the device vendor. This - * number is scoped to the device product id, and typically corresponds to a revision of the - * physical device, a change to its packaging, and/or a change to its marketing presentation. - * This value is generally *not* incremented for device software versions. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 100 - -#ifndef CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING "v0.1.0" -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING - * - * A string identifying the software version running on the device. - * CHIP currently expects the software version to be in the format - * {MAJOR_VERSION}.0d{MINOR_VERSION} - */ -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION NXP_CONFIG_DEVICE_SOFTWARE_VERSION -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "NXP Semiconductors" -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "NXP Demo App" -#endif - -/** - * CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_TIMEOUT - * - * The amount of time in miliseconds after which BLE should change his advertisements - * from fast interval to slow interval. - * - * 30000 (30 secondes). - */ -#define CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_TIMEOUT (30 * 1000) - -/** - * CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT - * - * The amount of time in miliseconds after which BLE advertisement should be disabled, counting - * from the moment of slow advertisement commencement. - * - * Defaults to 9000000 (15 minutes). - */ -#define CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT (15 * 60 * 1000) - -/** - * CONFIG_CHIP_NFC_COMMISSIONING, CHIP_DEVICE_CONFIG_ENABLE_NFC - * - * NFC commissioning is not supported - */ -#define CONFIG_CHIP_NFC_COMMISSIONING 0 -#define CHIP_DEVICE_CONFIG_ENABLE_NFC 0 - -/** - * @def CHIP_CONFIG_MAX_FABRICS - * - * @brief - * Maximum number of fabrics the device can participate in. Each fabric can - * provision the device with its unique operational credentials and manage - * its own access control lists. - */ -#define CHIP_CONFIG_MAX_FABRICS 5 // 5 is the minimum number of supported fabrics - -#define CHIP_DEVICE_CONFIG_ENABLE_SED 1 - -/** - * @def CHIP_DEVICE_CONFIG_KVS_WEAR_STATS - * - * @brief Toggle support for key value store wear stats on or off. - */ -#define CHIP_DEVICE_CONFIG_KVS_WEAR_STATS 0 - -/** - * @def CHIP_IM_MAX_NUM_COMMAND_HANDLER - * - * @brief Defines the maximum number of CommandHandler, limits the number of active commands transactions on server. - */ -#define CHIP_IM_MAX_NUM_COMMAND_HANDLER 2 - -/** - * @def CHIP_IM_MAX_NUM_WRITE_HANDLER - * - * @brief Defines the maximum number of WriteHandler, limits the number of active write transactions on server. - */ -#define CHIP_IM_MAX_NUM_WRITE_HANDLER 2 - -/** - * CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE - * - * For a development build, set the default importance of events to be logged as Debug. - * Since debug is the lowest importance level, this means all standard, critical, info and - * debug importance level vi events get logged. - */ -#if BUILD_RELEASE -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Production -#else -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug -#endif // BUILD_RELEASE - -#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1 - -#if CONFIG_DIAG_LOGS_DEMO -#define CHIP_CONFIG_ENABLE_BDX_LOG_TRANSFER 1 -#define CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE 1024 -#endif diff --git a/examples/lock-app/nxp/mcxw72/third_party/connectedhomeip b/examples/lock-app/nxp/mcxw72/third_party/connectedhomeip deleted file mode 120000 index 59307833b4f..00000000000 --- a/examples/lock-app/nxp/mcxw72/third_party/connectedhomeip +++ /dev/null @@ -1 +0,0 @@ -../../../../.. \ No newline at end of file diff --git a/examples/lock-app/nxp/zap/lock-app.matter b/examples/lock-app/nxp/zap/lock-app.matter index 63ea62eb1de..dc592ac5d4b 100644 --- a/examples/lock-app/nxp/zap/lock-app.matter +++ b/examples/lock-app/nxp/zap/lock-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/lock-app/qpg/zap/lock.matter b/examples/lock-app/qpg/zap/lock.matter index 608ff1bec58..346e55df7d1 100644 --- a/examples/lock-app/qpg/zap/lock.matter +++ b/examples/lock-app/qpg/zap/lock.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/lock-app/realtek/data_model/lock-app.matter b/examples/lock-app/realtek/data_model/lock-app.matter index 933f4a93af8..8aec908afb9 100644 --- a/examples/lock-app/realtek/data_model/lock-app.matter +++ b/examples/lock-app/realtek/data_model/lock-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/lock-app/silabs/data_model/lock-app.matter b/examples/lock-app/silabs/data_model/lock-app.matter index f7fc213706b..804cd13d0b6 100644 --- a/examples/lock-app/silabs/data_model/lock-app.matter +++ b/examples/lock-app/silabs/data_model/lock-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/log-source-app/log-source-common/log-source-app.matter b/examples/log-source-app/log-source-common/log-source-app.matter index b69a5119fe3..a3cf8ea576b 100644 --- a/examples/log-source-app/log-source-common/log-source-app.matter +++ b/examples/log-source-app/log-source-common/log-source-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/microwave-oven-app/microwave-oven-common/microwave-oven-app.matter b/examples/microwave-oven-app/microwave-oven-common/microwave-oven-app.matter index ffbde325ae6..d1b02546900 100644 --- a/examples/microwave-oven-app/microwave-oven-common/microwave-oven-app.matter +++ b/examples/microwave-oven-app/microwave-oven-common/microwave-oven-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/network-manager-app/network-manager-common/network-manager-app.matter b/examples/network-manager-app/network-manager-common/network-manager-app.matter index ebcdc8d549f..5f929026bf0 100644 --- a/examples/network-manager-app/network-manager-common/network-manager-app.matter +++ b/examples/network-manager-app/network-manager-common/network-manager-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter b/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter index e640cfa7f48..f95f1f9d818 100644 --- a/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter +++ b/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/ota-requestor-app/ameba/main/chipinterface.cpp b/examples/ota-requestor-app/ameba/main/chipinterface.cpp index cbc7eec3ac9..49b6bd2802a 100755 --- a/examples/ota-requestor-app/ameba/main/chipinterface.cpp +++ b/examples/ota-requestor-app/ameba/main/chipinterface.cpp @@ -78,12 +78,13 @@ static void InitServer(intptr_t context) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + static AmebaObserver sAmebaObserver; initParams.dataModelProvider = CodegenDataModelProviderInstance(initParams.persistentStorageDelegate); initParams.appDelegate = &sAmebaObserver; + chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); - chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); NetWorkCommissioningInstInit(); chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(&sAmebaObserver); diff --git a/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter b/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter index 0152bbf7b89..181998b51d0 100644 --- a/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter +++ b/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/placeholder/linux/apps/app1/config.matter b/examples/placeholder/linux/apps/app1/config.matter index ee66e8f669f..0734612b03b 100644 --- a/examples/placeholder/linux/apps/app1/config.matter +++ b/examples/placeholder/linux/apps/app1/config.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/placeholder/linux/apps/app2/config.matter b/examples/placeholder/linux/apps/app2/config.matter index 299a962870f..9b81753ed57 100644 --- a/examples/placeholder/linux/apps/app2/config.matter +++ b/examples/placeholder/linux/apps/app2/config.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/platform/esp32/icd/ICDSubscriptionCallback.cpp b/examples/platform/esp32/icd/ICDSubscriptionCallback.cpp deleted file mode 100644 index eba28968085..00000000000 --- a/examples/platform/esp32/icd/ICDSubscriptionCallback.cpp +++ /dev/null @@ -1,65 +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 "ICDSubscriptionCallback.h" -#include - -CHIP_ERROR ICDSubscriptionCallback::OnSubscriptionRequested(chip::app::ReadHandler & aReadHandler, - chip::Transport::SecureSession & aSecureSession) -{ - using namespace chip::System::Clock; - - Seconds32 interval_s32 = std::chrono::duration_cast(CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL); - - if (interval_s32 > Seconds16::max()) - { - interval_s32 = Seconds16::max(); - } - uint32_t decidedMaxInterval = interval_s32.count(); - - uint16_t requestedMinInterval = 0; - uint16_t requestedMaxInterval = 0; - aReadHandler.GetReportingIntervals(requestedMinInterval, requestedMaxInterval); - - // If requestedMinInterval is greater than IdleTimeInterval, select next wake up time as max interval - if (requestedMinInterval > decidedMaxInterval) - { - uint16_t ratio = requestedMinInterval / decidedMaxInterval; - if (requestedMinInterval % decidedMaxInterval) - { - ratio++; - } - - decidedMaxInterval *= ratio; - } - - // Verify that decidedMaxInterval is an acceptable value - if (decidedMaxInterval > Seconds16::max().count()) - { - decidedMaxInterval = Seconds16::max().count(); - } - - // Verify that the decidedMaxInterval respects MAX(SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT, MaxIntervalCeiling) - uint16_t maximumMaxInterval = std::max(kSubscriptionMaxIntervalPublisherLimit, requestedMaxInterval); - if (decidedMaxInterval > maximumMaxInterval) - { - decidedMaxInterval = maximumMaxInterval; - } - - return aReadHandler.SetMaxReportingInterval(decidedMaxInterval); -} diff --git a/examples/platform/esp32/icd/ICDSubscriptionCallback.h b/examples/platform/esp32/icd/ICDSubscriptionCallback.h deleted file mode 100644 index c9f77e6df2a..00000000000 --- a/examples/platform/esp32/icd/ICDSubscriptionCallback.h +++ /dev/null @@ -1,35 +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 - -/** - * @brief The goal of the ICDSubscriptionCallback class is to negotiate the max interval subscription to match the idle interval of - * the IC device. When a subscription is requested, the device will change the requested max interval to match its idle time - * interval through the OnSubscriptionRequested function. - */ -class ICDSubscriptionCallback : public chip::app::ReadHandler::ApplicationCallback -{ - /** - * @brief Function called when a subscription is requested. - * An ICD will use this function to negotiate the subscription max interval to match its idle time interval - */ - CHIP_ERROR OnSubscriptionRequested(chip::app::ReadHandler & aReadHandler, - chip::Transport::SecureSession & aSecureSession) override; -}; diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp index 0f77db5876d..d67b05541ce 100644 --- a/examples/platform/linux/AppMain.cpp +++ b/examples/platform/linux/AppMain.cpp @@ -1026,6 +1026,12 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl) sigaction(SIGTERM, &sa, nullptr); #endif + // This message is used as a marker for when the application process has started. + // See: scripts/tests/chiptest/test_definition.py + // TODO: A cleaner and more generic mechanism needs to be developed as a follow-up. + // Currently other places (OTA, TV) also scrape logs for information and a better way should be + // possible. + ChipLogProgress(DeviceLayer, "===== APP STATUS: Starting event loop ====="); if (impl != nullptr) { impl->RunMainLoop(); diff --git a/examples/platform/nxp/common/Kconfig b/examples/platform/nxp/common/Kconfig index c06efed8a54..01bb93e6f9f 100644 --- a/examples/platform/nxp/common/Kconfig +++ b/examples/platform/nxp/common/Kconfig @@ -74,21 +74,27 @@ if CHIP_APP_BLE_MANAGER endchoice # CHIP_APP_BLE_MANAGER - config CHIP_APP_EXTRA_GATT_DB_HEADER - string "Extra application Gatt db header" - default "<$(CHIP_ROOT)/examples/platform/nxp/mcxw71/app_ble/include/extra_gatt_db.h>" if CHIP_NXP_PLATFORM_MCXW71 || CHIP_NXP_PLATFORM_MCXW72 - depends on CHIP_NXP_MULTIPLE_BLE_CONNECTIONS - help +endif # CHIP_APP_BLE_MANAGER + +config CHIP_APP_CUSTOMIZE_EXTRA_GATT_INFO + bool "Enable customization of GATT service on MCXW platform" + default y if CHIP_NXP_MULTIPLE_BLE_CONNECTIONS + help + Enable customization of GATT service on MCXW platform + +if CHIP_APP_CUSTOMIZE_EXTRA_GATT_INFO +config CHIP_APP_EXTRA_GATT_DB_HEADER + string "Extra application Gatt db header" + default "<$(CHIP_ROOT)/examples/platform/nxp/mcxw71/app_ble/include/extra_gatt_db.h>" if CHIP_NXP_PLATFORM_MCXW71 || CHIP_NXP_PLATFORM_MCXW72 + help Set path to extra application Gatt db header. - config CHIP_APP_EXTRA_GATT_UUID_HEADER - string "Extra application Gatt UUID header" - default "<$(CHIP_ROOT)/examples/platform/nxp/mcxw71/app_ble/include/extra_gatt_uuid128.h>" if CHIP_NXP_PLATFORM_MCXW71 || CHIP_NXP_PLATFORM_MCXW72 - depends on CHIP_NXP_MULTIPLE_BLE_CONNECTIONS - help +config CHIP_APP_EXTRA_GATT_UUID_HEADER + string "Extra application Gatt UUID header" + default "<$(CHIP_ROOT)/examples/platform/nxp/mcxw71/app_ble/include/extra_gatt_uuid128.h>" if CHIP_NXP_PLATFORM_MCXW71 || CHIP_NXP_PLATFORM_MCXW72 + help Set path to extra application Gatt UUID header. - -endif # CHIP_APP_BLE_MANAGER +endif config DIAG_LOGS_DEMO bool "Diagnostic log demo" @@ -256,11 +262,11 @@ if CHIP_APP_OTA_REQUESTOR choice CHIP_APP_OTA_REQUESTOR_INITIATOR_SELECTION prompt "Select OTA Requestor Initiator" - config CHIP_APP_OTA_REQUESTOR_INITIATOR_MULTI_IMAGE - bool "OTA Requestor Initiator Multi-Image" + config CHIP_APP_OTA_REQUESTOR_INITIATOR_EMPTY_SELF_TEST + bool "OTA Requestor Initiator Empty Self Test" depends on CHIP_NXP_PLATFORM_MCXW71 || CHIP_NXP_PLATFORM_MCXW72 help - Enable OTA Requestor Initiator for multiple image OTA SW update. + Enable OTA Requestor Initiator with an empty self test function for OTA SW update. config CHIP_APP_OTA_REQUESTOR_INITIATOR_FREERTOS bool "OTA Requestor Initiator FreeRTOS" @@ -284,6 +290,12 @@ if CHIP_APP_OTA_REQUESTOR endif # CHIP_APP_OTA_REQUESTOR +config CHIP_REGISTER_SIMPLE_TEST_EVENT_TRIGGER_DELEGATE + bool "Registration of simple test event trigger delegate" + default y if CHIP_ENABLE_ICD_SUPPORT + help + Enable registration of a simple test event trigger delegate, ONLY enable it for matter certification testing. + config CHIP_APP_RPC bool "App RPC" help diff --git a/examples/platform/nxp/common/app_common.cmake b/examples/platform/nxp/common/app_common.cmake index 275990df878..7f34d011855 100644 --- a/examples/platform/nxp/common/app_common.cmake +++ b/examples/platform/nxp/common/app_common.cmake @@ -255,9 +255,10 @@ if (CONFIG_CHIP_APP_OTA_REQUESTOR) ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/ota_requestor/source/OTARequestorInitiatorCommon.cpp ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/ota_requestor/source/OTARequestorInitiatorZephyr.cpp ) - elseif (CONFIG_CHIP_APP_OTA_REQUESTOR_INITIATOR_MULTI_IMAGE) + elseif (CONFIG_CHIP_APP_OTA_REQUESTOR_INITIATOR_EMPTY_SELF_TEST) target_sources(app PRIVATE - ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/ota_requestor/source/OTARequestorInitiatorMultiImage.cpp + ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/ota_requestor/source/OTARequestorInitiatorCommon.cpp + ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/ota_requestor/source/OTARequestorInitiatorEmptySelfTest.cpp ) endif() if (CONFIG_CHIP_APP_PLATFORM_OTA_UTILS) diff --git a/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp b/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp index f9bbc2817cc..598e201df0f 100644 --- a/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp +++ b/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp @@ -89,20 +89,15 @@ #include "OTARequestorInitiator.h" #endif -#if CONFIG_CHIP_TEST_EVENT && CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR -#include +#if defined(CONFIG_CHIP_REGISTER_SIMPLE_TEST_EVENT_TRIGGER_DELEGATE) && CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +#include #endif #ifdef ENABLE_CHIP_SHELL #include #endif -#ifdef SMOKE_CO_ALARM -#include -#include -#endif - -#if CHIP_CONFIG_ENABLE_ICD_SERVER +#ifdef CONFIG_CHIP_REGISTER_SIMPLE_TEST_EVENT_TRIGGER_DELEGATE #include #endif @@ -144,16 +139,10 @@ app::Clusters::NetworkCommissioning::Instance #endif #if CHIP_DEVICE_CONFIG_ENABLE_TBR -extern char baseServiceInstanceName[]; -#endif - -#if CHIP_CONFIG_ENABLE_ICD_SERVER || (CONFIG_CHIP_TEST_EVENT && CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR) -static uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, - 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, - 0xcc, 0xdd, 0xee, 0xff }; +extern const char sBaseServiceInstanceName[]; #endif -#ifdef SMOKE_CO_ALARM +#ifdef CONFIG_CHIP_REGISTER_SIMPLE_TEST_EVENT_TRIGGER_DELEGATE static uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; @@ -184,23 +173,16 @@ void chip::NXP::App::AppTaskBase::InitServer(intptr_t arg) initParams.reportScheduler = &sReportScheduler; #endif -#if CONFIG_CHIP_TEST_EVENT && CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - static OTATestEventTriggerDelegate testEventTriggerDelegate{ ByteSpan(sTestEventTriggerEnableKey) }; - initParams.testEventTriggerDelegate = &testEventTriggerDelegate; -#endif - -#ifdef SMOKE_CO_ALARM +#ifdef CONFIG_CHIP_REGISTER_SIMPLE_TEST_EVENT_TRIGGER_DELEGATE static SimpleTestEventTriggerDelegate sTestEventTriggerDelegate{}; - static SmokeCOTestEventTriggerHandler sSmokeCOTestEventTriggerHandler{}; VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(sTestEventTriggerEnableKey)) == CHIP_NO_ERROR); - VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sSmokeCOTestEventTriggerHandler) == CHIP_NO_ERROR); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; + +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + static OTATestEventTriggerHandler sOtaTestEventTriggerHandler{}; + VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sOtaTestEventTriggerHandler) == CHIP_NO_ERROR); #endif -#if CHIP_CONFIG_ENABLE_ICD_SERVER - static SimpleTestEventTriggerDelegate sTestEventTriggerDelegate{}; - VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(sTestEventTriggerEnableKey)) == CHIP_NO_ERROR); - initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; #endif #if CONFIG_OPERATIONAL_KEYSTORE @@ -518,7 +500,7 @@ void chip::NXP::App::AppTaskBase::EnableTbrManagementCluster() Server::GetInstance().GetFailSafeContext()); // Initialize TBR name - CharSpan brName(baseServiceInstanceName, strlen(baseServiceInstanceName)); + CharSpan brName(sBaseServiceInstanceName, strlen(sBaseServiceInstanceName)); sThreadBRDelegate.SetThreadBorderRouterName(brName); // Initialize TBR cluster sThreadBRMgmtInstance.Init(); diff --git a/examples/platform/nxp/common/app_task/source/AppTaskZephyr.cpp b/examples/platform/nxp/common/app_task/source/AppTaskZephyr.cpp index d1d4f552b1d..7ee2caad64c 100644 --- a/examples/platform/nxp/common/app_task/source/AppTaskZephyr.cpp +++ b/examples/platform/nxp/common/app_task/source/AppTaskZephyr.cpp @@ -43,7 +43,7 @@ #if CONFIG_CHIP_FACTORY_DATA #include #else -#include +#include #endif #include "AppFactoryData.h" diff --git a/examples/platform/nxp/common/icd/source/ICDUtil.cpp b/examples/platform/nxp/common/icd/source/ICDUtil.cpp index 98abd6dcc48..4ff703931fa 100644 --- a/examples/platform/nxp/common/icd/source/ICDUtil.cpp +++ b/examples/platform/nxp/common/icd/source/ICDUtil.cpp @@ -20,7 +20,7 @@ #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR #ifndef CONFIG_APP_FREERTOS_OS -#include +#include #else #include #endif /* CONFIG_APP_FREERTOS_OS */ diff --git a/examples/platform/nxp/common/ota_requestor/include/OTARequestorInitiator.h b/examples/platform/nxp/common/ota_requestor/include/OTARequestorInitiator.h index b5874941442..3b10df4ee9d 100644 --- a/examples/platform/nxp/common/ota_requestor/include/OTARequestorInitiator.h +++ b/examples/platform/nxp/common/ota_requestor/include/OTARequestorInitiator.h @@ -25,7 +25,7 @@ #include "app/clusters/ota-requestor/DefaultOTARequestorStorage.h" #ifndef CONFIG_APP_FREERTOS_OS -#include +#include #else #include "platform/nxp/common/ota/OTAImageProcessorImpl.h" #endif /* CONFIG_APP_FREERTOS_OS */ diff --git a/src/platform/nxp/zephyr/PlatformManagerImpl.h b/examples/platform/nxp/common/ota_requestor/source/OTARequestorInitiatorEmptySelfTest.cpp similarity index 75% rename from src/platform/nxp/zephyr/PlatformManagerImpl.h rename to examples/platform/nxp/common/ota_requestor/source/OTARequestorInitiatorEmptySelfTest.cpp index 75dcb0e7d74..f6190448d10 100644 --- a/src/platform/nxp/zephyr/PlatformManagerImpl.h +++ b/examples/platform/nxp/common/ota_requestor/source/OTARequestorInitiatorEmptySelfTest.cpp @@ -1,6 +1,7 @@ /* * - * Copyright (c) 2024 Project CHIP Authors + * Copyright (c) 2025 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. @@ -15,11 +16,6 @@ * limitations under the License. */ -/** - * @file - * Provides an implementation of the PlatformManager object. - */ - -#pragma once +#include "OTARequestorInitiator.h" -#include +void chip::NXP::App::OTARequestorInitiator::HandleSelfTest() {} diff --git a/examples/platform/nxp/common/ota_requestor/source/OTARequestorInitiatorMultiImage.cpp b/examples/platform/nxp/common/ota_requestor/source/OTARequestorInitiatorMultiImage.cpp deleted file mode 100644 index 527b416a86a..00000000000 --- a/examples/platform/nxp/common/ota_requestor/source/OTARequestorInitiatorMultiImage.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * - * 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 "OTARequestorInitiator.h" - -using namespace chip; - -constexpr uint16_t requestedOtaBlockSize = 1024; - -void chip::NXP::App::OTARequestorInitiator::InitOTA(intptr_t context) -{ - auto * otaRequestorInit = reinterpret_cast(context); - // Set the global instance of the OTA requestor core component - SetRequestorInstance(&otaRequestorInit->gRequestorCore); - - otaRequestorInit->gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage()); - otaRequestorInit->gRequestorCore.Init(chip::Server::GetInstance(), otaRequestorInit->gRequestorStorage, - otaRequestorInit->gRequestorUser, otaRequestorInit->gDownloader); - otaRequestorInit->gRequestorUser.SetMaxDownloadBlockSize(requestedOtaBlockSize); - - auto & imageProcessor = OTAImageProcessorImpl::GetDefaultInstance(); - otaRequestorInit->gRequestorUser.Init(&otaRequestorInit->gRequestorCore, &imageProcessor); - imageProcessor.Init(&otaRequestorInit->gDownloader); - // Set the image processor instance used for handling image being downloaded - otaRequestorInit->gDownloader.SetImageProcessorDelegate(&imageProcessor); -} - -void chip::NXP::App::OTARequestorInitiator::HandleSelfTest() {} diff --git a/examples/platform/nxp/common/wifi_connect/source/WifiConnect.cpp b/examples/platform/nxp/common/wifi_connect/source/WifiConnect.cpp index 438bee50407..17ae6c811ab 100644 --- a/examples/platform/nxp/common/wifi_connect/source/WifiConnect.cpp +++ b/examples/platform/nxp/common/wifi_connect/source/WifiConnect.cpp @@ -45,6 +45,10 @@ CHIP_ERROR WifiConnectAtboot(chip::DeviceLayer::NetworkCommissioning::WiFiDriver VerifyOrReturnError(status == chip::DeviceLayer::NetworkCommissioning::Status::kSuccess, CHIP_ERROR_CONNECTION_ABORTED); wifiDriver->ConnectNetwork(ssidSpan, nullptr); } + if (networks != nullptr) + { + networks->Release(); + } return CHIP_NO_ERROR; } diff --git a/examples/platform/nxp/config/prj_thread_mtd_low_power_lit.conf b/examples/platform/nxp/config/prj_thread_mtd_low_power_lit.conf index fd8d587d605..d8dd4359f2a 100644 --- a/examples/platform/nxp/config/prj_thread_mtd_low_power_lit.conf +++ b/examples/platform/nxp/config/prj_thread_mtd_low_power_lit.conf @@ -34,6 +34,6 @@ CONFIG_CHIP_ICD_LIT_SUPPORT=y CONFIG_CHIP_ICD_DSLS_SUPPORT=y CONFIG_CHIP_ICD_SLOW_POLL_INTERVAL=15000 CONFIG_CHIP_ICD_FAST_POLLING_INTERVAL=500 -CONFIG_CHIP_ICD_IDLE_MODE_DURATION=60 +CONFIG_CHIP_ICD_IDLE_MODE_DURATION=3600 CONFIG_CHIP_ICD_ACTIVE_MODE_DURATION=15000 CONFIG_CHIP_ICD_ACTIVE_MODE_THRESHOLD=30000 \ No newline at end of file diff --git a/examples/platform/nxp/zephyr/factory_data/source/AppFactoryDataExample.cpp b/examples/platform/nxp/zephyr/factory_data/source/AppFactoryDataExample.cpp index 116dedc8993..c6b216e35fc 100644 --- a/examples/platform/nxp/zephyr/factory_data/source/AppFactoryDataExample.cpp +++ b/examples/platform/nxp/zephyr/factory_data/source/AppFactoryDataExample.cpp @@ -38,7 +38,7 @@ static const uint8_t aes128TestKey[] #if CONFIG_CHIP_FACTORY_DATA #include #else -#include +#include #endif #if CONFIG_CHIP_FACTORY_DATA && CONFIG_CHIP_ENCRYPTED_FACTORY_DATA diff --git a/examples/pump-app/pump-common/pump-app.matter b/examples/pump-app/pump-common/pump-app.matter index adb0b132c06..297959d03fe 100644 --- a/examples/pump-app/pump-common/pump-app.matter +++ b/examples/pump-app/pump-common/pump-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/pump-app/silabs/data_model/pump-thread-app.matter b/examples/pump-app/silabs/data_model/pump-thread-app.matter index 55eb7f93be5..85ac9288fa6 100644 --- a/examples/pump-app/silabs/data_model/pump-thread-app.matter +++ b/examples/pump-app/silabs/data_model/pump-thread-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/pump-app/silabs/data_model/pump-wifi-app.matter b/examples/pump-app/silabs/data_model/pump-wifi-app.matter index 55eb7f93be5..85ac9288fa6 100644 --- a/examples/pump-app/silabs/data_model/pump-wifi-app.matter +++ b/examples/pump-app/silabs/data_model/pump-wifi-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter b/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter index 7e1331883b2..db8b3146d96 100644 --- a/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter +++ b/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/refrigerator-app/refrigerator-common/refrigerator-app.matter b/examples/refrigerator-app/refrigerator-common/refrigerator-app.matter index d819a2c55c2..9c4de528bcc 100644 --- a/examples/refrigerator-app/refrigerator-common/refrigerator-app.matter +++ b/examples/refrigerator-app/refrigerator-common/refrigerator-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter b/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter index 0bd3abf64e9..e5381b8f194 100644 --- a/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter +++ b/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter b/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter index 5a539a4ca4e..c0a2dfeb3a3 100644 --- a/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter +++ b/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/rvc-app/rvc-common/rvc-app.matter b/examples/rvc-app/rvc-common/rvc-app.matter index f34c2f1f4b0..0870d61a2fe 100644 --- a/examples/rvc-app/rvc-common/rvc-app.matter +++ b/examples/rvc-app/rvc-common/rvc-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } 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 3994eb815e5..19892dd4959 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 @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/temperature-measurement-app/temperature-measurement-common/temperature-measurement.matter b/examples/temperature-measurement-app/temperature-measurement-common/temperature-measurement.matter index 1904fa015d2..e85f49e7a1b 100644 --- a/examples/temperature-measurement-app/temperature-measurement-common/temperature-measurement.matter +++ b/examples/temperature-measurement-app/temperature-measurement-common/temperature-measurement.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/terms-and-conditions-app/terms-and-conditions-common/terms-and-conditions-app.matter b/examples/terms-and-conditions-app/terms-and-conditions-common/terms-and-conditions-app.matter index 1ce20a00c9c..eef9caa0b1f 100644 --- a/examples/terms-and-conditions-app/terms-and-conditions-common/terms-and-conditions-app.matter +++ b/examples/terms-and-conditions-app/terms-and-conditions-common/terms-and-conditions-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/thermostat/nxp/rt/rt1060/.gn b/examples/thermostat/nxp/rt/rt1060/.gn deleted file mode 100644 index 0985ed955a4..00000000000 --- a/examples/thermostat/nxp/rt/rt1060/.gn +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) 2020 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") -import("//build_overrides/chip.gni") - -# The location of the build configuration file. -buildconfig = "${build_root}/config/BUILDCONFIG.gn" - -# CHIP uses angle bracket includes. -check_system_includes = true - -default_args = { - target_cpu = "arm" - target_os = "freertos" - - import("//args.gni") - - # Import common example GN args - import("${chip_root}/examples/platform/nxp/common/gn/args.gni") - - # Import default platform configs - import("${chip_root}/src/platform/nxp/rt/rt1060/args.gni") -} diff --git a/examples/thermostat/nxp/rt/rt1060/BUILD.gn b/examples/thermostat/nxp/rt/rt1060/BUILD.gn deleted file mode 100644 index 1a13b18f2f5..00000000000 --- a/examples/thermostat/nxp/rt/rt1060/BUILD.gn +++ /dev/null @@ -1,333 +0,0 @@ -# Copyright (c) 2021-2023 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") -import("//build_overrides/chip.gni") -import("//build_overrides/nxp_sdk.gni") -import("//build_overrides/openthread.gni") -import("${chip_root}/src/platform/device.gni") - -#allows to get common NXP SDK gn options -import("${nxp_sdk_build_root}/nxp_sdk.gni") - -# Allows to get various RT gn options -import("${nxp_sdk_build_root}/${nxp_sdk_name}/rt_sdk.gni") - -import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") -import( - "${nxp_sdk_build_root}/${nxp_sdk_name}/${rt_platform}/${rt_platform}.gni") -import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") - -assert(current_os == "freertos") -assert(target_os == "freertos") -assert(nxp_platform == "rt/rt1060") - -declare_args() { - # Allows to enable to ota_provider support - enable_ota_provider = false - - # Allows to connect to a predefine Wi-Fi network at boot - wifi_auto_connect_at_boot = false - wifi_auto_connect_at_boot_ssid = "" - wifi_auto_connect_at_boot_password = "" - - # Setup discriminator as argument - setup_discriminator = 3840 - - chip_with_diag_logs_demo = true -} - -example_platform_dir = - "${nxp_sdk_matter_support_root}/examples/platform/${nxp_platform}" -common_example_dir = "${chip_root}/examples/platform/nxp/common" - -app_common_folder = "thermostat/nxp/zap" - -# Create here the SDK instance. -# Particular sources/defines/includes could be added/changed depending on the target application. -rt_sdk("sdk") { - defines = [] - - cflags = [] - public_deps = [] - public_configs = [] - sources = [] - include_dirs = [] - - # Indicate paths to default board files - include_dirs += [ "${example_platform_dir}/board/" ] - - # RT1060 rev A use same pin mux as rev B - # If user needs different pin mux files for rev A and rev B boards, the source and include from below needs to be updated accordingly - if (evkname == "evkmimxrt1060") { - include_dirs += [ "${example_platform_dir}/board/evkbmimxrt1060/" ] - sources += [ "${example_platform_dir}/board/evkbmimxrt1060/pin_mux.c" ] - } else { - include_dirs += [ "${example_platform_dir}/board/${evkname}/" ] - sources += [ "${example_platform_dir}/board/${evkname}/pin_mux.c" ] - } - - if (iw416_transceiver || w8801_transceiver || iwx12_transceiver) { - if (evkname == "evkmimxrt1060") { - include_dirs += [ "${example_platform_dir}/board/evkbmimxrt1060/" ] - sources += - [ "${example_platform_dir}/board/evkbmimxrt1060/sdmmc_config.c" ] - sources += - [ "${example_platform_dir}/board/evkbmimxrt1060/wifi_bt_config.c" ] - } else { - include_dirs += [ "${example_platform_dir}/board/${evkname}/" ] - sources += [ "${example_platform_dir}/board/${evkname}/sdmmc_config.c" ] - sources += [ "${example_platform_dir}/board/${evkname}/wifi_bt_config.c" ] - } - } - - sources += [ "${example_platform_dir}/board/hardware_init.c" ] - sources += [ "${example_platform_dir}/board/clock_config.c" ] - sources += [ "${example_platform_dir}/board/board.c" ] - sources += [ "${example_platform_dir}/board/peripherals.c" ] - - # Indicate the path to CHIPProjectConfig.h - include_dirs += [ "include/config" ] - - # Indicate the default path to FreeRTOSConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/freeRTOS" ] - - # Indicate the default path to OpenThreadConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/openthread" ] - - # For matter with BR feature, increase FreeRTOS heap size and enable TBR cluster - if (chip_enable_wifi && chip_enable_openthread) { - defines += [ - "configTOTAL_HEAP_SIZE=(size_t)(170 * 1024)", - "CHIP_DEVICE_CONFIG_ENABLE_TBR=1", - ] - } - - defines += [ - "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", - ] -} - -# Create the SDK driver instance. -# Particular sources/defines/includes could be added to add other drivers not available in the default sdk driver template -rt1060_sdk_drivers("sdk_driver") { -} - -rt_executable("thermostat") { - output_name = "chip-rt1060-thermostat-example" - - defines = [ - "CONFIG_RENDEZVOUS_MODE=7", - "CONFIG_APP_FREERTOS_OS=1", - ] - - if (chip_enable_openthread) { - defines += [ "CONFIG_NET_L2_OPENTHREAD=1" ] - } - - if (chip_with_diag_logs_demo) { - defines += [ - "CONFIG_DIAG_LOGS_DEMO=1", - "CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE=1024", - ] - } - - include_dirs = [ - "../../common/main/include", - "../../common/main", - "${chip_root}/examples/all-clusters-app/all-clusters-common/include", - "${chip_root}/examples/providers/", - ] - - sources = [ - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp", - "${chip_root}/examples/providers/DeviceInfoProviderImpl.cpp", - "../../common/main/AppTask.cpp", - "../../common/main/DeviceCallbacks.cpp", - "../../common/main/ZclCallbacks.cpp", - "../../common/main/include/AppEvent.h", - "../../common/main/include/AppTask.h", - "../../common/main/include/DeviceCallbacks.h", - "../../common/main/main.cpp", - ] - - if (chip_enable_ble) { - defines += [ "APP_BT_DEVICE_NAME=\"NXP-ThermostatApp\"" ] - include_dirs += [ "${common_example_dir}/app_ble/include" ] - if (ble_adv_data_custom) { - # to customize BLE advertising data - defines += [ "CONFIG_CHIP_CUSTOM_BLE_ADV_DATA=1" ] - include_dirs += [ "${chip_root}/src/platform/nxp/common/ble_zephyr" ] - sources += - [ "${common_example_dir}/app_ble/source/BleZephyrManagerApp.cpp" ] - } else { - # Empty implementation, default matter advertising data - sources += [ - "${common_example_dir}/app_ble/source/BLEApplicationManagerEmpty.cpp", - ] - } - } - - if (chip_with_diag_logs_demo) { - include_dirs += [ - "${common_example_dir}/diagnostic_logs/include", - "${chip_root}", - ] - sources += [ - "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsDemo.cpp", - "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp", - ] - } - - # App common files - include_dirs += [ - "${common_example_dir}/icd/include", - "${common_example_dir}/matter_cli/include", - "${common_example_dir}/device_manager/include", - "${common_example_dir}/device_callbacks/include", - "${common_example_dir}/matter_button/include", - "${common_example_dir}/factory_data/include", - "${common_example_dir}/app_task/include", - ] - - sources += [ - "${chip_root}/examples/platform/nxp/${nxp_platform}/factory_data/source/AppFactoryDataExample.cpp", - "${common_example_dir}/app_task/source/AppTaskBase.cpp", - "${common_example_dir}/app_task/source/AppTaskFreeRTOS.cpp", - "${common_example_dir}/device_callbacks/source/CommonDeviceCallbacks.cpp", - "${common_example_dir}/device_manager/source/CHIPDeviceManager.cpp", - "${common_example_dir}/icd/source/ICDUtil.cpp", - "${common_example_dir}/matter_button/source/ButtonRegistrationEmpty.cpp", - ] - - deps = [ - "${chip_root}/examples/${app_common_folder}", - "${chip_root}/src/app/clusters/network-commissioning:network-commissioning", - "${chip_root}/src/setup_payload:onboarding-codes-utils", - ] - - if (nxp_enable_matter_cli) { - defines += [ "ENABLE_CHIP_SHELL" ] - deps += [ - "${chip_root}/examples/shell/shell_common:shell_common", - "${chip_root}/src/lib/shell:shell", - ] - sources += [ - "${common_example_dir}/matter_cli/source/AppCLIBase.cpp", - "${common_example_dir}/matter_cli/source/AppCLIFreeRTOS.cpp", - ] - } - - if (chip_enable_ota_requestor) { - include_dirs += [ "${common_example_dir}/ota_requestor/include" ] - sources += [ - "${common_example_dir}/ota_requestor/source/OTARequestorInitiator.cpp", - "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorCommon.cpp", - ] - } - - if (wifi_auto_connect_at_boot) { - assert(wifi_auto_connect_at_boot_ssid != "" && - wifi_auto_connect_at_boot_password != "", - "WiFi SSID and password must be specified at build time!") - - defines += [ - "CONFIG_CHIP_APP_WIFI_CONNECT_AT_BOOT=1", - "CONFIG_CHIP_APP_WIFI_SSID=\"${wifi_auto_connect_at_boot_ssid}\"", - "CONFIG_CHIP_APP_WIFI_PASSWORD=\"${wifi_auto_connect_at_boot_password}\"", - ] - - include_dirs += [ "${common_example_dir}/wifi_connect/include" ] - sources += [ "${common_example_dir}/wifi_connect/source/WifiConnect.cpp" ] - } - - if (enable_ota_provider) { - defines += [ "CONFIG_CHIP_OTA_PROVIDER=1" ] - - include_dirs += [ - "${common_example_dir}/ota_provider/include", - "${common_example_dir}/ota_provider/ota-provider-common", - ] - - sources += [ - "${common_example_dir}/ota_provider/ota-provider-common/RTBdxOtaSender.cpp", - "${common_example_dir}/ota_provider/ota-provider-common/RTOTAProviderExample.cpp", - "${common_example_dir}/ota_provider/source/OTAProvider.cpp", - ] - - deps += [ - "${chip_root}/src/app/server", - "${chip_root}/src/protocols/bdx", - "${chip_root}/third_party/jsoncpp", - ] - } - - # In case a dedicated assert function needs to be supported the flag sdk_fsl_assert_support should be set to false - # The would add to the build a dedicated application assert implementation. - if (!sdk_fsl_assert_support) { - sources += [ "${common_example_dir}/app_assert/source/AppAssert.cpp" ] - } - - cflags = [ "-Wconversion" ] - - ldscript = - "${example_platform_dir}/app/ldscripts/MIMXRT1062xxxxx_flexspi_nor.ld" - - inputs = [ ldscript ] - - ldflags = [ - "-T" + rebase_path(ldscript, root_build_dir), - "-fno-common", - "-Wl,--defsym=__stack_size__=2048", - "-ffreestanding", - "-fno-builtin", - "-mapcs", - "-u qspiflash_config", - "-u image_vector_table", - "-u boot_data", - "-u dcd_data", - "-Wl,-print-memory-usage", - "-Wl,--no-warn-rwx-segments", - ] - - if (evkname == "evkcmimxrt1060") { - ldflags += [ "-Wl,--defsym=gFlashSize_d=0x1000000" ] - } - if (enable_ota_provider) { - # As the OTA file will be stored in the littlefs file system, it is required to increase the size of the file system - # To be able to store an OTA file with a MAX size of 640K, - # it recommended to size the file system with: - # 161 sectors of 4K => reserved for the OTA file - # 32 sectors of 4K => reserved for Matter/OT/BLE settings storage - ldflags += [ "-Wl,--defsym=gNVMSectorCountLink_d=193" ] - } - - if (chip_enable_ota_requestor) { - # If OTA build flag is enabled, - # we would need to reserve enough space for the bootloader (MCUBoot) - # MCUBoot requires 0x11000 Bytes to be reserved at the base of the flash - # Consequently, some sections will need to be shifted - ldflags += [ "-Wl,--defsym=__m_mcuboot_size__=0x40000" ] - } - - output_dir = root_out_dir -} - -group("rt1060") { - deps = [ ":thermostat" ] -} - -group("default") { - deps = [ ":rt1060" ] -} diff --git a/examples/thermostat/nxp/rt/rt1060/args.gni b/examples/thermostat/nxp/rt/rt1060/args.gni deleted file mode 100644 index d3fc29a80c4..00000000000 --- a/examples/thermostat/nxp/rt/rt1060/args.gni +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2023 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") - -# Set to true to customized BLE advertising data at application layer, -# instead of default Zephyr BLE manager implementation advertising data -ble_adv_data_custom = true - -# SDK target definitions -nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") -nxp_sdk_driver_target = get_label_info(":sdk_driver", "label_no_toolchain") diff --git a/examples/thermostat/nxp/rt/rt1060/build_overrides b/examples/thermostat/nxp/rt/rt1060/build_overrides deleted file mode 120000 index f10867042f4..00000000000 --- a/examples/thermostat/nxp/rt/rt1060/build_overrides +++ /dev/null @@ -1 +0,0 @@ -../../../../build_overrides \ No newline at end of file diff --git a/examples/thermostat/nxp/rt/rt1060/include/config/CHIPProjectConfig.h b/examples/thermostat/nxp/rt/rt1060/include/config/CHIPProjectConfig.h deleted file mode 100644 index 61be0867102..00000000000 --- a/examples/thermostat/nxp/rt/rt1060/include/config/CHIPProjectConfig.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2020 Google LLC. - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Example project configuration file for CHIP. - * - * This is a place to put application or project-specific overrides - * to the default configuration values for general CHIP features. - * - */ - -#pragma once - -/* - * Tells to the platform Factory Data Provider whether to use the example configuration or real/provisioned data. - */ -#ifndef CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -#define CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA 0 -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID - * - * 0xFFF1: Test vendor. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1 - -/** - * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID - * - */ -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8005 - -#if !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -// Use a default pairing code if one hasn't been provisioned in flash. -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 -#endif - -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 -#endif - -// Use a default pairing code if one hasn't been provisioned in flash. -#define CHIP_DEVICE_CONFIG_USE_TEST_PAIRING_CODE "CHIPUS" - -/** - * CHIP_DEVICE_CONFIG_USE_TEST_SERIAL_NUMBER - * - * Enables the use of a hard-coded default serial number if none - * is found in CHIP NV storage. - */ -#define CHIP_DEVICE_CONFIG_USE_TEST_SERIAL_NUMBER "DUMMY_SN" - -#endif /* !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA */ - -/** - * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION - * - * The hardware version number assigned to device or product by the device vendor. This - * number is scoped to the device product id, and typically corresponds to a revision of the - * physical device, a change to its packaging, and/or a change to its marketing presentation. - * This value is generally *not* incremented for device software versions. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 100 - -#ifndef CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING "v0.1.0" -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING - * - * A string identifying the software version running on the device. - * CHIP currently expects the software version to be in the format - * {MAJOR_VERSION}.0d{MINOR_VERSION} - */ -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION NXP_CONFIG_DEVICE_SOFTWARE_VERSION -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "NXP Semiconductors" -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "NXP Demo App" -#endif - -#ifndef CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION -//-> format_version = 1 -//-> vendor_id = 0xFFF1 -//-> product_id_array = [ 0x8000, 0x8001, 0x8002, 0x8003, 0x8004, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009, 0x800A, 0x800B, -// 0x800C, 0x800D, 0x800E, 0x800F, 0x8010, 0x8011, 0x8012, 0x8013, 0x8014, 0x8015, 0x8016, 0x8017, 0x8018, 0x8019, 0x801A, -// 0x801B, 0x801C, 0x801D, 0x801E, 0x801F, 0x8020, 0x8021, 0x8022, 0x8023, 0x8024, 0x8025, 0x8026, 0x8027, 0x8028, 0x8029, -// 0x802A, 0x802B, 0x802C, 0x802D, 0x802E, 0x802F, 0x8030, 0x8031, 0x8032, 0x8033, 0x8034, 0x8035, 0x8036, 0x8037, 0x8038, -// 0x8039, 0x803A, 0x803B, 0x803C, 0x803D, 0x803E, 0x803F, 0x8040, 0x8041, 0x8042, 0x8043, 0x8044, 0x8045, 0x8046, 0x8047, -// 0x8048, 0x8049, 0x804A, 0x804B, 0x804C, 0x804D, 0x804E, 0x804F, 0x8050, 0x8051, 0x8052, 0x8053, 0x8054, 0x8055, 0x8056, -// 0x8057, 0x8058, 0x8059, 0x805A, 0x805B, 0x805C, 0x805D, 0x805E, 0x805F, 0x8060, 0x8061, 0x8062, 0x8063 ] -//-> device_type_id = 0x0016 -//-> certificate_id = "ZIG20142ZB330003-24" -//-> security_level = 0 -//-> security_information = 0 -//-> version_number = 0x2694 -//-> certification_type = 0 -//-> dac_origin_vendor_id is not present -//-> dac_origin_product_id is not present -#define CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION \ - { \ - 0x30, 0x82, 0x02, 0x19, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0x0a, 0x30, \ - 0x82, 0x02, 0x06, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, \ - 0x02, 0x01, 0x30, 0x82, 0x01, 0x71, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, \ - 0x01, 0x62, 0x04, 0x82, 0x01, 0x5e, 0x15, 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, \ - 0x05, 0x01, 0x80, 0x05, 0x02, 0x80, 0x05, 0x03, 0x80, 0x05, 0x04, 0x80, 0x05, 0x05, 0x80, 0x05, 0x06, 0x80, 0x05, \ - 0x07, 0x80, 0x05, 0x08, 0x80, 0x05, 0x09, 0x80, 0x05, 0x0a, 0x80, 0x05, 0x0b, 0x80, 0x05, 0x0c, 0x80, 0x05, 0x0d, \ - 0x80, 0x05, 0x0e, 0x80, 0x05, 0x0f, 0x80, 0x05, 0x10, 0x80, 0x05, 0x11, 0x80, 0x05, 0x12, 0x80, 0x05, 0x13, 0x80, \ - 0x05, 0x14, 0x80, 0x05, 0x15, 0x80, 0x05, 0x16, 0x80, 0x05, 0x17, 0x80, 0x05, 0x18, 0x80, 0x05, 0x19, 0x80, 0x05, \ - 0x1a, 0x80, 0x05, 0x1b, 0x80, 0x05, 0x1c, 0x80, 0x05, 0x1d, 0x80, 0x05, 0x1e, 0x80, 0x05, 0x1f, 0x80, 0x05, 0x20, \ - 0x80, 0x05, 0x21, 0x80, 0x05, 0x22, 0x80, 0x05, 0x23, 0x80, 0x05, 0x24, 0x80, 0x05, 0x25, 0x80, 0x05, 0x26, 0x80, \ - 0x05, 0x27, 0x80, 0x05, 0x28, 0x80, 0x05, 0x29, 0x80, 0x05, 0x2a, 0x80, 0x05, 0x2b, 0x80, 0x05, 0x2c, 0x80, 0x05, \ - 0x2d, 0x80, 0x05, 0x2e, 0x80, 0x05, 0x2f, 0x80, 0x05, 0x30, 0x80, 0x05, 0x31, 0x80, 0x05, 0x32, 0x80, 0x05, 0x33, \ - 0x80, 0x05, 0x34, 0x80, 0x05, 0x35, 0x80, 0x05, 0x36, 0x80, 0x05, 0x37, 0x80, 0x05, 0x38, 0x80, 0x05, 0x39, 0x80, \ - 0x05, 0x3a, 0x80, 0x05, 0x3b, 0x80, 0x05, 0x3c, 0x80, 0x05, 0x3d, 0x80, 0x05, 0x3e, 0x80, 0x05, 0x3f, 0x80, 0x05, \ - 0x40, 0x80, 0x05, 0x41, 0x80, 0x05, 0x42, 0x80, 0x05, 0x43, 0x80, 0x05, 0x44, 0x80, 0x05, 0x45, 0x80, 0x05, 0x46, \ - 0x80, 0x05, 0x47, 0x80, 0x05, 0x48, 0x80, 0x05, 0x49, 0x80, 0x05, 0x4a, 0x80, 0x05, 0x4b, 0x80, 0x05, 0x4c, 0x80, \ - 0x05, 0x4d, 0x80, 0x05, 0x4e, 0x80, 0x05, 0x4f, 0x80, 0x05, 0x50, 0x80, 0x05, 0x51, 0x80, 0x05, 0x52, 0x80, 0x05, \ - 0x53, 0x80, 0x05, 0x54, 0x80, 0x05, 0x55, 0x80, 0x05, 0x56, 0x80, 0x05, 0x57, 0x80, 0x05, 0x58, 0x80, 0x05, 0x59, \ - 0x80, 0x05, 0x5a, 0x80, 0x05, 0x5b, 0x80, 0x05, 0x5c, 0x80, 0x05, 0x5d, 0x80, 0x05, 0x5e, 0x80, 0x05, 0x5f, 0x80, \ - 0x05, 0x60, 0x80, 0x05, 0x61, 0x80, 0x05, 0x62, 0x80, 0x05, 0x63, 0x80, 0x18, 0x24, 0x03, 0x16, 0x2c, 0x04, 0x13, \ - 0x5a, 0x49, 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x34, \ - 0x24, 0x05, 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x94, 0x26, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7d, 0x30, 0x7b, 0x02, \ - 0x01, 0x03, 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, \ - 0xf5, 0x04, 0xf3, 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, \ - 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x24, 0xe5, \ - 0xd1, 0xf4, 0x7a, 0x7d, 0x7b, 0x0d, 0x20, 0x6a, 0x26, 0xef, 0x69, 0x9b, 0x7c, 0x97, 0x57, 0xb7, 0x2d, 0x46, 0x90, \ - 0x89, 0xde, 0x31, 0x92, 0xe6, 0x78, 0xc7, 0x45, 0xe7, 0xf6, 0x0c, 0x02, 0x21, 0x00, 0xf8, 0xaa, 0x2f, 0xa7, 0x11, \ - 0xfc, 0xb7, 0x9b, 0x97, 0xe3, 0x97, 0xce, 0xda, 0x66, 0x7b, 0xae, 0x46, 0x4e, 0x2b, 0xd3, 0xff, 0xdf, 0xc3, 0xcc, \ - 0xed, 0x7a, 0xa8, 0xca, 0x5f, 0x4c, 0x1a, 0x7c \ - } -#endif - -/** - * CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC - * - * Enables synchronizing the device's real time clock with a remote CHIP Time service - * using the CHIP Time Sync protocol. - */ -// #define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 1 - -/** - * CHIP_CONFIG_EVENT_LOGGING_WDM_OFFLOAD - * - * Select the ability to offload event logs to any interested subscribers using WDM. - */ -#define CHIP_CONFIG_EVENT_LOGGING_WDM_OFFLOAD 1 - -/** - * CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS - * - * Enable recording UTC timestamps. - */ -#define CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1 - -/** - * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE - * - * A size, in bytes, of the individual debug event logging buffer. - */ -#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512) - -/** - * CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE - * - * For a development build, set the default importance of events to be logged as Debug. - * Since debug is the lowest importance level, this means all standard, critical, info and - * debug importance level vi events get logged. - */ -#if BUILD_RELEASE -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Production -#else -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug -#endif // BUILD_RELEASE - -/* Increasing the retransmission interval of the MRP messages after subsequent failures */ -#ifndef CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL -#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32) -#endif diff --git a/examples/thermostat/nxp/rt/rt1060/third_party/connectedhomeip b/examples/thermostat/nxp/rt/rt1060/third_party/connectedhomeip deleted file mode 120000 index 305f2077ffe..00000000000 --- a/examples/thermostat/nxp/rt/rt1060/third_party/connectedhomeip +++ /dev/null @@ -1 +0,0 @@ -../../../../../.. \ No newline at end of file diff --git a/examples/thermostat/nxp/rt/rt1170/.gn b/examples/thermostat/nxp/rt/rt1170/.gn deleted file mode 100644 index 59dcfeb229a..00000000000 --- a/examples/thermostat/nxp/rt/rt1170/.gn +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) 2020 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") -import("//build_overrides/chip.gni") - -# The location of the build configuration file. -buildconfig = "${build_root}/config/BUILDCONFIG.gn" - -# CHIP uses angle bracket includes. -check_system_includes = true - -default_args = { - target_cpu = "arm" - target_os = "freertos" - - import("//args.gni") - - # Import common example GN args - import("${chip_root}/examples/platform/nxp/common/gn/args.gni") - - # Import default platform configs - import("${chip_root}/src/platform/nxp/rt/rt1170/args.gni") -} diff --git a/examples/thermostat/nxp/rt/rt1170/BUILD.gn b/examples/thermostat/nxp/rt/rt1170/BUILD.gn deleted file mode 100644 index eb1d53b8373..00000000000 --- a/examples/thermostat/nxp/rt/rt1170/BUILD.gn +++ /dev/null @@ -1,279 +0,0 @@ -# Copyright (c) 2021-2023 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/build.gni") -import("//build_overrides/chip.gni") -import("//build_overrides/nxp_sdk.gni") -import("//build_overrides/openthread.gni") -import("${chip_root}/src/platform/device.gni") - -#allows to get common NXP SDK gn options -import("${nxp_sdk_build_root}/nxp_sdk.gni") - -# Allows to get various RT gn options -import("${nxp_sdk_build_root}/${nxp_sdk_name}/rt_sdk.gni") - -import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") -import( - "${nxp_sdk_build_root}/${nxp_sdk_name}/${rt_platform}/${rt_platform}.gni") -import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") - -assert(current_os == "freertos") -assert(target_os == "freertos") -assert(nxp_platform == "rt/rt1170") - -declare_args() { - # Allows to connect to a predefine Wi-Fi network at boot - wifi_auto_connect_at_boot = false - wifi_auto_connect_at_boot_ssid = "" - wifi_auto_connect_at_boot_password = "" - - # Setup discriminator as argument - setup_discriminator = 3840 - - chip_with_diag_logs_demo = true -} - -example_platform_dir = - "${nxp_sdk_matter_support_root}/examples/platform/${nxp_platform}" -common_example_dir = "${chip_root}/examples/platform/nxp/common" - -app_common_folder = "thermostat/nxp/zap" - -# Create here the SDK instance. -# Particular sources/defines/includes could be added/changed depending on the target application. -rt_sdk("sdk") { - defines = [] - - cflags = [] - public_deps = [] - public_configs = [] - sources = [] - include_dirs = [] - - # Indicate paths to default board files - include_dirs += [ "${example_platform_dir}/board/" ] - sources += [ "${example_platform_dir}/board/pin_mux.c" ] - sources += [ "${example_platform_dir}/board/hardware_init.c" ] - sources += [ "${example_platform_dir}/board/clock_config.c" ] - sources += [ "${example_platform_dir}/board/board.c" ] - sources += [ "${example_platform_dir}/board/peripherals.c" ] - sources += [ "${example_platform_dir}/board/sdmmc_config.c" ] - sources += [ "${example_platform_dir}/board/wifi_bt_config.c" ] - - # Indicate the path to CHIPProjectConfig.h - include_dirs += [ "include/config" ] - - # Indicate the default path to FreeRTOSConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/freeRTOS" ] - - # Indicate the default path to OpenThreadConfig.h - include_dirs += [ "${example_platform_dir}/app/project_include/openthread" ] - - # For matter with BR feature, increase FreeRTOS heap size and enable TBR cluster - if (chip_enable_wifi && chip_enable_openthread) { - defines += [ - "configTOTAL_HEAP_SIZE=(size_t)(170 * 1024)", - "CHIP_DEVICE_CONFIG_ENABLE_TBR=1", - ] - } - defines += [ - "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", - ] -} - -# Create the SDK driver instance. -# Particular sources/defines/includes could be added to add other drivers not available in the default sdk driver template -rt1170_sdk_drivers("sdk_driver") { -} - -rt_executable("thermostat") { - output_name = "chip-rt1170-thermostat-example" - - defines = [ - "CONFIG_RENDEZVOUS_MODE=7", - "CONFIG_APP_FREERTOS_OS=1", - ] - - if (chip_enable_openthread) { - defines += [ "CONFIG_NET_L2_OPENTHREAD=1" ] - } - - if (chip_with_diag_logs_demo) { - defines += [ - "CONFIG_DIAG_LOGS_DEMO=1", - "CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE=1024", - ] - } - - include_dirs = [ - "../../common/main/include", - "../../common/main", - "${chip_root}/examples/all-clusters-app/all-clusters-common/include", - "${chip_root}/examples/providers/", - ] - - sources = [ - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp", - "${chip_root}/examples/providers/DeviceInfoProviderImpl.cpp", - "../../common/main/AppTask.cpp", - "../../common/main/DeviceCallbacks.cpp", - "../../common/main/ZclCallbacks.cpp", - "../../common/main/include/AppEvent.h", - "../../common/main/include/AppTask.h", - "../../common/main/include/DeviceCallbacks.h", - "../../common/main/main.cpp", - ] - - if (chip_enable_ble) { - defines += [ "APP_BT_DEVICE_NAME=\"NXP-ThermostatApp\"" ] - include_dirs += [ "${common_example_dir}/app_ble/include" ] - if (ble_adv_data_custom) { - # to customize BLE advertising data - defines += [ "CONFIG_CHIP_CUSTOM_BLE_ADV_DATA=1" ] - include_dirs += [ "${chip_root}/src/platform/nxp/common/ble_zephyr" ] - sources += - [ "${common_example_dir}/app_ble/source/BleZephyrManagerApp.cpp" ] - } else { - # Empty implementation, default matter advertising data - sources += [ - "${common_example_dir}/app_ble/source/BLEApplicationManagerEmpty.cpp", - ] - } - } - - if (chip_with_diag_logs_demo) { - include_dirs += [ - "${common_example_dir}/diagnostic_logs/include", - "${chip_root}", - ] - sources += [ - "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsDemo.cpp", - "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp", - ] - } - - # App common files - include_dirs += [ - "${common_example_dir}/icd/include", - "${common_example_dir}/matter_button/include", - "${common_example_dir}/matter_cli/include", - "${common_example_dir}/device_manager/include", - "${common_example_dir}/device_callbacks/include", - "${common_example_dir}/factory_data/include", - "${common_example_dir}/app_task/include", - ] - - sources += [ - "${common_example_dir}/app_task/source/AppTaskBase.cpp", - "${common_example_dir}/app_task/source/AppTaskFreeRTOS.cpp", - "${common_example_dir}/device_callbacks/source/CommonDeviceCallbacks.cpp", - "${common_example_dir}/device_manager/source/CHIPDeviceManager.cpp", - "${common_example_dir}/factory_data/source/AppFactoryDataDefaultImpl.cpp", - "${common_example_dir}/icd/source/ICDUtil.cpp", - "${common_example_dir}/matter_button/source/ButtonRegistrationEmpty.cpp", - ] - - deps = [ - "${chip_root}/examples/${app_common_folder}", - "${chip_root}/src/app/clusters/network-commissioning:network-commissioning", - "${chip_root}/src/setup_payload:onboarding-codes-utils", - ] - - if (nxp_enable_matter_cli) { - defines += [ "ENABLE_CHIP_SHELL" ] - deps += [ - "${chip_root}/examples/shell/shell_common:shell_common", - "${chip_root}/src/lib/shell:shell", - ] - sources += [ - "${common_example_dir}/matter_cli/source/AppCLIBase.cpp", - "${common_example_dir}/matter_cli/source/AppCLIFreeRTOS.cpp", - ] - } - - if (chip_enable_ota_requestor) { - include_dirs += [ "${common_example_dir}/ota_requestor/include" ] - sources += [ - "${common_example_dir}/ota_requestor/source/OTARequestorInitiator.cpp", - "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorCommon.cpp", - ] - } - - if (wifi_auto_connect_at_boot) { - assert(wifi_auto_connect_at_boot_ssid != "" && - wifi_auto_connect_at_boot_password != "", - "WiFi SSID and password must be specified at build time!") - - defines += [ - "CONFIG_CHIP_APP_WIFI_CONNECT_AT_BOOT=1", - "CONFIG_CHIP_APP_WIFI_SSID=\"${wifi_auto_connect_at_boot_ssid}\"", - "CONFIG_CHIP_APP_WIFI_PASSWORD=\"${wifi_auto_connect_at_boot_password}\"", - ] - - include_dirs += [ "${common_example_dir}/wifi_connect/include" ] - sources += [ "${common_example_dir}/wifi_connect/source/WifiConnect.cpp" ] - } - - # In case a dedicated assert function needs to be supported the flag sdk_fsl_assert_support should be set to false - # The would add to the build a dedicated application assert implementation. - if (!sdk_fsl_assert_support) { - sources += [ "${common_example_dir}/app_assert/source/AppAssert.cpp" ] - } - - cflags = [ "-Wconversion" ] - - ldscript = - "${example_platform_dir}/app/ldscripts/MIMXRT1176xxxxx_cm7_flexspi_nor.ld" - - inputs = [ ldscript ] - - ldflags = [ - "-T" + rebase_path(ldscript, root_build_dir), - "-fno-common", - "-Wl,--defsym=__stack_size__=2048", - "-ffreestanding", - "-fno-builtin", - "-mapcs", - "-u qspiflash_config", - "-u image_vector_table", - "-u boot_data", - "-u dcd_data", - "-Wl,-print-memory-usage", - "-Wl,--no-warn-rwx-segments", - ] - - if (chip_enable_ota_requestor) { - if (no_mcuboot) { - # If "no_mcuboot" is set to true, the application will be linked at the base of the flash. - print( - "Warning : The OTA Requestor is enabled without MCUBoot. This will prevent the application from applying software updates.") - } else { - # we need to reserve enough space for the bootloader (MCUBoot) - # MCUBoot requires 0x40000 Bytes to be reserved at the base of the flash - # Consequently, some sections will need to be shifted - ldflags += [ "-Wl,--defsym=__m_mcuboot_size__=0x40000" ] - } - } - - output_dir = root_out_dir -} - -group("rt1170") { - deps = [ ":thermostat" ] -} - -group("default") { - deps = [ ":rt1170" ] -} diff --git a/examples/thermostat/nxp/rt/rt1170/args.gni b/examples/thermostat/nxp/rt/rt1170/args.gni deleted file mode 100644 index d3fc29a80c4..00000000000 --- a/examples/thermostat/nxp/rt/rt1170/args.gni +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2023 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") - -# Set to true to customized BLE advertising data at application layer, -# instead of default Zephyr BLE manager implementation advertising data -ble_adv_data_custom = true - -# SDK target definitions -nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") -nxp_sdk_driver_target = get_label_info(":sdk_driver", "label_no_toolchain") diff --git a/examples/thermostat/nxp/rt/rt1170/build_overrides b/examples/thermostat/nxp/rt/rt1170/build_overrides deleted file mode 120000 index f10867042f4..00000000000 --- a/examples/thermostat/nxp/rt/rt1170/build_overrides +++ /dev/null @@ -1 +0,0 @@ -../../../../build_overrides \ No newline at end of file diff --git a/examples/thermostat/nxp/rt/rt1170/include/config/CHIPProjectConfig.h b/examples/thermostat/nxp/rt/rt1170/include/config/CHIPProjectConfig.h deleted file mode 100644 index 61be0867102..00000000000 --- a/examples/thermostat/nxp/rt/rt1170/include/config/CHIPProjectConfig.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2020 Google LLC. - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Example project configuration file for CHIP. - * - * This is a place to put application or project-specific overrides - * to the default configuration values for general CHIP features. - * - */ - -#pragma once - -/* - * Tells to the platform Factory Data Provider whether to use the example configuration or real/provisioned data. - */ -#ifndef CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -#define CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA 0 -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID - * - * 0xFFF1: Test vendor. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1 - -/** - * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID - * - */ -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8005 - -#if !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -// Use a default pairing code if one hasn't been provisioned in flash. -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 -#endif - -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 -#endif - -// Use a default pairing code if one hasn't been provisioned in flash. -#define CHIP_DEVICE_CONFIG_USE_TEST_PAIRING_CODE "CHIPUS" - -/** - * CHIP_DEVICE_CONFIG_USE_TEST_SERIAL_NUMBER - * - * Enables the use of a hard-coded default serial number if none - * is found in CHIP NV storage. - */ -#define CHIP_DEVICE_CONFIG_USE_TEST_SERIAL_NUMBER "DUMMY_SN" - -#endif /* !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA */ - -/** - * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION - * - * The hardware version number assigned to device or product by the device vendor. This - * number is scoped to the device product id, and typically corresponds to a revision of the - * physical device, a change to its packaging, and/or a change to its marketing presentation. - * This value is generally *not* incremented for device software versions. - */ -#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 100 - -#ifndef CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING "v0.1.0" -#endif - -/** - * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING - * - * A string identifying the software version running on the device. - * CHIP currently expects the software version to be in the format - * {MAJOR_VERSION}.0d{MINOR_VERSION} - */ -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION NXP_CONFIG_DEVICE_SOFTWARE_VERSION -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "NXP Semiconductors" -#endif - -#ifndef CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "NXP Demo App" -#endif - -#ifndef CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION -//-> format_version = 1 -//-> vendor_id = 0xFFF1 -//-> product_id_array = [ 0x8000, 0x8001, 0x8002, 0x8003, 0x8004, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009, 0x800A, 0x800B, -// 0x800C, 0x800D, 0x800E, 0x800F, 0x8010, 0x8011, 0x8012, 0x8013, 0x8014, 0x8015, 0x8016, 0x8017, 0x8018, 0x8019, 0x801A, -// 0x801B, 0x801C, 0x801D, 0x801E, 0x801F, 0x8020, 0x8021, 0x8022, 0x8023, 0x8024, 0x8025, 0x8026, 0x8027, 0x8028, 0x8029, -// 0x802A, 0x802B, 0x802C, 0x802D, 0x802E, 0x802F, 0x8030, 0x8031, 0x8032, 0x8033, 0x8034, 0x8035, 0x8036, 0x8037, 0x8038, -// 0x8039, 0x803A, 0x803B, 0x803C, 0x803D, 0x803E, 0x803F, 0x8040, 0x8041, 0x8042, 0x8043, 0x8044, 0x8045, 0x8046, 0x8047, -// 0x8048, 0x8049, 0x804A, 0x804B, 0x804C, 0x804D, 0x804E, 0x804F, 0x8050, 0x8051, 0x8052, 0x8053, 0x8054, 0x8055, 0x8056, -// 0x8057, 0x8058, 0x8059, 0x805A, 0x805B, 0x805C, 0x805D, 0x805E, 0x805F, 0x8060, 0x8061, 0x8062, 0x8063 ] -//-> device_type_id = 0x0016 -//-> certificate_id = "ZIG20142ZB330003-24" -//-> security_level = 0 -//-> security_information = 0 -//-> version_number = 0x2694 -//-> certification_type = 0 -//-> dac_origin_vendor_id is not present -//-> dac_origin_product_id is not present -#define CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION \ - { \ - 0x30, 0x82, 0x02, 0x19, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0x0a, 0x30, \ - 0x82, 0x02, 0x06, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, \ - 0x02, 0x01, 0x30, 0x82, 0x01, 0x71, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, \ - 0x01, 0x62, 0x04, 0x82, 0x01, 0x5e, 0x15, 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, \ - 0x05, 0x01, 0x80, 0x05, 0x02, 0x80, 0x05, 0x03, 0x80, 0x05, 0x04, 0x80, 0x05, 0x05, 0x80, 0x05, 0x06, 0x80, 0x05, \ - 0x07, 0x80, 0x05, 0x08, 0x80, 0x05, 0x09, 0x80, 0x05, 0x0a, 0x80, 0x05, 0x0b, 0x80, 0x05, 0x0c, 0x80, 0x05, 0x0d, \ - 0x80, 0x05, 0x0e, 0x80, 0x05, 0x0f, 0x80, 0x05, 0x10, 0x80, 0x05, 0x11, 0x80, 0x05, 0x12, 0x80, 0x05, 0x13, 0x80, \ - 0x05, 0x14, 0x80, 0x05, 0x15, 0x80, 0x05, 0x16, 0x80, 0x05, 0x17, 0x80, 0x05, 0x18, 0x80, 0x05, 0x19, 0x80, 0x05, \ - 0x1a, 0x80, 0x05, 0x1b, 0x80, 0x05, 0x1c, 0x80, 0x05, 0x1d, 0x80, 0x05, 0x1e, 0x80, 0x05, 0x1f, 0x80, 0x05, 0x20, \ - 0x80, 0x05, 0x21, 0x80, 0x05, 0x22, 0x80, 0x05, 0x23, 0x80, 0x05, 0x24, 0x80, 0x05, 0x25, 0x80, 0x05, 0x26, 0x80, \ - 0x05, 0x27, 0x80, 0x05, 0x28, 0x80, 0x05, 0x29, 0x80, 0x05, 0x2a, 0x80, 0x05, 0x2b, 0x80, 0x05, 0x2c, 0x80, 0x05, \ - 0x2d, 0x80, 0x05, 0x2e, 0x80, 0x05, 0x2f, 0x80, 0x05, 0x30, 0x80, 0x05, 0x31, 0x80, 0x05, 0x32, 0x80, 0x05, 0x33, \ - 0x80, 0x05, 0x34, 0x80, 0x05, 0x35, 0x80, 0x05, 0x36, 0x80, 0x05, 0x37, 0x80, 0x05, 0x38, 0x80, 0x05, 0x39, 0x80, \ - 0x05, 0x3a, 0x80, 0x05, 0x3b, 0x80, 0x05, 0x3c, 0x80, 0x05, 0x3d, 0x80, 0x05, 0x3e, 0x80, 0x05, 0x3f, 0x80, 0x05, \ - 0x40, 0x80, 0x05, 0x41, 0x80, 0x05, 0x42, 0x80, 0x05, 0x43, 0x80, 0x05, 0x44, 0x80, 0x05, 0x45, 0x80, 0x05, 0x46, \ - 0x80, 0x05, 0x47, 0x80, 0x05, 0x48, 0x80, 0x05, 0x49, 0x80, 0x05, 0x4a, 0x80, 0x05, 0x4b, 0x80, 0x05, 0x4c, 0x80, \ - 0x05, 0x4d, 0x80, 0x05, 0x4e, 0x80, 0x05, 0x4f, 0x80, 0x05, 0x50, 0x80, 0x05, 0x51, 0x80, 0x05, 0x52, 0x80, 0x05, \ - 0x53, 0x80, 0x05, 0x54, 0x80, 0x05, 0x55, 0x80, 0x05, 0x56, 0x80, 0x05, 0x57, 0x80, 0x05, 0x58, 0x80, 0x05, 0x59, \ - 0x80, 0x05, 0x5a, 0x80, 0x05, 0x5b, 0x80, 0x05, 0x5c, 0x80, 0x05, 0x5d, 0x80, 0x05, 0x5e, 0x80, 0x05, 0x5f, 0x80, \ - 0x05, 0x60, 0x80, 0x05, 0x61, 0x80, 0x05, 0x62, 0x80, 0x05, 0x63, 0x80, 0x18, 0x24, 0x03, 0x16, 0x2c, 0x04, 0x13, \ - 0x5a, 0x49, 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x34, \ - 0x24, 0x05, 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x94, 0x26, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7d, 0x30, 0x7b, 0x02, \ - 0x01, 0x03, 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, \ - 0xf5, 0x04, 0xf3, 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, \ - 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x24, 0xe5, \ - 0xd1, 0xf4, 0x7a, 0x7d, 0x7b, 0x0d, 0x20, 0x6a, 0x26, 0xef, 0x69, 0x9b, 0x7c, 0x97, 0x57, 0xb7, 0x2d, 0x46, 0x90, \ - 0x89, 0xde, 0x31, 0x92, 0xe6, 0x78, 0xc7, 0x45, 0xe7, 0xf6, 0x0c, 0x02, 0x21, 0x00, 0xf8, 0xaa, 0x2f, 0xa7, 0x11, \ - 0xfc, 0xb7, 0x9b, 0x97, 0xe3, 0x97, 0xce, 0xda, 0x66, 0x7b, 0xae, 0x46, 0x4e, 0x2b, 0xd3, 0xff, 0xdf, 0xc3, 0xcc, \ - 0xed, 0x7a, 0xa8, 0xca, 0x5f, 0x4c, 0x1a, 0x7c \ - } -#endif - -/** - * CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC - * - * Enables synchronizing the device's real time clock with a remote CHIP Time service - * using the CHIP Time Sync protocol. - */ -// #define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 1 - -/** - * CHIP_CONFIG_EVENT_LOGGING_WDM_OFFLOAD - * - * Select the ability to offload event logs to any interested subscribers using WDM. - */ -#define CHIP_CONFIG_EVENT_LOGGING_WDM_OFFLOAD 1 - -/** - * CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS - * - * Enable recording UTC timestamps. - */ -#define CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1 - -/** - * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE - * - * A size, in bytes, of the individual debug event logging buffer. - */ -#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512) - -/** - * CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE - * - * For a development build, set the default importance of events to be logged as Debug. - * Since debug is the lowest importance level, this means all standard, critical, info and - * debug importance level vi events get logged. - */ -#if BUILD_RELEASE -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Production -#else -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug -#endif // BUILD_RELEASE - -/* Increasing the retransmission interval of the MRP messages after subsequent failures */ -#ifndef CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL -#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32) -#endif diff --git a/examples/thermostat/nxp/rt/rt1170/third_party/connectedhomeip b/examples/thermostat/nxp/rt/rt1170/third_party/connectedhomeip deleted file mode 120000 index 305f2077ffe..00000000000 --- a/examples/thermostat/nxp/rt/rt1170/third_party/connectedhomeip +++ /dev/null @@ -1 +0,0 @@ -../../../../../.. \ No newline at end of file diff --git a/examples/thermostat/nxp/zap/thermostat_matter_br.matter b/examples/thermostat/nxp/zap/thermostat_matter_br.matter index 89930330e98..d0c013a69f7 100644 --- a/examples/thermostat/nxp/zap/thermostat_matter_br.matter +++ b/examples/thermostat/nxp/zap/thermostat_matter_br.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/thermostat/nxp/zap/thermostat_matter_eth.matter b/examples/thermostat/nxp/zap/thermostat_matter_eth.matter index dffcd231ac3..7713f0b6561 100644 --- a/examples/thermostat/nxp/zap/thermostat_matter_eth.matter +++ b/examples/thermostat/nxp/zap/thermostat_matter_eth.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/thermostat/nxp/zap/thermostat_matter_thread.matter b/examples/thermostat/nxp/zap/thermostat_matter_thread.matter index cdbe3aeb1fd..062352e60d1 100644 --- a/examples/thermostat/nxp/zap/thermostat_matter_thread.matter +++ b/examples/thermostat/nxp/zap/thermostat_matter_thread.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter b/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter index 99f26bbc711..0af56e6d3cd 100644 --- a/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter +++ b/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/thermostat/nxp/zephyr/CMakeLists.txt b/examples/thermostat/nxp/zephyr/CMakeLists.txt index 829869aa020..6c6970b1063 100644 --- a/examples/thermostat/nxp/zephyr/CMakeLists.txt +++ b/examples/thermostat/nxp/zephyr/CMakeLists.txt @@ -90,6 +90,13 @@ if(CONFIG_CHIP_OTA_REQUESTOR) ) endif() +if (CONFIG_CHIP_FACTORY_DATA) + target_sources(app PRIVATE + ${CHIP_ROOT}/src/platform/nxp/zephyr/FactoryDataProviderImpl.cpp + ${CHIP_ROOT}/src/platform/nxp/common/factory_data/legacy/FactoryDataProvider.cpp + ) +endif() + chip_configure_data_model(app ZAP_FILE ${ALL_CLUSTERS_COMMON_DIR}/../../thermostat/nxp/zap/thermostat_matter_wifi.zap ) diff --git a/examples/thermostat/qpg/zap/thermostaticRadiatorValve.matter b/examples/thermostat/qpg/zap/thermostaticRadiatorValve.matter index cd57d272e15..7b08e986615 100644 --- a/examples/thermostat/qpg/zap/thermostaticRadiatorValve.matter +++ b/examples/thermostat/qpg/zap/thermostaticRadiatorValve.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/thermostat/thermostat-common/thermostat.matter b/examples/thermostat/thermostat-common/thermostat.matter index c50c71ad947..b4763e1b415 100644 --- a/examples/thermostat/thermostat-common/thermostat.matter +++ b/examples/thermostat/thermostat-common/thermostat.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/thread-br-app/thread-br-common/thread-br-app.matter b/examples/thread-br-app/thread-br-common/thread-br-app.matter index c1710efe76c..a6f8a04cd0f 100644 --- a/examples/thread-br-app/thread-br-common/thread-br-app.matter +++ b/examples/thread-br-app/thread-br-common/thread-br-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/tv-app/tv-common/tv-app.matter b/examples/tv-app/tv-common/tv-app.matter index 5cc5b8c40bf..4f9fb4ad53a 100644 --- a/examples/tv-app/tv-common/tv-app.matter +++ b/examples/tv-app/tv-common/tv-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter b/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter index 15ef2cd628d..63c00682130 100644 --- a/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter +++ b/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/virtual-device-app/virtual-device-common/virtual-device-app.matter b/examples/virtual-device-app/virtual-device-common/virtual-device-app.matter index 47494ed7a64..86b69af914c 100644 --- a/examples/virtual-device-app/virtual-device-common/virtual-device-app.matter +++ b/examples/virtual-device-app/virtual-device-common/virtual-device-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/water-leak-detector-app/water-leak-detector-common/water-leak-detector-app.matter b/examples/water-leak-detector-app/water-leak-detector-common/water-leak-detector-app.matter index fdd1da82fd4..2b6b3882833 100644 --- a/examples/water-leak-detector-app/water-leak-detector-common/water-leak-detector-app.matter +++ b/examples/water-leak-detector-app/water-leak-detector-common/water-leak-detector-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/examples/window-app/common/window-app.matter b/examples/window-app/common/window-app.matter index 5e0833b9212..c0869c6499c 100644 --- a/examples/window-app/common/window-app.matter +++ b/examples/window-app/common/window-app.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index 08d30d37180..d0f7ff867ee 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -543,8 +543,8 @@ def BuildNxpTarget(): target.AppendModifier(name="matter-shell", enable_shell=True) target.AppendModifier(name="factory-build", enable_factory_data_build=True).OnlyIfRe('rt1060|rt1170|rw61x') target.AppendModifier(name="frdm", board_variant=NxpBoardVariant.FRDM).OnlyIfRe('rw61x|mcxw71|mcxw72') - target.AppendModifier(name="cmake", build_system=NxpBuildSystem.CMAKE).ExceptIfRe( - 'laundry-washer').OnlyIfRe('rt1060|rt1170|rw61x|mcxw71|mcxw72') + target.AppendModifier(name="gn", build_system=NxpBuildSystem.GN).OnlyIfRe( + 'thermostat|contact-sensor').OnlyIfRe('rw61x|mcxw72').OnlyIfRe('freertos') target.AppendModifier(name="evkc", board_variant=NxpBoardVariant.EVKC).OnlyIfRe('rt1060') target.AppendModifier(name="iw416", iw416_transceiver=True).OnlyIfRe('rt1060') target.AppendModifier(name="w8801", w8801_transceiver=True).OnlyIfRe('rt1060') diff --git a/scripts/build/builders/nxp.py b/scripts/build/builders/nxp.py index da9d25394a1..c233d63be7d 100644 --- a/scripts/build/builders/nxp.py +++ b/scripts/build/builders/nxp.py @@ -167,7 +167,7 @@ def __init__(self, board: NxpBoard = NxpBoard.MCXW71, board_variant: NxpBoardVariant = None, os_env: NxpOsUsed = NxpOsUsed.FREERTOS, - build_system: NxpBuildSystem = NxpBuildSystem.GN, + build_system: NxpBuildSystem = NxpBuildSystem.CMAKE, low_power: bool = False, smu2: bool = False, enable_factory_data: bool = False, @@ -339,16 +339,6 @@ def GnBuildArgs(self): flag_board_variant = "board_version=\"frdm\"" args.append(flag_board_variant) - if self.iw416_transceiver: - args.append('iw416_transceiver=true') - - if self.w8801_transceiver: - # BLE not supported on this transceiver - args.append('w8801_transceiver=true chip_enable_ble=false') - - if self.iwx12_transceiver: - args.append('iwx12_transceiver=true') - return args def CmakeBuildFlags(self): diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt index 275108fedec..a5ea25dd461 100644 --- a/scripts/build/testdata/all_targets_linux_x64.txt +++ b/scripts/build/testdata/all_targets_linux_x64.txt @@ -13,7 +13,7 @@ linux-{arm64,x64}-{address-resolve-tool,air-purifier,air-quality-sensor,all-clus linux-x64-efr32-test-runner[-clang] imx-{all-clusters-app,all-clusters-minimal-app,chip-tool,lighting-app,ota-provider-app,thermostat}[-release][-trusty] infineon-psoc6-{all-clusters,all-clusters-minimal,light,lock}[-ota][-trustm][-updateimage] -nxp-{mcxw71,mcxw72,rt1060,rt1170,rw61x}-{freertos,zephyr}-{all-clusters,contact-sensor,laundry-washer,lighting,lock-app,thermostat,unit-test}[-cmake][-dac-conversion][-ethernet][-evkc][-factory][-factory-build][-frdm][-iw416][-iw610][-iwx12][-lit][-log-all][-log-error][-log-none][-log-progress][-low-power][-matter-shell][-mtd][-no-ble][-ota][-rotating-id][-se05x][-smu2][-sw-v2][-thread][-w8801][-wifi] +nxp-{mcxw71,mcxw72,rt1060,rt1170,rw61x}-{freertos,zephyr}-{all-clusters,contact-sensor,laundry-washer,lighting,lock-app,thermostat,unit-test}[-dac-conversion][-ethernet][-evkc][-factory][-factory-build][-frdm][-gn][-iw416][-iw610][-iwx12][-lit][-log-all][-log-error][-log-none][-log-progress][-low-power][-matter-shell][-mtd][-no-ble][-ota][-rotating-id][-se05x][-smu2][-sw-v2][-thread][-w8801][-wifi] nrf-{nrf52840dk,nrf52840dongle,nrf5340dk}-{all-clusters,all-clusters-minimal,light,light-switch,lock,pump,pump-controller,shell,window-covering}[-rpc] nrf-native-sim-tests nuttx-x64-light diff --git a/scripts/setup/constraints.txt b/scripts/setup/constraints.txt index fe050463894..389bb012f3a 100644 --- a/scripts/setup/constraints.txt +++ b/scripts/setup/constraints.txt @@ -292,3 +292,7 @@ setuptools==68.0.0 # Higher versions depend on proto-plus, which break # nanopb code generation (due to name conflict of the 'proto' module) google-api-core==2.17.0 + +# pydantic-core < 2.20 uses PyO3 0.21.x which does not support Python 3.13+ +# See: https://github.com/pydantic/pydantic/issues/11524 +pydantic-core>=2.20.0,<3.0.0; python_version >= "3.13" diff --git a/scripts/spec_xml/generate_spec_xml.py b/scripts/spec_xml/generate_spec_xml.py index 34577c30846..7b2392d7aea 100755 --- a/scripts/spec_xml/generate_spec_xml.py +++ b/scripts/spec_xml/generate_spec_xml.py @@ -28,7 +28,7 @@ import paths from lxml import etree -from matter.testing.conformance import ConformanceDecision +from matter.testing.conformance import EMPTY_CLUSTER_GLOBAL_ATTRIBUTES, ConformanceDecision from matter.testing.spec_parsing import build_xml_clusters, build_xml_device_types logging.basicConfig(level=logging.DEBUG, format="[%(levelname)s] %(message)s") @@ -43,22 +43,7 @@ CURRENT_IN_PROGRESS_DEFINES = [ - "access-closure", - "cameras", - "closures", - "electrical-grid-conditions", - "energy-mtrid", - "energy-price", - "energy-tariff", - "irrigation-system", - "metering", - "nfcCommissioning", - "q-phase-2", - "rvc-direct-mode", - "rvc-go-home", - "soil-sensor", - "temperature-sensor-with-screen", - "tls" + "cameras" ] @@ -156,7 +141,7 @@ def main(scraper, spec_root, output_dir, dry_run, include_in_progress, skip_scra dump_json_ids(output_dir) dump_ids_from_data_model_dirs() # Update all the files in the python wheels - generate_data_model_xmls_gni.generate_gni_file() + generate_data_model_xmls_gni.generate_dm_gni_file() def scrape_all(scraper, spec_root, output_dir, dry_run, include_in_progress): @@ -413,10 +398,10 @@ def cluster_support_str(c): def device_type_support_str(d): logging.info(f"checking device type for {d.name} for {dir}") dt_server_mandatory = [id for id, requirement in d.server_clusters.items() if requirement.conformance( - [], 0, 0).decision == ConformanceDecision.MANDATORY] + EMPTY_CLUSTER_GLOBAL_ATTRIBUTES).decision == ConformanceDecision.MANDATORY] server_provisional = [clusters[c].name for c in dt_server_mandatory if clusters[c].is_provisional] dt_client_mandatory = [id for id, requirement in d.client_clusters.items( - ) if requirement.conformance([], 0, 0).decision == ConformanceDecision.MANDATORY] + ) if requirement.conformance(EMPTY_CLUSTER_GLOBAL_ATTRIBUTES).decision == ConformanceDecision.MANDATORY] client_provisional = [clusters[c].name for c in dt_client_mandatory if clusters[c].is_provisional] if server_provisional or client_provisional: logging.info( diff --git a/scripts/spec_xml/spec_revision_diff_summary.py b/scripts/spec_xml/spec_revision_diff_summary.py index adfc93a0339..4e934bf9db9 100644 --- a/scripts/spec_xml/spec_revision_diff_summary.py +++ b/scripts/spec_xml/spec_revision_diff_summary.py @@ -22,7 +22,7 @@ import click -from matter.testing.conformance import ConformanceDecision +from matter.testing.conformance import EMPTY_CLUSTER_GLOBAL_ATTRIBUTES, ConformanceDecision from matter.testing.spec_parsing import PrebuiltDataModelDirectory, build_xml_clusters, build_xml_device_types @@ -119,7 +119,7 @@ def diff_device_types(prior_revision: PrebuiltDataModelDirectory, new_revision: def _get_provisional(items): - return [e.name for e in items if e.conformance(0, [], []).decision == ConformanceDecision.PROVISIONAL] + return [e.name for e in items if e.conformance(EMPTY_CLUSTER_GLOBAL_ATTRIBUTES).decision == ConformanceDecision.PROVISIONAL] def get_all_provisional_clusters(new_revision: PrebuiltDataModelDirectory): diff --git a/scripts/tests/chiptest/test_definition.py b/scripts/tests/chiptest/test_definition.py index c82175eda03..f688af87de0 100644 --- a/scripts/tests/chiptest/test_definition.py +++ b/scripts/tests/chiptest/test_definition.py @@ -21,6 +21,7 @@ import threading import time import typing +from collections.abc import Iterable from dataclasses import dataclass, field from datetime import datetime from enum import Enum, auto @@ -65,7 +66,7 @@ def start(self, options=None): # Make sure to assign self.process before we do any operations that # might fail, so attempts to kill us on failure actually work. self.process, self.outpipe, _ = self.__startServer() - self.waitForAnyAdvertisement() + self.waitForApplicationUp() self.__updateSetUpCode() with self.cv_stopped: self.stopped = False @@ -97,11 +98,14 @@ def factoryReset(self): return True - def waitForAnyAdvertisement(self): - self.__waitFor("mDNS service published:", self.process, self.outpipe) + def waitForApplicationUp(self): + # Watch for both mDNS advertisement start as well as event loop start. + # These two messages can appear in any order depending on the implementation. + # Waiting for both makes the startup detection more robust. + self.__waitFor(["mDNS service published:", "APP STATUS: Starting event loop"]) - def waitForMessage(self, message, timeoutInSeconds=10): - self.__waitFor(message, self.process, self.outpipe, timeoutInSeconds) + def waitForMessage(self, message: str, timeoutInSeconds: int = 10): + self.__waitFor([message], timeoutInSeconds=timeoutInSeconds) return True def kill(self): @@ -142,30 +146,38 @@ def __startServer(self): self.kvsPathSet.add(value) return self.runner.RunSubprocess(app_cmd, name='APP ', wait=False) - def __waitFor(self, waitForString, server_process, outpipe, timeoutInSeconds=10): - logging.debug('Waiting for %s' % waitForString) + def __waitFor(self, patterns: Iterable[str], timeoutInSeconds: int = 10): + """ + Wait for all provided pattern strings to appear in the process output pipe (capture log). + """ + logging.debug('Waiting for all patterns %r', patterns) start_time = time.monotonic() - ready, self.lastLogIndex = outpipe.CapturedLogContains( - waitForString, self.lastLogIndex) - if ready: - self.lastLogIndex += 1 - - while not ready: - if server_process.poll() is not None: - died_str = ('Server died while waiting for %s, returncode %d' % - (waitForString, server_process.returncode)) + + def allPatternsFound() -> int | None: + lastLogIndex = self.lastLogIndex + for p in patterns: + found, index = self.outpipe.CapturedLogContains(p, self.lastLogIndex) + if not found: + return None + lastLogIndex = max(lastLogIndex, index) + + return lastLogIndex + + lastLogIndex = allPatternsFound() + while lastLogIndex is None: + if self.process.poll() is not None: + died_str = f'Server died while waiting for {patterns!r}, returncode {self.process.returncode}' logging.error(died_str) raise Exception(died_str) if time.monotonic() - start_time > timeoutInSeconds: - raise Exception('Timeout while waiting for %s' % waitForString) + raise Exception(f'Timeout while waiting for {patterns!r}') time.sleep(0.1) - ready, self.lastLogIndex = outpipe.CapturedLogContains( - waitForString, self.lastLogIndex) - if ready: - self.lastLogIndex += 1 - logging.debug('Success waiting for: %s' % waitForString) + lastLogIndex = allPatternsFound() + + self.lastLogIndex = lastLogIndex + 1 + logging.debug('Success waiting for: %r', patterns) def __updateSetUpCode(self): qrLine = self.outpipe.FindLastMatchingLine('.*SetupQRCode: *\\[(.*)]') @@ -193,6 +205,7 @@ def __terminateProcess(self): self.process.wait(10) self.process = None self.outpipe = None + self.lastLogIndex = 0 return True diff --git a/scripts/tools/check_includes_config.py b/scripts/tools/check_includes_config.py index 787bca9ea6f..59c35163880 100644 --- a/scripts/tools/check_includes_config.py +++ b/scripts/tools/check_includes_config.py @@ -137,17 +137,20 @@ 'src/app/clusters/media-playback-server/media-playback-delegate.h': {'list'}, 'src/app/clusters/target-navigator-server/target-navigator-delegate.h': {'list'}, # WebRTCTransportProvider is for Camera and is intended to run on devices that are capable of handling these types. - 'src/app/clusters/webrtc-transport-provider-server/webrtc-transport-provider-server.h': {'string', 'vector'}, + 'src/app/clusters/webrtc-transport-provider-server/WebRTCTransportProviderCluster.h': {'string', 'vector'}, + 'src/app/clusters/webrtc-transport-provider-server/WebRTCTransportProviderCluster.cpp': {'set'}, # Camera AV Stream Management and Camera AV Settings User Level Management clusters are expected to run on resource-capable devices - 'src/app/clusters/camera-av-stream-management-server/camera-av-stream-management-server.h': {'vector'}, - 'src/app/clusters/camera-av-stream-management-server/camera-av-stream-management-server.cpp': {'set'}, - 'src/app/clusters/camera-av-settings-user-level-management-server/camera-av-settings-user-level-management-server.h': {'string', 'vector'}, - 'src/app/clusters/webrtc-transport-requestor-server/webrtc-transport-requestor-cluster.h': {'string', 'vector'}, + 'src/app/clusters/camera-av-stream-management-server/CameraAVStreamManagementCluster.h': {'vector'}, + 'src/app/clusters/camera-av-stream-management-server/CameraAVStreamManagementCluster.cpp': {'set'}, + 'src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementCluster.h': {'string', 'vector'}, + 'src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementConstants.h': {'string', 'vector'}, + 'src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementLogic.h': {'string', 'vector'}, + 'src/app/clusters/webrtc-transport-requestor-server/WebRTCTransportRequestorCluster.h': {'string', 'vector'}, 'src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-server.h': {'vector'}, 'src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-delegate.h': {'vector'}, 'src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-storage.h': {'vector'}, - 'src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-logic.cpp': {'set'}, - 'src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-logic.h': {'vector'}, + 'src/app/clusters/push-av-stream-transport-server/PushAVStreamTransportLogic.cpp': {'set'}, + 'src/app/clusters/push-av-stream-transport-server/PushAVStreamTransportLogic.h': {'vector'}, 'src/app/clusters/zone-management-server/zone-management-server.h': {'vector'}, 'src/app/clusters/zone-management-server/zone-geometry.h': {'vector', 'set'}, 'src/credentials/attestation_verifier/FileAttestationTrustStore.h': {'vector'}, diff --git a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/CodeDrivenCallback.h b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/CodeDrivenCallback.h index d0f4a29f6fb..c900305a790 100644 --- a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/CodeDrivenCallback.h +++ b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/CodeDrivenCallback.h @@ -98,3 +98,15 @@ void MatterUserLabelClusterShutdownCallback(chip::EndpointId endpointId); void MatterBooleanStateClusterInitCallback(chip::EndpointId endpointId); void MatterBooleanStateClusterShutdownCallback(chip::EndpointId endpointId); + +void MatterChimeClusterInitCallback(chip::EndpointId endpointId); + +void MatterChimeClusterShutdownCallback(chip::EndpointId endpointId); + +void MatterTlsCertificateManagementClusterInitCallback(chip::EndpointId endpointId); + +void MatterTlsCertificateManagementClusterShutdownCallback(chip::EndpointId endpointId); + +void MatterTlsClientManagementClusterInitCallback(chip::EndpointId endpointId); + +void MatterTlsClientManagementClusterShutdownCallback(chip::EndpointId endpointId); diff --git a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/CodeDrivenInitShutdown.cpp b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/CodeDrivenInitShutdown.cpp index 413bba553bd..f8887e17764 100644 --- a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/CodeDrivenInitShutdown.cpp +++ b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/CodeDrivenInitShutdown.cpp @@ -84,6 +84,15 @@ void MatterClusterServerInitCallback(EndpointId endpoint, ClusterId clusterId) case app::Clusters::BooleanState::Id: MatterBooleanStateClusterInitCallback(endpoint); break; + case app::Clusters::Chime::Id: + MatterChimeClusterInitCallback(endpoint); + break; + case app::Clusters::TlsCertificateManagement::Id: + MatterTlsCertificateManagementClusterInitCallback(endpoint); + break; + case app::Clusters::TlsClientManagement::Id: + MatterTlsClientManagementClusterInitCallback(endpoint); + break; } } @@ -148,5 +157,14 @@ void MatterClusterServerShutdownCallback(EndpointId endpoint, ClusterId clusterI case app::Clusters::BooleanState::Id: MatterBooleanStateClusterShutdownCallback(endpoint); break; + case app::Clusters::Chime::Id: + MatterChimeClusterShutdownCallback(endpoint); + break; + case app::Clusters::TlsCertificateManagement::Id: + MatterTlsCertificateManagementClusterShutdownCallback(endpoint); + break; + case app::Clusters::TlsClientManagement::Id: + MatterTlsClientManagementClusterShutdownCallback(endpoint); + break; } } diff --git a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h index f4d8f5d6e23..c1bf382983f 100644 --- a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h +++ b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h @@ -527,7 +527,7 @@ #define GENERATED_DEFAULTS_COUNT (27) // This is an array of EmberAfAttributeMinMaxValue structures. -#define GENERATED_MIN_MAX_DEFAULT_COUNT 47 +#define GENERATED_MIN_MAX_DEFAULT_COUNT 46 #define GENERATED_MIN_MAX_DEFAULTS \ { \ \ @@ -600,9 +600,6 @@ { (uint16_t) 0xFF, (uint16_t) 0x64, (uint16_t) 0xFF }, /* BallastFactorAdjustment */ \ { (uint16_t) 0x0, (uint16_t) 0x0, (uint16_t) 0x1 }, /* LampAlarmMode */ \ \ - /* Endpoint: 1, Cluster: Chime (server) */ \ - { (uint16_t) 0x0, (uint16_t) 0x0, (uint16_t) 0xFF }, /* SelectedChime */ \ - \ /* Endpoint: 1, Cluster: Unit Testing (server) */ \ { (uint16_t) 0x46, (uint16_t) 0x14, (uint16_t) 0x64 }, /* range_restricted_int8u */ \ { (uint16_t) -0x14, (uint16_t) -0x28, (uint16_t) 0x32 }, /* range_restricted_int8s */ \ @@ -2485,8 +2482,8 @@ /* Endpoint: 1, Cluster: Chime (server) */ \ { ZAP_EMPTY_DEFAULT(), 0x00000000, 0, ZAP_TYPE(ARRAY), \ ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(READABLE) }, /* InstalledChimeSounds */ \ - { ZAP_MIN_MAX_DEFAULTS_INDEX(37), 0x00000001, 1, ZAP_TYPE(INT8U), \ - ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(WRITABLE) | \ + { ZAP_EMPTY_DEFAULT(), 0x00000001, 1, ZAP_TYPE(INT8U), \ + ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(WRITABLE) | \ ZAP_ATTRIBUTE_MASK(READABLE) }, /* SelectedChime */ \ { ZAP_EMPTY_DEFAULT(), 0x00000002, 1, ZAP_TYPE(BOOLEAN), \ ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(READABLE) }, /* Enabled */ \ @@ -2595,16 +2592,16 @@ ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(READABLE) }, /* enum_attr */ \ { ZAP_EMPTY_DEFAULT(), 0x00000025, 0, ZAP_TYPE(STRUCT), \ ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(READABLE) }, /* struct_attr */ \ - { ZAP_MIN_MAX_DEFAULTS_INDEX(38), 0x00000026, 1, ZAP_TYPE(INT8U), \ + { ZAP_MIN_MAX_DEFAULTS_INDEX(37), 0x00000026, 1, ZAP_TYPE(INT8U), \ ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE) | \ ZAP_ATTRIBUTE_MASK(READABLE) }, /* range_restricted_int8u */ \ - { ZAP_MIN_MAX_DEFAULTS_INDEX(39), 0x00000027, 1, ZAP_TYPE(INT8S), \ + { ZAP_MIN_MAX_DEFAULTS_INDEX(38), 0x00000027, 1, ZAP_TYPE(INT8S), \ ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE) | \ ZAP_ATTRIBUTE_MASK(READABLE) }, /* range_restricted_int8s */ \ - { ZAP_MIN_MAX_DEFAULTS_INDEX(40), 0x00000028, 2, ZAP_TYPE(INT16U), \ + { ZAP_MIN_MAX_DEFAULTS_INDEX(39), 0x00000028, 2, ZAP_TYPE(INT16U), \ ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE) | \ ZAP_ATTRIBUTE_MASK(READABLE) }, /* range_restricted_int16u */ \ - { ZAP_MIN_MAX_DEFAULTS_INDEX(41), 0x00000029, 2, ZAP_TYPE(INT16S), \ + { ZAP_MIN_MAX_DEFAULTS_INDEX(40), 0x00000029, 2, ZAP_TYPE(INT16S), \ ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE) | \ ZAP_ATTRIBUTE_MASK(READABLE) }, /* range_restricted_int16s */ \ { ZAP_EMPTY_DEFAULT(), 0x0000002A, 0, ZAP_TYPE(ARRAY), \ @@ -2684,16 +2681,16 @@ { ZAP_EMPTY_DEFAULT(), 0x00004025, 0, ZAP_TYPE(STRUCT), \ ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(READABLE) | \ ZAP_ATTRIBUTE_MASK(NULLABLE) }, /* nullable_struct */ \ - { ZAP_MIN_MAX_DEFAULTS_INDEX(42), 0x00004026, 1, ZAP_TYPE(INT8U), \ + { ZAP_MIN_MAX_DEFAULTS_INDEX(41), 0x00004026, 1, ZAP_TYPE(INT8U), \ ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(READABLE) | \ ZAP_ATTRIBUTE_MASK(NULLABLE) }, /* nullable_range_restricted_int8u */ \ - { ZAP_MIN_MAX_DEFAULTS_INDEX(43), 0x00004027, 1, ZAP_TYPE(INT8S), \ + { ZAP_MIN_MAX_DEFAULTS_INDEX(42), 0x00004027, 1, ZAP_TYPE(INT8S), \ ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(READABLE) | \ ZAP_ATTRIBUTE_MASK(NULLABLE) }, /* nullable_range_restricted_int8s */ \ - { ZAP_MIN_MAX_DEFAULTS_INDEX(44), 0x00004028, 2, ZAP_TYPE(INT16U), \ + { ZAP_MIN_MAX_DEFAULTS_INDEX(43), 0x00004028, 2, ZAP_TYPE(INT16U), \ ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(READABLE) | \ ZAP_ATTRIBUTE_MASK(NULLABLE) }, /* nullable_range_restricted_int16u */ \ - { ZAP_MIN_MAX_DEFAULTS_INDEX(45), 0x00004029, 2, ZAP_TYPE(INT16S), \ + { ZAP_MIN_MAX_DEFAULTS_INDEX(44), 0x00004029, 2, ZAP_TYPE(INT16S), \ ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(READABLE) | \ ZAP_ATTRIBUTE_MASK(NULLABLE) }, /* nullable_range_restricted_int16s */ \ { ZAP_EMPTY_DEFAULT(), 0x0000402A, 1, ZAP_TYPE(INT8U), \ @@ -2725,7 +2722,7 @@ ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(READABLE) }, /* OnTime */ \ { ZAP_SIMPLE_DEFAULT(0), 0x00004002, 2, ZAP_TYPE(INT16U), \ ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(READABLE) }, /* OffWaitTime */ \ - { ZAP_MIN_MAX_DEFAULTS_INDEX(46), 0x00004003, 1, ZAP_TYPE(ENUM8), \ + { ZAP_MIN_MAX_DEFAULTS_INDEX(45), 0x00004003, 1, ZAP_TYPE(ENUM8), \ ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(READABLE) | \ ZAP_ATTRIBUTE_MASK(NULLABLE) }, /* StartUpOnOff */ \ { ZAP_SIMPLE_DEFAULT(0x0001), 0x0000FFFC, 4, ZAP_TYPE(BITMAP32), ZAP_ATTRIBUTE_MASK(READABLE) }, /* FeatureMap */ \ diff --git a/src/BUILD.gn b/src/BUILD.gn index 14eb5e836c4..9667b669071 100644 --- a/src/BUILD.gn +++ b/src/BUILD.gn @@ -55,6 +55,9 @@ if (chip_build_tests) { "${chip_root}/src/app/clusters/access-control-server/tests", "${chip_root}/src/app/clusters/basic-information/tests", "${chip_root}/src/app/clusters/bindings/tests", + "${chip_root}/src/app/clusters/camera-av-settings-user-level-management-server/tests", + "${chip_root}/src/app/clusters/camera-av-stream-management-server/tests", + "${chip_root}/src/app/clusters/chime-server/tests", "${chip_root}/src/app/clusters/descriptor/tests", "${chip_root}/src/app/clusters/general-commissioning-server/tests", "${chip_root}/src/app/clusters/general-diagnostics-server/tests", @@ -65,6 +68,7 @@ if (chip_build_tests) { "${chip_root}/src/app/clusters/ethernet-network-diagnostics-server/tests", "${chip_root}/src/app/clusters/operational-credentials-server/tests", "${chip_root}/src/app/clusters/push-av-stream-transport-server/tests", + "${chip_root}/src/app/clusters/webrtc-transport-provider-server/tests", "${chip_root}/src/app/clusters/webrtc-transport-requestor-server/tests", "${chip_root}/src/app/clusters/zone-management-server/tests", "${chip_root}/src/app/clusters/wifi-network-diagnostics-server/tests", @@ -99,9 +103,6 @@ if (chip_build_tests) { "${chip_root}/src/transport/retransmit/tests", "${chip_root}/src/transport/tests", "${chip_root}/src/tracing/esp32_diagnostics/tests", - "${chip_root}/src/app/clusters/push-av-stream-transport-server/tests", - "${chip_root}/src/app/clusters/webrtc-transport-requestor-server/tests", - "${chip_root}/src/app/clusters/zone-management-server/tests", "${chip_root}/src/lib/dnssd/minimal_mdns/core/tests", "${chip_root}/src/lib/dnssd/minimal_mdns/responders/tests", "${chip_root}/src/lib/dnssd/minimal_mdns/tests", diff --git a/src/app/SpecificationDefinedRevisions.h b/src/app/SpecificationDefinedRevisions.h index 42eaa0d701a..9abdcd1e1df 100644 --- a/src/app/SpecificationDefinedRevisions.h +++ b/src/app/SpecificationDefinedRevisions.h @@ -50,7 +50,7 @@ inline constexpr uint16_t kDataModelRevision = 19; * See section 11.1.5.22. "SpecificationVersion Attribute" in "Service and * Device Management" chapter of the core Matter specification. */ -inline constexpr uint32_t kSpecificationVersion = 0x01050000; +inline constexpr uint32_t kSpecificationVersion = 0x01050100; } // namespace Revision } // namespace chip diff --git a/src/app/clusters/actions-server/actions-server.cpp b/src/app/clusters/actions-server/actions-server.cpp index 9e01a7041ce..87d971e8df4 100644 --- a/src/app/clusters/actions-server/actions-server.cpp +++ b/src/app/clusters/actions-server/actions-server.cpp @@ -39,7 +39,7 @@ ActionsServer::~ActionsServer() void ActionsServer::Shutdown() { - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); + TEMPORARY_RETURN_IGNORED CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); AttributeAccessInterfaceRegistry::Instance().Unregister(this); } @@ -170,7 +170,7 @@ void ActionsServer::HandleCommand(HandlerContext & handlerContext, FuncT func) if (actionIndex != kMaxActionListLength) { ActionStructStorage action; - mDelegate.ReadActionAtIndex(actionIndex, action); + TEMPORARY_RETURN_IGNORED mDelegate.ReadActionAtIndex(actionIndex, action); // Check if the command bit is set in the SupportedCommands of an ations. if (!(action.supportedCommands.Raw() & (1 << handlerContext.mRequestPath.mCommandId))) { diff --git a/src/app/clusters/application-launcher-server/application-launcher-server.cpp b/src/app/clusters/application-launcher-server/application-launcher-server.cpp index 632713b2676..b934abb1a25 100644 --- a/src/app/clusters/application-launcher-server/application-launcher-server.cpp +++ b/src/app/clusters/application-launcher-server/application-launcher-server.cpp @@ -262,7 +262,7 @@ bool emberAfApplicationLauncherClusterLaunchAppCallback(app::CommandHandler * co ChipLogError(Zcl, "ApplicationLauncher target app not found"); LauncherResponseType response; response.status = StatusEnum::kAppNotAvailable; - responder.Success(response); + TEMPORARY_RETURN_IGNORED responder.Success(response); return true; } @@ -297,7 +297,7 @@ bool emberAfApplicationLauncherClusterLaunchAppCallback(app::CommandHandler * co ChipLogProgress(Zcl, "ApplicationLauncher target app not found"); LauncherResponseType response; response.status = StatusEnum::kAppNotAvailable; - responder.Success(response); + TEMPORARY_RETURN_IGNORED responder.Success(response); return true; } #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED @@ -356,7 +356,7 @@ bool emberAfApplicationLauncherClusterStopAppCallback(app::CommandHandler * comm ChipLogError(Zcl, "ApplicationLauncher target app not loaded"); LauncherResponseType response; response.status = StatusEnum::kAppNotAvailable; - responder.Success(response); + TEMPORARY_RETURN_IGNORED responder.Success(response); return true; } @@ -445,7 +445,7 @@ bool emberAfApplicationLauncherClusterHideAppCallback(app::CommandHandler * comm ChipLogError(Zcl, "ApplicationLauncher target app not loaded"); LauncherResponseType response; response.status = StatusEnum::kAppNotAvailable; - responder.Success(response); + TEMPORARY_RETURN_IGNORED responder.Success(response); return true; } diff --git a/src/app/clusters/bindings/BindingManager.cpp b/src/app/clusters/bindings/BindingManager.cpp index cf3124e87d2..17bf48b9d6f 100644 --- a/src/app/clusters/bindings/BindingManager.cpp +++ b/src/app/clusters/bindings/BindingManager.cpp @@ -33,7 +33,7 @@ class BindingFabricTableDelegate : public chip::FabricTable::Delegate { if (iter->fabricIndex == fabricIndex) { - bindingTable.RemoveAt(iter); + TEMPORARY_RETURN_IGNORED bindingTable.RemoveAt(iter); } else { @@ -72,7 +72,7 @@ CHIP_ERROR Manager::Init(const ManagerInitParams & params) VerifyOrReturnError(params.mFabricTable != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(params.mStorage != nullptr, CHIP_ERROR_INVALID_ARGUMENT); mInitParams = params; - params.mFabricTable->AddFabricDelegate(&gFabricTableDelegate); + TEMPORARY_RETURN_IGNORED params.mFabricTable->AddFabricDelegate(&gFabricTableDelegate); Table::GetInstance().SetPersistentStorage(params.mStorage); CHIP_ERROR error = Table::GetInstance().LoadFromStorage(); if (error != CHIP_NO_ERROR) diff --git a/src/app/clusters/bindings/binding-cluster.cpp b/src/app/clusters/bindings/binding-cluster.cpp index f4f01be5a09..f5b2596674e 100644 --- a/src/app/clusters/bindings/binding-cluster.cpp +++ b/src/app/clusters/bindings/binding-cluster.cpp @@ -181,7 +181,7 @@ DataModel::ActionReturnStatus BindingCluster::WriteAttribute(const DataModel::Wr { if (bindingTableIter->type == Binding::MATTER_UNICAST_BINDING) { - Binding::Manager::GetInstance().UnicastBindingRemoved(bindingTableIter.GetIndex()); + TEMPORARY_RETURN_IGNORED Binding::Manager::GetInstance().UnicastBindingRemoved(bindingTableIter.GetIndex()); } ReturnErrorOnFailure(Binding::Table::GetInstance().RemoveAt(bindingTableIter)); } diff --git a/src/app/clusters/bindings/binding-table.cpp b/src/app/clusters/bindings/binding-table.cpp index ed98d72710a..47d579e9776 100644 --- a/src/app/clusters/bindings/binding-table.cpp +++ b/src/app/clusters/bindings/binding-table.cpp @@ -58,7 +58,8 @@ CHIP_ERROR Table::Add(const TableEntry & entry) } if (error != CHIP_NO_ERROR) { - mStorage->SyncDeleteKeyValue(DefaultStorageKeyAllocator::BindingTableEntry(newIndex).KeyName()); + TEMPORARY_RETURN_IGNORED mStorage->SyncDeleteKeyValue( + DefaultStorageKeyAllocator::BindingTableEntry(newIndex).KeyName()); } } if (error != CHIP_NO_ERROR) diff --git a/src/app/clusters/boolean-state-configuration-server/boolean-state-configuration-cluster.cpp b/src/app/clusters/boolean-state-configuration-server/boolean-state-configuration-cluster.cpp index ec583248e56..719a48c7ee5 100644 --- a/src/app/clusters/boolean-state-configuration-server/boolean-state-configuration-cluster.cpp +++ b/src/app/clusters/boolean-state-configuration-server/boolean-state-configuration-cluster.cpp @@ -336,7 +336,7 @@ CHIP_ERROR SuppressAlarms(EndpointId ep, BitMaskHandleSuppressAlarm(alarm); + TEMPORARY_RETURN_IGNORED delegate->HandleSuppressAlarm(alarm); } VerifyOrReturnError(Status::Success == AlarmsSuppressed::Get(ep, &alarmsSuppressed), attribute_error); @@ -414,7 +414,7 @@ bool emberAfBooleanStateConfigurationClusterEnableDisableAlarmCallback( if (!isDelegateNull(delegate)) { - delegate->HandleEnableDisableAlarms(alarms); + TEMPORARY_RETURN_IGNORED delegate->HandleEnableDisableAlarms(alarms); } VerifyOrExit(Status::Success == AlarmsActive::Get(ep, &alarmsActive), status.Emplace(Status::Failure)); diff --git a/src/app/clusters/camera-av-settings-user-level-management-server/BUILD.gn b/src/app/clusters/camera-av-settings-user-level-management-server/BUILD.gn index 18a77617554..d99dc9861d9 100644 --- a/src/app/clusters/camera-av-settings-user-level-management-server/BUILD.gn +++ b/src/app/clusters/camera-av-settings-user-level-management-server/BUILD.gn @@ -11,5 +11,33 @@ # 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. -group("camera-av-settings-user-level-management-server") { +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +source_set("camera-av-settings-user-level-management-server") { + sources = [ + "CameraAvSettingsUserLevelManagementCluster.cpp", + "CameraAvSettingsUserLevelManagementCluster.h", + "CameraAvSettingsUserLevelManagementLogic.cpp", + "CameraAvSettingsUserLevelManagementLogic.h", + ] + + deps = [ + "${chip_root}/src/lib/core", + "${chip_root}/src/lib/support", + ] + + public_deps = [ ":camera-av-settings-user-level-management-cluster" ] +} + +source_set("camera-av-settings-user-level-management-cluster") { + public_deps = [ + "${chip_root}/src/app:constants", + "${chip_root}/src/app:interaction-model", + "${chip_root}/src/app/data-model-provider", + "${chip_root}/src/app/persistence:singleton", + "${chip_root}/src/app/server", + "${chip_root}/src/app/server-cluster", + "${chip_root}/zzz_generated/app-common/clusters/CameraAvSettingsUserLevelManagement", + ] } diff --git a/src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementCluster.cpp b/src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementCluster.cpp new file mode 100644 index 00000000000..386dd4f535c --- /dev/null +++ b/src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementCluster.cpp @@ -0,0 +1,256 @@ +/** + * + * Copyright (c) 2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { + +using Protocols::InteractionModel::Status; +using namespace CameraAvSettingsUserLevelManagement; + +CHIP_ERROR +CameraAvSettingsUserLevelManagementCluster::AcceptedCommands(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) +{ + return mLogic.AcceptedCommands(builder); +} + +CHIP_ERROR CameraAvSettingsUserLevelManagementCluster::Attributes(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) +{ + return mLogic.Attributes(builder); +} + +CHIP_ERROR CameraAvSettingsUserLevelManagementCluster::Startup(ServerClusterContext & context) +{ + ReturnErrorOnFailure(DefaultServerCluster::Startup(context)); + + mLogic.SetMarkDirtyCallback([this](AttributeId attributeId) { MarkAttributeDirty(attributeId); }); + return mLogic.Startup(); +} +/** + * Helper Read functions for complex attribute types + */ +CHIP_ERROR CameraAvSettingsUserLevelManagementCluster::ReadAndEncodeMPTZPresets(AttributeValueEncoder & aEncoder) +{ + return aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR { + for (const auto & mptzPresets : mLogic.mMptzPresetHelpers) + { + // Get the details to encode from the preset helper + // + CameraAvSettingsUserLevelManagement::Structs::MPTZPresetStruct::Type presetStruct; + std::string name = mptzPresets.GetName(); + uint8_t preset = mptzPresets.GetPresetID(); + presetStruct.presetID = preset; + presetStruct.name = CharSpan(name.c_str(), name.size()); + presetStruct.settings = mptzPresets.GetMptzPosition(); + ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt: Encoding an instance of MPTZPresetStruct. ID = %d. Name = %s", + presetStruct.presetID, NullTerminated(presetStruct.name).c_str()); + ReturnErrorOnFailure(encoder.Encode(presetStruct)); + } + + return CHIP_NO_ERROR; + }); +} + +CHIP_ERROR CameraAvSettingsUserLevelManagementCluster::ReadAndEncodeDPTZStreams(AttributeValueEncoder & aEncoder) +{ + return aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR { + for (const auto & dptzStream : mLogic.mDptzStreams) + { + ReturnErrorOnFailure(encoder.Encode(dptzStream)); + } + + return CHIP_NO_ERROR; + }); +} + +DataModel::ActionReturnStatus +CameraAvSettingsUserLevelManagementCluster::ReadAttribute(const DataModel::ReadAttributeRequest & request, + AttributeValueEncoder & aEncoder) +{ + switch (request.path.mAttributeId) + { + case Attributes::FeatureMap::Id: + return aEncoder.Encode(mLogic.mFeatures); + case Attributes::MPTZPosition::Id: + return aEncoder.Encode(mLogic.mMptzPosition); + case Attributes::MaxPresets::Id: + return aEncoder.Encode(mLogic.mMaxPresets); + case Attributes::MPTZPresets::Id: + return ReadAndEncodeMPTZPresets(aEncoder); + case Attributes::DPTZStreams::Id: + return ReadAndEncodeDPTZStreams(aEncoder); + case Attributes::ZoomMax::Id: + return aEncoder.Encode(mLogic.mZoomMax); + case Attributes::TiltMin::Id: + return aEncoder.Encode(mLogic.mTiltMin); + case Attributes::TiltMax::Id: + return aEncoder.Encode(mLogic.mTiltMax); + case Attributes::PanMin::Id: + return aEncoder.Encode(mLogic.mPanMin); + case Attributes::PanMax::Id: + return aEncoder.Encode(mLogic.mPanMax); + case Attributes::MovementState::Id: + return aEncoder.Encode(mLogic.mMovementState); + } + + return Status::UnsupportedAttribute; +} + +std::optional +CameraAvSettingsUserLevelManagementCluster::InvokeCommand(const DataModel::InvokeRequest & request, + chip::TLV::TLVReader & input_arguments, CommandHandler * handler) +{ + ChipLogProgress(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: InvokeCommand", request.path.mEndpointId); + + switch (request.path.mCommandId) + { + case Commands::MPTZSetPosition::Id: { + ChipLogProgress(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Setting MPTZ Position", request.path.mEndpointId); + Commands::MPTZSetPosition::DecodableType data; + ReturnErrorOnFailure(data.Decode(input_arguments)); + return mLogic.HandleMPTZSetPosition(*handler, request.path, data); + } + + case Commands::MPTZRelativeMove::Id: { + ChipLogProgress(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Relative move of MPTZ Position", request.path.mEndpointId); + Commands::MPTZRelativeMove::DecodableType data; + ReturnErrorOnFailure(data.Decode(input_arguments)); + return mLogic.HandleMPTZRelativeMove(*handler, request.path, data); + } + + case Commands::MPTZMoveToPreset::Id: { + ChipLogProgress(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Moving to an indicated MPTZ Preset", request.path.mEndpointId); + Commands::MPTZMoveToPreset::DecodableType data; + ReturnErrorOnFailure(data.Decode(input_arguments)); + return mLogic.HandleMPTZMoveToPreset(*handler, request.path, data); + } + + case Commands::MPTZSavePreset::Id: { + ChipLogProgress(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Saving MPTZ Preset", request.path.mEndpointId); + Commands::MPTZSavePreset::DecodableType data; + ReturnErrorOnFailure(data.Decode(input_arguments)); + return mLogic.HandleMPTZSavePreset(*handler, request.path, data); + } + + case Commands::MPTZRemovePreset::Id: { + ChipLogProgress(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Remove indicated MPTZ Preset", request.path.mEndpointId); + Commands::MPTZRemovePreset::DecodableType data; + ReturnErrorOnFailure(data.Decode(input_arguments)); + return mLogic.HandleMPTZRemovePreset(*handler, request.path, data); + } + + case Commands::DPTZSetViewport::Id: { + ChipLogProgress(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Setting DPTZ Viewport", request.path.mEndpointId); + Commands::DPTZSetViewport::DecodableType data; + ReturnErrorOnFailure(data.Decode(input_arguments)); + return mLogic.HandleDPTZSetViewport(*handler, request.path, data); + } + + case Commands::DPTZRelativeMove::Id: { + ChipLogProgress(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Relative move within a defined DPTZ Viewport", + request.path.mEndpointId); + Commands::DPTZRelativeMove::DecodableType data; + ReturnErrorOnFailure(data.Decode(input_arguments)); + return mLogic.HandleDPTZRelativeMove(*handler, request.path, data); + } + } + + return Status::UnsupportedCommand; +} + +/** + * Allows for a delegate or application to provide the ID and default Viewport of an allocated video stream that is capable of + * digital movement. This should be invoked by a delegate on the conclusion of allocating a video stream via the AV Stream + * Management cluster. + */ +void CameraAvSettingsUserLevelManagementCluster::AddMoveCapableVideoStream(uint16_t aVideoStreamID, + Globals::Structs::ViewportStruct::Type aViewport) +{ + mLogic.AddMoveCapableVideoStream(aVideoStreamID, aViewport); +} + +/** + * Allows for a delegate or application to update the viewport of an already allocated video stream. + * This should be invoked whenever a viewport is updated by DPTZSetVewport or DPTZRelativeMove + */ +void CameraAvSettingsUserLevelManagementCluster::UpdateMoveCapableVideoStream(uint16_t aVideoStreamID, + Globals::Structs::ViewportStruct::Type aViewport) +{ + mLogic.UpdateMoveCapableVideoStream(aVideoStreamID, aViewport); +} + +/** + * Allows for a delegate or application to update all of the viewports for all of the allocated video streams. + * This should be invoked whenever the device default viewport is updated via a write to Viewport on the + * AV Stream Management Cluster + */ +void CameraAvSettingsUserLevelManagementCluster::UpdateMoveCapableVideoStreams(Globals::Structs::ViewportStruct::Type aViewport) +{ + mLogic.UpdateMoveCapableVideoStreams(aViewport); +} + +/** + * Allows for a delegate or application to remove a video stream from the set that is capable of digital movement. + * This should be invoked by a delegate on the conclusion of deallocating a video stream via the AV Stream Management cluster. + */ +void CameraAvSettingsUserLevelManagementCluster::RemoveMoveCapableVideoStream(uint16_t aVideoStreamID) +{ + mLogic.RemoveMoveCapableVideoStream(aVideoStreamID); +} + +CHIP_ERROR CameraAvSettingsUserLevelManagementCluster::SetTiltMin(int16_t aTiltMin) +{ + return mLogic.SetTiltMin(aTiltMin); +} + +CHIP_ERROR CameraAvSettingsUserLevelManagementCluster::SetTiltMax(int16_t aTiltMax) +{ + return mLogic.SetTiltMax(aTiltMax); +} + +CHIP_ERROR CameraAvSettingsUserLevelManagementCluster::SetPanMin(int16_t aPanMin) +{ + return mLogic.SetPanMin(aPanMin); +} + +CHIP_ERROR CameraAvSettingsUserLevelManagementCluster::SetPanMax(int16_t aPanMax) +{ + return mLogic.SetPanMax(aPanMax); +} + +CHIP_ERROR CameraAvSettingsUserLevelManagementCluster::SetZoomMax(uint8_t aZoomMax) +{ + return mLogic.SetZoomMax(aZoomMax); +} + +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/camera-av-settings-user-level-management-server/camera-av-settings-user-level-management-server.h b/src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementCluster.h similarity index 59% rename from src/app/clusters/camera-av-settings-user-level-management-server/camera-av-settings-user-level-management-server.h rename to src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementCluster.h index d891c5591c2..b1d2f2580e5 100644 --- a/src/app/clusters/camera-av-settings-user-level-management-server/camera-av-settings-user-level-management-server.h +++ b/src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementCluster.h @@ -18,11 +18,9 @@ #pragma once -#include -#include -#include -#include -#include +#include +#include +#include #include #include #include @@ -30,75 +28,21 @@ namespace chip { namespace app { namespace Clusters { -namespace CameraAvSettingsUserLevelManagement { - -using MPTZStructType = Structs::MPTZStruct::Type; -using MPTZPresetStructType = Structs::MPTZPresetStruct::Type; -using DPTZStruct = Structs::DPTZStruct::Type; - -constexpr int16_t kMinPanValue = -180; -constexpr int16_t kMaxPanValue = 180; -constexpr int16_t kMinTiltValue = -180; -constexpr int16_t kMaxTiltValue = 180; -constexpr uint8_t kMinZoomValue = 1; -constexpr uint8_t kMaxZoomValue = 100; - -// Spec defined defaults for Pan, Tilt, and Zoom -constexpr int16_t kDefaultPan = 0; -constexpr int16_t kDefaultTilt = 0; -constexpr uint8_t kDefaultZoom = 1; constexpr size_t kMptzPositionStructMaxSerializedSize = TLV::EstimateStructOverhead(sizeof(int16_t), sizeof(int16_t), sizeof(uint8_t)); -class CameraAvSettingsUserLevelMgmtServer; - -struct MPTZPresetHelper -{ -private: - uint8_t mPresetID; - std::string mName; - MPTZStructType mMptzPosition; - -public: - virtual ~MPTZPresetHelper() = default; - MPTZPresetHelper() {} - MPTZPresetHelper(uint8_t aPreset, CharSpan aName, MPTZStructType aPosition) - { - SetPresetID(aPreset); - SetName(aName); - SetMptzPosition(aPosition); - } - - // Accessors and Mutators - // - std::string GetName() const { return mName; } - void SetName(chip::CharSpan aName) { mName = std::string(aName.begin(), aName.end()); } - - uint8_t GetPresetID() const { return mPresetID; } - void SetPresetID(uint8_t aPreset) { mPresetID = aPreset; } - - MPTZStructType GetMptzPosition() const { return mMptzPosition; } - void SetMptzPosition(MPTZStructType aPosition) { mMptzPosition = aPosition; } -}; - -class PhysicalPTZCallback -{ -public: - PhysicalPTZCallback() = default; - virtual ~PhysicalPTZCallback() = default; - virtual void OnPhysicalMovementComplete(Protocols::InteractionModel::Status status) = 0; -}; +class CameraAvSettingsUserLevelManagementCluster; /** @brief * Defines interfaces for implementing application-specific logic for various aspects of the CameraAvUserSettingsManagement * Cluster. Specifically, it defines interfaces for the interaction with manual and digital pan, tilt, and zoom functions. */ -class Delegate +class CameraAvSettingsUserLevelManagementDelegate { public: - Delegate() = default; - virtual ~Delegate() = default; + CameraAvSettingsUserLevelManagementDelegate() = default; + virtual ~CameraAvSettingsUserLevelManagementDelegate() = default; /** * Allows the delegate to perform any specific functions such as timer cancellation on a shutdown, this is invoked prior to @@ -137,8 +81,9 @@ class Delegate * It is the delegate's responsibility to ensure liveness of this server cluster instance before invocation of * the callback, which needs to take place in the Matter threading context. */ - virtual Protocols::InteractionModel::Status MPTZSetPosition(Optional aPan, Optional aTilt, - Optional aZoom, PhysicalPTZCallback * callback) = 0; + virtual Protocols::InteractionModel::Status + MPTZSetPosition(Optional aPan, Optional aTilt, Optional aZoom, + CameraAvSettingsUserLevelManagement::PhysicalPTZCallback * callback) = 0; /** * Allows any needed app handling given provided and already validated pan, tilt, and zoom values that are to be set based on @@ -154,8 +99,9 @@ class Delegate * It is the delegate's responsibility to ensure liveness of this server cluster instance before invocation of * the callback. which needs to take place in the Matter threading context. */ - virtual Protocols::InteractionModel::Status MPTZRelativeMove(Optional aPan, Optional aTilt, - Optional aZoom, PhysicalPTZCallback * callback) = 0; + virtual Protocols::InteractionModel::Status + MPTZRelativeMove(Optional aPan, Optional aTilt, Optional aZoom, + CameraAvSettingsUserLevelManagement::PhysicalPTZCallback * callback) = 0; /** * Allows any needed app handling given provided and already validated pan, tilt, and zoom values that are to be set based on @@ -173,8 +119,9 @@ class Delegate * it is the delegate's responsibility to ensure liveness of this server cluster instance before invocation of * the callback. which needs to take place in the Matter threading context. */ - virtual Protocols::InteractionModel::Status MPTZMoveToPreset(uint8_t aPreset, Optional aPan, Optional aTilt, - Optional aZoom, PhysicalPTZCallback * callback) = 0; + virtual Protocols::InteractionModel::Status + MPTZMoveToPreset(uint8_t aPreset, Optional aPan, Optional aTilt, Optional aZoom, + CameraAvSettingsUserLevelManagement::PhysicalPTZCallback * callback) = 0; /** * Informs the delegate that a request has been made to save the current PTZ values in a new (or updated) preset ID. @@ -230,65 +177,78 @@ class Delegate * hese Load APIs would be used to load the known presets and stream ids into the cluster * server list, at initialization. */ - virtual CHIP_ERROR LoadMPTZPresets(std::vector & mptzPresetHelpers) = 0; - virtual CHIP_ERROR LoadDPTZStreams(std::vector & dptzStreams) = 0; + virtual CHIP_ERROR LoadMPTZPresets(std::vector & mptzPresetHelpers) = 0; + virtual CHIP_ERROR + LoadDPTZStreams(std::vector & dptzStreams) = 0; private: - friend class CameraAvSettingsUserLevelMgmtServer; + friend class CameraAvSettingsUserLevelManagementCluster; - CameraAvSettingsUserLevelMgmtServer * mServer = nullptr; + CameraAvSettingsUserLevelManagementCluster * mServer = nullptr; // Sets the Server pointer - void SetServer(CameraAvSettingsUserLevelMgmtServer * aServer) { mServer = aServer; } + void SetServer(CameraAvSettingsUserLevelManagementCluster * aServer) { mServer = aServer; } protected: - CameraAvSettingsUserLevelMgmtServer * GetServer() const { return mServer; } + CameraAvSettingsUserLevelManagementCluster * GetServer() const { return mServer; } }; -enum class OptionalAttributes : uint32_t -{ - kMptzPosition = 0x0001, - kMaxPresets = 0x0002, - kMptzPresets = 0x0004, - kDptzStreams = 0x0008, - kZoomMax = 0x0010, - kTiltMin = 0x0020, - kTiltMax = 0x0040, - kPanMin = 0x0080, - kPanMax = 0x0100, - kMovementState = 0x0200, -}; - -class CameraAvSettingsUserLevelMgmtServer : public AttributeAccessInterface, - public CommandHandlerInterface, - public PhysicalPTZCallback +class CameraAvSettingsUserLevelManagementCluster : public DefaultServerCluster { public: /** * Creates a server instance. The Init() function needs to be called for this instance to be registered and * called by the interaction model at the appropriate times. * @param aEndpointId The endpoint on which this cluster exists. This must match the zap configuration. - * @param aDelegate A reference to the delegate to be used by this server. * @param aFeatures The bitflags value that identifies which features are supported by this instance. - * @param aOptionalAttrs The bitflags value that identifies the optional attributes supported by this instance. - * instance. + * Note: the caller must ensure that the delegate lives throughout the instance's lifetime. */ - CameraAvSettingsUserLevelMgmtServer(EndpointId aEndpointId, Delegate & aDelegate, BitFlags aFeatures, - BitFlags aOptionalAttrs, uint8_t aMaxPresets); - ~CameraAvSettingsUserLevelMgmtServer() override; + CameraAvSettingsUserLevelManagementCluster(EndpointId aEndpointId, + BitFlags aFeatures, + uint8_t aMaxPresets) : + DefaultServerCluster({ aEndpointId, CameraAvSettingsUserLevelManagement::Id }), + mLogic(aEndpointId, aFeatures, aMaxPresets) + {} + + CameraAvSettingsUserLevelMgmtServerLogic & GetLogic() { return mLogic; } + + void MarkAttributeDirty(AttributeId attributeId) { NotifyAttributeChanged(attributeId); } + + void SetDelegate(CameraAvSettingsUserLevelManagementDelegate * delegate) + { + mLogic.SetDelegate(delegate); + if (delegate != nullptr) + { + delegate->SetServer(this); + } + } - CHIP_ERROR Init(); + CHIP_ERROR Init() { return mLogic.Init(); } + + CHIP_ERROR Startup(ServerClusterContext & context) override; // Handle any dynamic cleanup required prior to the destructor being called on an app shutdown. To be invoked by // an app as part of its own shutdown sequence and prior to the destruction of the app/delegate. - void Shutdown(); + void Shutdown(/* ClusterShutdownType shutdownType */) override + { + DefaultServerCluster::Shutdown(/* shutdownType */); + mLogic.Shutdown(); + } + + DataModel::ActionReturnStatus ReadAttribute(const DataModel::ReadAttributeRequest & request, + AttributeValueEncoder & encoder) override; + + std::optional InvokeCommand(const DataModel::InvokeRequest & request, + chip::TLV::TLVReader & input_arguments, + CommandHandler * handler) override; - bool HasFeature(Feature aFeature) const; + CHIP_ERROR AcceptedCommands(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) override; - bool SupportsOptAttr(OptionalAttributes aOptionalAttr) const; + CHIP_ERROR Attributes(const ConcreteClusterPath & path, ReadOnlyBufferBuilder & builder) override; - // Attribute Accessors and Mutators + // Attribute Mutators CHIP_ERROR SetTiltMin(int16_t aTiltMin); CHIP_ERROR SetTiltMax(int16_t aTiltMax); @@ -299,40 +259,6 @@ class CameraAvSettingsUserLevelMgmtServer : public AttributeAccessInterface, CHIP_ERROR SetZoomMax(uint8_t aZoomMax); - const MPTZStructType & GetMptzPosition() const { return mMptzPosition; } - - uint8_t GetMaxPresets() const { return mMaxPresets; } - - const std::vector GetDptzRelativeMove() const { return mDptzStreams; } - - uint8_t GetZoomMax() const { return mZoomMax; } - - int16_t GetTiltMin() const { return mTiltMin; } - - int16_t GetTiltMax() const { return mTiltMax; } - - int16_t GetPanMin() const { return mPanMin; } - - int16_t GetPanMax() const { return mPanMax; } - - /** - * Allows for a delegate or application to set the pan value given physical changes on the device itself, possibly due to direct - * user changes - */ - void SetPan(Optional aPan); - - /** - * Allows for a delegate or application to set the tilt value given physical changes on the device itself, possibly due to - * direct user changes - */ - void SetTilt(Optional aTilt); - - /** - * Allows for a delegate or application to set the zoom value given physical changes on the device itself, possibly due to - * direct user changes - */ - void SetZoom(Optional aZoom); - /** * Allows for a delegate or application to provide the ID and default Viewport of an allocated video stream that is capable of * digital movement. This should be invoked by a delegate on the conclusion of allocating a video stream via the AV Stream @@ -359,91 +285,23 @@ class CameraAvSettingsUserLevelMgmtServer : public AttributeAccessInterface, */ void RemoveMoveCapableVideoStream(uint16_t aVideoStreamID); - EndpointId GetEndpointId() { return AttributeAccessInterface::GetEndpointId().Value(); } - - // Physical PTZ Interface - void OnPhysicalMovementComplete(Protocols::InteractionModel::Status status) override; - - // Is a command already being processed - bool IsMoving() const { return mMovementState == PhysicalMovementEnum::kMoving; } - private: - Delegate & mDelegate; - EndpointId mEndpointId; - BitFlags mFeatures; - BitFlags mOptionalAttrs; - - // Next available preset ID - uint8_t mCurrentPresetID = 1; - - // My known values for MPTZ. - MPTZStructType mMptzPosition; + CameraAvSettingsUserLevelMgmtServerLogic mLogic; + BitFlags mFeatures; - // Note, where assigned, these are spec defaults, potentially overwritten by the delegate. Exception is MaxPresets that - // is an F quality attribute and assigned by the constructor - const uint8_t mMaxPresets; - int16_t mPanMin = kMinPanValue; - int16_t mPanMax = kMaxPanValue; - int16_t mTiltMin = -90; - int16_t mTiltMax = 90; - uint8_t mZoomMax = kMaxZoomValue; - - std::vector mMptzPresetHelpers; - std::vector mDptzStreams; - - PhysicalMovementEnum mMovementState; + std::vector mMptzPresetHelpers; + std::vector mDptzStreams; // Holding variables for values subject to successful physical movement Optional mTargetPan; Optional mTargetTilt; Optional mTargetZoom; - // Attribute handler interface - CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; - // Helper Read functions for complex attribute types CHIP_ERROR ReadAndEncodeMPTZPresets(AttributeValueEncoder & encoder); CHIP_ERROR ReadAndEncodeDPTZStreams(AttributeValueEncoder & encoder); - - CHIP_ERROR StoreMPTZPosition(const MPTZStructType & mptzPosition); - CHIP_ERROR LoadMPTZPosition(MPTZStructType & mptzPosition); - - /** - * Helper function that loads all the persistent attributes from the KVS. - */ - void LoadPersistentAttributes(); - - // Command handler interface - void InvokeCommand(HandlerContext & ctx) override; - void HandleMPTZSetPosition(HandlerContext & ctx, const Commands::MPTZSetPosition::DecodableType & commandData); - void HandleMPTZRelativeMove(HandlerContext & ctx, const Commands::MPTZRelativeMove::DecodableType & commandData); - void HandleMPTZMoveToPreset(HandlerContext & ctx, const Commands::MPTZMoveToPreset::DecodableType & commandData); - void HandleMPTZSavePreset(HandlerContext & ctx, const Commands::MPTZSavePreset::DecodableType & commandData); - void HandleMPTZRemovePreset(HandlerContext & ctx, const Commands::MPTZRemovePreset::DecodableType & commandData); - void HandleDPTZSetViewport(HandlerContext & ctx, const Commands::DPTZSetViewport::DecodableType & commandData); - void HandleDPTZRelativeMove(HandlerContext & ctx, const Commands::DPTZRelativeMove::DecodableType & commandData); - - /** - * Helper function that manages preset IDs - */ - void UpdatePresetID(); - - /** - * Helper function that validates whether a given video stream ID is already known - */ - bool KnownVideoStreamID(uint16_t aVideoStreamID); - - /** - * Mutator for MovementState, only accessible by the server instance - */ - void SetMovementState(PhysicalMovementEnum aMovementState); - /** - * Helper function for attribute handlers to mark the attribute as dirty - */ - void MarkDirty(AttributeId aAttributeId); }; -} // namespace CameraAvSettingsUserLevelManagement } // namespace Clusters } // namespace app } // namespace chip diff --git a/src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementConstants.h b/src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementConstants.h new file mode 100644 index 00000000000..753e5941c5d --- /dev/null +++ b/src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementConstants.h @@ -0,0 +1,94 @@ +/* + * + * Copyright (c) 2025 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace CameraAvSettingsUserLevelManagement { + +constexpr int16_t kPanMinMinValue = -180; +constexpr int16_t kPanMinMaxValue = 0; +constexpr int16_t kPanMaxMinValue = 1; +constexpr int16_t kPanMaxMaxValue = 180; +constexpr int16_t kTiltMinMinValue = -180; +constexpr int16_t kTiltMinMaxValue = 0; +constexpr int16_t kTiltMaxMinValue = 1; +constexpr int16_t kTiltMaxMaxValue = 180; +constexpr uint8_t kZoomMinValue = 1; +constexpr uint8_t kZoomMaxMinValue = 2; +constexpr uint8_t kZoomMaxMaxValue = 100; + +// Spec defined defaults for Pan, Tilt, and Zoom +constexpr int16_t kDefaultPan = 0; +constexpr int16_t kDefaultTilt = 0; +constexpr uint8_t kDefaultZoom = 1; + +constexpr size_t kMptzPositionStructMaxSerializedSize = + TLV::EstimateStructOverhead(sizeof(int16_t), sizeof(int16_t), sizeof(uint8_t)); + +class PhysicalPTZCallback +{ +public: + PhysicalPTZCallback() = default; + virtual ~PhysicalPTZCallback() = default; + virtual void OnPhysicalMovementComplete(Protocols::InteractionModel::Status status) = 0; +}; + +struct MPTZPresetHelper +{ +private: + uint8_t mPresetID; + std::string mName; + CameraAvSettingsUserLevelManagement::Structs::MPTZStruct::Type mMptzPosition; + +public: + virtual ~MPTZPresetHelper() = default; + MPTZPresetHelper() {} + MPTZPresetHelper(uint8_t aPreset, CharSpan aName, CameraAvSettingsUserLevelManagement::Structs::MPTZStruct::Type aPosition) + { + SetPresetID(aPreset); + SetName(aName); + SetMptzPosition(aPosition); + } + + // Accessors and Mutators + // + std::string GetName() const { return mName; } + void SetName(chip::CharSpan aName) + { + mName = std::string(aName.begin(), aName.end()); + ChipLogProgress(Zcl, "My preset name being set %s", mName.c_str()); + } + + uint8_t GetPresetID() const { return mPresetID; } + void SetPresetID(uint8_t aPreset) { mPresetID = aPreset; } + + CameraAvSettingsUserLevelManagement::Structs::MPTZStruct::Type GetMptzPosition() const { return mMptzPosition; } + void SetMptzPosition(CameraAvSettingsUserLevelManagement::Structs::MPTZStruct::Type aPosition) { mMptzPosition = aPosition; } +}; + +} // namespace CameraAvSettingsUserLevelManagement +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementLogic.cpp b/src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementLogic.cpp new file mode 100644 index 00000000000..35b95faf062 --- /dev/null +++ b/src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementLogic.cpp @@ -0,0 +1,1026 @@ +/** + * + * Copyright (c) 2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::CameraAvSettingsUserLevelManagement; +using namespace chip::app::Clusters::CameraAvSettingsUserLevelManagement::Structs; +using namespace chip::app::Clusters::CameraAvSettingsUserLevelManagement::Attributes; +using namespace Protocols::InteractionModel; + +namespace chip { +namespace app { +namespace Clusters { + +CameraAvSettingsUserLevelMgmtServerLogic::CameraAvSettingsUserLevelMgmtServerLogic(EndpointId aEndpointId, + BitFlags aFeatures, + uint8_t aMaxPresets) : + mEndpointId(aEndpointId), + mFeatures(aFeatures), mMaxPresets(aMaxPresets) +{} + +CameraAvSettingsUserLevelMgmtServerLogic::~CameraAvSettingsUserLevelMgmtServerLogic() {} + +CHIP_ERROR CameraAvSettingsUserLevelMgmtServerLogic::Startup() +{ + ChipLogProgress(Zcl, "CameraAvSettingsUserLevelManagement: Startup"); + // Make sure mandated Features are set + // + VerifyOrReturnError(HasFeature(Feature::kMechanicalPan) || HasFeature(Feature::kMechanicalTilt) || + HasFeature(Feature::kMechanicalZoom) || HasFeature(Feature::kDigitalPTZ), + CHIP_ERROR_INVALID_ARGUMENT, + ChipLogError(Zcl, + "CameraAVSettingsUserLevelMgmt: Feature configuration error. At least one of " + "Mechanical Pan, Tilt, Zoom, or Digital PTZ must be supported")); + + // Set up our defaults + SetPan(MakeOptional(kDefaultPan)); + SetTilt(MakeOptional(kDefaultTilt)); + SetZoom(MakeOptional(kDefaultZoom)); + + SetMovementState(PhysicalMovementEnum::kIdle); + + LoadPersistentAttributes(); + + return CHIP_NO_ERROR; +} + +void CameraAvSettingsUserLevelMgmtServerLogic::Shutdown() +{ + mDelegate->ShutdownApp(); +} + +bool CameraAvSettingsUserLevelMgmtServerLogic::HasFeature(Feature aFeature) const +{ + return mFeatures.Has(aFeature); +} + +CHIP_ERROR +CameraAvSettingsUserLevelMgmtServerLogic::AcceptedCommands(ReadOnlyBufferBuilder & builder) +{ + if ((HasFeature(Feature::kMechanicalPan)) || (HasFeature(Feature::kMechanicalTilt)) || (HasFeature(Feature::kMechanicalZoom))) + { + ReturnErrorOnFailure(builder.AppendElements({ Commands::MPTZSetPosition::kMetadataEntry })); + ReturnErrorOnFailure(builder.AppendElements({ Commands::MPTZRelativeMove::kMetadataEntry })); + } + + if (HasFeature(Feature::kMechanicalPresets)) + { + ReturnErrorOnFailure(builder.AppendElements({ Commands::MPTZMoveToPreset::kMetadataEntry })); + ReturnErrorOnFailure(builder.AppendElements({ Commands::MPTZSavePreset::kMetadataEntry })); + ReturnErrorOnFailure(builder.AppendElements({ Commands::MPTZRemovePreset::kMetadataEntry })); + } + + if (HasFeature(Feature::kDigitalPTZ)) + { + ReturnErrorOnFailure(builder.AppendElements({ Commands::DPTZSetViewport::kMetadataEntry })); + ReturnErrorOnFailure(builder.AppendElements({ Commands::DPTZRelativeMove::kMetadataEntry })); + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR CameraAvSettingsUserLevelMgmtServerLogic::Attributes(ReadOnlyBufferBuilder & builder) +{ + AttributeListBuilder listBuilder(builder); + + // All attributes are set dependent on the Feature Flags + AttributeListBuilder::OptionalAttributeEntry optionalAttributes[] = { + { HasFeature(Feature::kMechanicalPan) || HasFeature(Feature::kMechanicalTilt) || HasFeature(Feature::kMechanicalZoom), + MPTZPosition::kMetadataEntry }, + { HasFeature(Feature::kMechanicalPresets), MaxPresets::kMetadataEntry }, + { HasFeature(Feature::kMechanicalPan), MPTZPresets::kMetadataEntry }, + { HasFeature(Feature::kDigitalPTZ), DPTZStreams::kMetadataEntry }, + { HasFeature(Feature::kMechanicalZoom), ZoomMax::kMetadataEntry }, + { HasFeature(Feature::kMechanicalTilt), TiltMin::kMetadataEntry }, + { HasFeature(Feature::kMechanicalTilt), TiltMax::kMetadataEntry }, + { HasFeature(Feature::kMechanicalPan), PanMin::kMetadataEntry }, + { HasFeature(Feature::kMechanicalPan), PanMax::kMetadataEntry }, + { HasFeature(Feature::kMechanicalPan) || HasFeature(Feature::kMechanicalTilt) || HasFeature(Feature::kMechanicalZoom), + MovementState::kMetadataEntry }, + }; + + return listBuilder.Append(Span(Attributes::kMandatoryMetadata), Span(optionalAttributes)); +} + +void CameraAvSettingsUserLevelMgmtServerLogic::MarkDirty(AttributeId aAttributeId) +{ + if (mMarkDirtyCallback) + { + mMarkDirtyCallback(aAttributeId); + } +} + +CHIP_ERROR CameraAvSettingsUserLevelMgmtServerLogic::StoreMPTZPosition( + const CameraAvSettingsUserLevelManagement::Structs::MPTZStruct::Type & mptzPosition) +{ + uint8_t buffer[kMptzPositionStructMaxSerializedSize]; + MutableByteSpan bufferSpan(buffer); + TLV::TLVWriter writer; + + writer.Init(bufferSpan); + ReturnErrorOnFailure(mptzPosition.Encode(writer, TLV::AnonymousTag())); + + auto path = ConcreteAttributePath(mEndpointId, CameraAvSettingsUserLevelManagement::Id, Attributes::MPTZPosition::Id); + bufferSpan.reduce_size(writer.GetLengthWritten()); + return GetAttributePersistenceProvider()->WriteValue(path, bufferSpan); +} + +CHIP_ERROR CameraAvSettingsUserLevelMgmtServerLogic::LoadMPTZPosition( + CameraAvSettingsUserLevelManagement::Structs::MPTZStruct::Type & mptzPosition) +{ + uint8_t buffer[kMptzPositionStructMaxSerializedSize]; + MutableByteSpan bufferSpan(buffer); + + auto path = ConcreteAttributePath(mEndpointId, CameraAvSettingsUserLevelManagement::Id, Attributes::MPTZPosition::Id); + ReturnErrorOnFailure(GetAttributePersistenceProvider()->ReadValue(path, bufferSpan)); + + TLV::TLVReader reader; + + reader.Init(bufferSpan); + ReturnErrorOnFailure(reader.Next(TLV::AnonymousTag())); + ReturnErrorOnFailure(mptzPosition.Decode(reader)); + + return CHIP_NO_ERROR; +} + +/** + * Attribute mutators. In all cases, given that these may not have been enabled depending on the Feature Flags that are set, + * the associated Feature presence is checked. The attributes are updated, and marked dirty, only if there is a change in the + * attribute value after constraint checking has been completed. + */ +CHIP_ERROR CameraAvSettingsUserLevelMgmtServerLogic::SetTiltMin(int16_t aTiltMin) +{ + VerifyOrReturnError(HasFeature(Feature::kMechanicalTilt), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute)); + VerifyOrReturnError((aTiltMin >= kTiltMinMinValue) && (aTiltMin <= kTiltMinMaxValue), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + + if (aTiltMin != mTiltMin) + { + mTiltMin = aTiltMin; + MarkDirty(Attributes::TiltMin::Id); + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR CameraAvSettingsUserLevelMgmtServerLogic::SetTiltMax(int16_t aTiltMax) +{ + VerifyOrReturnError(HasFeature(Feature::kMechanicalTilt), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute)); + VerifyOrReturnError((aTiltMax <= kTiltMaxMaxValue) && (aTiltMax >= kTiltMaxMinValue), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + + if (aTiltMax != mTiltMax) + { + mTiltMax = aTiltMax; + MarkDirty(Attributes::TiltMax::Id); + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR CameraAvSettingsUserLevelMgmtServerLogic::SetPanMin(int16_t aPanMin) +{ + VerifyOrReturnError(HasFeature(Feature::kMechanicalPan), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute)); + VerifyOrReturnError((aPanMin >= kPanMinMinValue) && (aPanMin <= kPanMinMaxValue), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + + if (aPanMin != mPanMin) + { + mPanMin = aPanMin; + MarkDirty(Attributes::PanMin::Id); + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR CameraAvSettingsUserLevelMgmtServerLogic::SetPanMax(int16_t aPanMax) +{ + VerifyOrReturnError(HasFeature(Feature::kMechanicalPan), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute)); + VerifyOrReturnError((aPanMax <= kPanMaxMaxValue) && (aPanMax >= kPanMaxMinValue), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + + if (aPanMax != mPanMax) + { + mPanMax = aPanMax; + MarkDirty(Attributes::PanMax::Id); + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR CameraAvSettingsUserLevelMgmtServerLogic::SetZoomMax(uint8_t aZoomMax) +{ + VerifyOrReturnError(HasFeature(Feature::kMechanicalZoom), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute)); + VerifyOrReturnError((aZoomMax <= kZoomMaxMaxValue) && (aZoomMax >= kZoomMaxMinValue), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + + if (aZoomMax != mZoomMax) + { + mZoomMax = aZoomMax; + MarkDirty(Attributes::ZoomMax::Id); + } + + return CHIP_NO_ERROR; +} + +/** + * Mutators for server copies of Pan, Tilt, and Zoom that may be invoked by a delegate or the server itself in responding to command + * callbacks, or due to local on device changes. + * Only set the value if the Feature Flag is set. + * It is entirely possible for a mutator to be called with a parameter that has no value. Case in point an invoke of + * MPTZSetPosition, this will be handled and the attributes updated if at least one of the three pan, tilt, or zoom have a value, + * with all three params passed through once validation is complete. An empty value is just ignored. + */ +void CameraAvSettingsUserLevelMgmtServerLogic::SetPan(Optional aPan) +{ + ChipLogProgress(Zcl, "CameraAvSettingsUserLevelManagement: SetPan"); + + if (HasFeature(Feature::kMechanicalPan)) + { + if (aPan.HasValue()) + { + mMptzPosition.pan = aPan; + TEMPORARY_RETURN_IGNORED StoreMPTZPosition(mMptzPosition); + MarkDirty(Attributes::MPTZPosition::Id); + } + } +} + +void CameraAvSettingsUserLevelMgmtServerLogic::SetTilt(Optional aTilt) +{ + if (HasFeature(Feature::kMechanicalTilt)) + { + if (aTilt.HasValue()) + { + mMptzPosition.tilt = aTilt; + TEMPORARY_RETURN_IGNORED StoreMPTZPosition(mMptzPosition); + MarkDirty(Attributes::MPTZPosition::Id); + } + } +} + +void CameraAvSettingsUserLevelMgmtServerLogic::SetZoom(Optional aZoom) +{ + if (HasFeature(Feature::kMechanicalZoom)) + { + if (aZoom.HasValue()) + { + mMptzPosition.zoom = aZoom; + TEMPORARY_RETURN_IGNORED StoreMPTZPosition(mMptzPosition); + MarkDirty(Attributes::MPTZPosition::Id); + } + } +} + +void CameraAvSettingsUserLevelMgmtServerLogic::SetMovementState(PhysicalMovementEnum aMovementState) +{ + if (HasFeature(Feature::kMechanicalPan) || HasFeature(Feature::kMechanicalTilt) || HasFeature(Feature::kMechanicalZoom)) + { + // The attribute is only ever changed to a new value, so this will always be dirty + mMovementState = aMovementState; + MarkDirty(Attributes::MovementState::Id); + } +} + +/** + * Methods handling known video stream IDs, the addition and removal thereof. + */ +void CameraAvSettingsUserLevelMgmtServerLogic::AddMoveCapableVideoStream(uint16_t aVideoStreamID, + Globals::Structs::ViewportStruct::Type aViewport) +{ + CameraAvSettingsUserLevelManagement::Structs::DPTZStruct::Type dptzEntry; + dptzEntry.videoStreamID = aVideoStreamID; + dptzEntry.viewport = aViewport; + mDptzStreams.push_back(dptzEntry); + MarkDirty(Attributes::DPTZStreams::Id); +} + +void CameraAvSettingsUserLevelMgmtServerLogic::UpdateMoveCapableVideoStream(uint16_t aVideoStreamID, + Globals::Structs::ViewportStruct::Type aViewport) +{ + auto it = std::find_if(mDptzStreams.begin(), mDptzStreams.end(), + [aVideoStreamID](const CameraAvSettingsUserLevelManagement::Structs::DPTZStruct::Type & dptzs) { + return dptzs.videoStreamID == aVideoStreamID; + }); + + if (it == mDptzStreams.end()) + { + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]. No matching video stream ID, update not possible. ID=%d.", + mEndpointId, aVideoStreamID); + return; + } + + it->viewport = aViewport; + MarkDirty(Attributes::DPTZStreams::Id); +} + +void CameraAvSettingsUserLevelMgmtServerLogic::UpdateMoveCapableVideoStreams(Globals::Structs::ViewportStruct::Type aViewport) +{ + for (auto & dptzStream : mDptzStreams) + { + dptzStream.viewport = aViewport; + } + + MarkDirty(Attributes::DPTZStreams::Id); +} + +void CameraAvSettingsUserLevelMgmtServerLogic::RemoveMoveCapableVideoStream(uint16_t aVideoStreamID) +{ + // Verify that this is a known ID, if it is, remove from the list + // + auto it = std::find_if(mDptzStreams.begin(), mDptzStreams.end(), + [aVideoStreamID](const CameraAvSettingsUserLevelManagement::Structs::DPTZStruct::Type & dptzs) { + return dptzs.videoStreamID == aVideoStreamID; + }); + + if (it == mDptzStreams.end()) + { + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]. No matching video stream ID, removal not possible. ID=%d.", + mEndpointId, aVideoStreamID); + return; + } + + mDptzStreams.erase(it); + MarkDirty(Attributes::DPTZStreams::Id); +} + +/** + * @returns bool True if the provided video stream ID is known to the server. False if not. + */ +bool CameraAvSettingsUserLevelMgmtServerLogic::KnownVideoStreamID(uint16_t aVideoStreamID) +{ + auto it = std::find_if(mDptzStreams.begin(), mDptzStreams.end(), + [aVideoStreamID](const DPTZStruct::Type & dptzs) { return dptzs.videoStreamID == aVideoStreamID; }); + + return (it == mDptzStreams.end() ? false : true); +} + +/** + * Helper function for setting the next preset ID to use in advance of reception of an MPTZSavePreset. + * The method loops over the range of possible IDs, starting with the current ID, if the preset ID is in use, + * it continues to the next possible value, looping back to 1. The checking is needed as the preset IDs aren't + * solely server generated, they can also be provided by a client. + * If there are no free presets (which will happen if all slots are taken), the value is not updated. + */ +void CameraAvSettingsUserLevelMgmtServerLogic::UpdatePresetID() +{ + uint8_t nextIDToCheck = mCurrentPresetID; + ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: UpdatePresetID. Current Preset is %d.", mEndpointId, + mCurrentPresetID); + + do + { + nextIDToCheck = static_cast((nextIDToCheck % mMaxPresets) + 1); + + // Have we lapped back round to where we started? If so, break + // + if (nextIDToCheck == mCurrentPresetID) + { + break; + } + + auto it = std::find_if(mMptzPresetHelpers.begin(), mMptzPresetHelpers.end(), + [=](const CameraAvSettingsUserLevelManagement::MPTZPresetHelper & mptzph) { + return mptzph.GetPresetID() == nextIDToCheck; + }); + if (it == mMptzPresetHelpers.end()) + { + mCurrentPresetID = nextIDToCheck; + break; + } + } while (true); + + ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Updated PresetID is %d.", mEndpointId, mCurrentPresetID); +} + +/** + * Helper Read functions for complex attribute types + */ +CHIP_ERROR CameraAvSettingsUserLevelMgmtServerLogic::ReadAndEncodeMPTZPresets(AttributeValueEncoder & aEncoder) +{ + return aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR { + for (const auto & mptzPresets : mMptzPresetHelpers) + { + // Get the details to encode from the preset helper + // + MPTZPresetStruct::Type presetStruct; + std::string name = mptzPresets.GetName(); + uint8_t preset = mptzPresets.GetPresetID(); + presetStruct.presetID = preset; + presetStruct.name = CharSpan(name.c_str(), name.size()); + presetStruct.settings = mptzPresets.GetMptzPosition(); + ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Encoding an instance of MPTZPresetStruct. ID = %d. Name = %s", + mEndpointId, presetStruct.presetID, NullTerminated(presetStruct.name).c_str()); + ReturnErrorOnFailure(encoder.Encode(presetStruct)); + } + + return CHIP_NO_ERROR; + }); +} + +CHIP_ERROR CameraAvSettingsUserLevelMgmtServerLogic::ReadAndEncodeDPTZStreams(AttributeValueEncoder & aEncoder) +{ + return aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR { + for (const auto & dptzStream : mDptzStreams) + { + ReturnErrorOnFailure(encoder.Encode(dptzStream)); + } + + return CHIP_NO_ERROR; + }); +} + +void CameraAvSettingsUserLevelMgmtServerLogic::LoadPersistentAttributes() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + // Load MPTZPosition + MPTZStruct::Type storedMPTZPosition; + err = LoadMPTZPosition(storedMPTZPosition); + if (err == CHIP_NO_ERROR) + { + mMptzPosition = storedMPTZPosition; + ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Loaded MPTZPosition", mEndpointId); + } + else + { + ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Unable to load the MPTZPosition from the KVS.", mEndpointId); + } + + // Load MPTZPresets + err = mDelegate->LoadMPTZPresets(mMptzPresetHelpers); + if (err != CHIP_NO_ERROR) + { + ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Unable to load the MPTZPresets from the KVS.", mEndpointId); + } + + // Load DPTZRelativeMove + err = mDelegate->LoadDPTZStreams(mDptzStreams); + if (err != CHIP_NO_ERROR) + { + ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Unable to load the DPTZRelativeMove from the KVS.", mEndpointId); + } + + // Signal delegate that all persistent configuration attributes have been loaded. + TEMPORARY_RETURN_IGNORED mDelegate->PersistentAttributesLoadedCallback(); +} + +std::optional CameraAvSettingsUserLevelMgmtServerLogic::HandleMPTZSetPosition( + CommandHandler & handler, const ConcreteCommandPath & commandPath, + const CameraAvSettingsUserLevelManagement::Commands::MPTZSetPosition::DecodableType & commandData) +{ + bool hasAtLeastOneValue = false; + + Optional pan = commandData.pan; + Optional tilt = commandData.tilt; + Optional zoom = commandData.zoom; + + // Validate the received command fields + // + if (pan.HasValue()) + { + VerifyOrReturnError( + HasFeature(Feature::kMechanicalPan), Status::InvalidCommand, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Mechanical Pan not supported although pan value provided", + mEndpointId)); + + int16_t panValue = pan.Value(); + VerifyOrReturnError( + (panValue <= mPanMax) && (panValue >= mPanMin), Status::ConstraintError, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Received Pan value out of range", mEndpointId)); + + hasAtLeastOneValue = true; + } + + if (tilt.HasValue()) + { + VerifyOrReturnError( + HasFeature(Feature::kMechanicalTilt), Status::InvalidCommand, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Mechanical Tilt not supported although tilt value provided", + mEndpointId)); + + int16_t tiltValue = tilt.Value(); + VerifyOrReturnError( + (tiltValue <= mTiltMax) && (tiltValue >= mTiltMin), Status::ConstraintError, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Received Tilt value out of range", mEndpointId)); + + hasAtLeastOneValue = true; + } + + if (zoom.HasValue()) + { + VerifyOrReturnError( + HasFeature(Feature::kMechanicalZoom), Status::InvalidCommand, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Mechanical Zoom not supported although zoom value provided", + mEndpointId)); + + uint8_t zoomValue = zoom.Value(); + + VerifyOrReturnError( + (zoomValue <= mZoomMax) && (zoomValue >= kZoomMinValue), Status::ConstraintError, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Received Zoom value out of range", mEndpointId)); + + hasAtLeastOneValue = true; + } + + // Was a value received in the command + VerifyOrReturnError(hasAtLeastOneValue, Status::InvalidCommand, + ChipLogError(Zcl, + "CameraAVSettingsUserLevelMgmt[ep=%d]: MPTZSetPosition command contains no actionable fields", + mEndpointId)); + + // If the camera is still in motion, then return Busy. Subsequently check with the delegate that we're in a position to change + // any of the PTZ values which may not be possible for other reasons + // + VerifyOrReturnError( + !IsMoving(), Status::Busy, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: cannot execute command as camera is busy with a physical movement", + mEndpointId)); + + VerifyOrReturnError( + mDelegate->CanChangeMPTZ(), Status::Busy, + ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Device not able to process MPTZ change", mEndpointId)); + + Status status = mDelegate->MPTZSetPosition(pan, tilt, zoom, this); + + if (status != Status::Success) + { + return status; + } + + // We don't update the server persisted attributes until the delegate confirms via callback that the physical device movement is + // complete + // + mTargetPan = pan; + mTargetTilt = tilt; + mTargetZoom = zoom; + + SetMovementState(PhysicalMovementEnum::kMoving); + + return status; +} + +std::optional CameraAvSettingsUserLevelMgmtServerLogic::HandleMPTZRelativeMove( + CommandHandler & handler, const ConcreteCommandPath & commandPath, + const CameraAvSettingsUserLevelManagement::Commands::MPTZRelativeMove::DecodableType & commandData) +{ + bool hasAtLeastOneValue = false; + + Optional panDelta = commandData.panDelta; + Optional tiltDelta = commandData.tiltDelta; + Optional zoomDelta = commandData.zoomDelta; + + // These will all be set to actual values if there is a delta provided, and constraint checking passes. + Optional newPan; + Optional newTilt; + Optional newZoom; + + // Validate the received command fields + // + if (panDelta.HasValue()) + { + VerifyOrReturnError( + HasFeature(Feature::kMechanicalPan), Status::InvalidCommand, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Mechanical Pan not supported although panDelta value provided", + mEndpointId)); + + int16_t panDeltaValue = panDelta.Value(); + VerifyOrReturnError( + (panDeltaValue <= (mPanMax - mPanMin) && panDeltaValue >= -(mPanMax - mPanMin)), Status::ConstraintError, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: PanDelta value received is out of range.", mEndpointId)); + + // If we're here, then we'll also have an existing Pan value in MPTZPosition + // Note that newPan is always between -180 and 180; and the panDeltaValue is constrained to -360 to 360 by the + // code above, so the addition sum can never overflow int16_t. + // + int16_t newPanValue = static_cast(mMptzPosition.pan.Value() + panDeltaValue); + if (newPanValue > mPanMax) + { + newPanValue = mPanMax; + } + if (newPanValue < mPanMin) + { + newPanValue = mPanMin; + } + + newPan.Emplace(newPanValue); + + hasAtLeastOneValue = true; + } + + if (tiltDelta.HasValue()) + { + VerifyOrReturnError( + HasFeature(Feature::kMechanicalTilt), Status::InvalidCommand, + ChipLogError(Zcl, + "CameraAVSettingsUserLevelMgmt[ep=%d]: Mechanical Tilt not supported although tiltDelta value provided", + mEndpointId)); + + int16_t tiltDeltaValue = tiltDelta.Value(); + VerifyOrReturnError( + (tiltDeltaValue <= (mTiltMax - mTiltMin) && tiltDeltaValue >= -(mTiltMax - mTiltMin)), Status::ConstraintError, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: TiltDelta value received is out of range.", mEndpointId)); + + // If we're here, then we'll also have an existing Tilt value in MPTZPosition + // Note that newTilt is always between -180 and 180; and the tiltDeltaValue is constrained to -360 to 360 by the + // code above, so the addition sum can never overflow int16_t. + // + int16_t newTiltValue = static_cast(mMptzPosition.tilt.Value() + tiltDeltaValue); + if (newTiltValue > mTiltMax) + { + newTiltValue = mTiltMax; + } + if (newTiltValue < mTiltMin) + { + newTiltValue = mTiltMin; + } + + newTilt.Emplace(newTiltValue); + + hasAtLeastOneValue = true; + } + + if (zoomDelta.HasValue()) + { + VerifyOrReturnError( + HasFeature(Feature::kMechanicalZoom), Status::InvalidCommand, + ChipLogError(Zcl, + "CameraAVSettingsUserLevelMgmt[ep=%d]: Mechanical Zoom not supported although zoomDelta value provided", + mEndpointId)); + + int8_t zoomDeltaValue = zoomDelta.Value(); + VerifyOrReturnError( + (zoomDeltaValue <= (mZoomMax - 1) && zoomDeltaValue >= -(mZoomMax - 1)), Status::ConstraintError, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: ZoomDelta value received is out of range.", mEndpointId)); + + // If we're here, then we'll also have an existing Zoom value in MPTZPosition. The zoom values are constrained such that + // we won't overflow newZoomValue + // + int newZoomValue = static_cast(mMptzPosition.zoom.Value()) + zoomDeltaValue; + + if (newZoomValue > mZoomMax) + { + newZoomValue = static_cast(mZoomMax); + } + if (newZoomValue < 1) + { + newZoomValue = 1; + } + + ChipLogProgress(Zcl, "New Zoom Value %d", newZoomValue); + + newZoom.Emplace(static_cast(newZoomValue)); + + hasAtLeastOneValue = true; + } + + // Was a value received in the command + VerifyOrReturnError(hasAtLeastOneValue, Status::InvalidCommand, + ChipLogError(Zcl, + "CameraAVSettingsUserLevelMgmt[ep=%d]: MPTZRelativeMove command contains no actionable fields", + mEndpointId)); + + // If the camera is still in motion, then return Busy. Subsequently check with the delegate that we're in a position to change + // any of the PTZ values which may not be possible for other reasons + // + VerifyOrReturnError( + !IsMoving(), Status::Busy, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: cannot execute command as camera is busy with a physical movement", + mEndpointId)); + + VerifyOrReturnError(mDelegate->CanChangeMPTZ(), Status::Busy, + ChipLogDetail(Zcl, + "CameraAVSettingsUserLevelMgmt[ep=%d]: Device not able to process MPTZ relative value change", + mEndpointId)); + + Status status = mDelegate->MPTZRelativeMove(newPan, newTilt, newZoom, this); + + if (status != Status::Success) + { + return status; + } + + // We don't update the server persisted attributes until the delegate confirms via callback that the physical device movement is + // complete + // + mTargetPan = newPan; + mTargetTilt = newTilt; + mTargetZoom = newZoom; + SetMovementState(PhysicalMovementEnum::kMoving); + + return status; +} + +std::optional CameraAvSettingsUserLevelMgmtServerLogic::HandleMPTZMoveToPreset( + CommandHandler & handler, const ConcreteCommandPath & commandPath, + const CameraAvSettingsUserLevelManagement::Commands::MPTZMoveToPreset::DecodableType & commandData) +{ + uint8_t preset = commandData.presetID; + + // Verify the provided presetID is within spec limits + // + VerifyOrReturnError((preset <= mMaxPresets) && (preset >= 1), Status::ConstraintError, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Preset provided is out of range. Preset: %d", + mEndpointId, preset)); + + // Do we have any presets? + // + VerifyOrReturnError( + !mMptzPresetHelpers.empty(), Status::NotFound, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: No stored presets, MoveToPreset not possible", mEndpointId)); + + // We have presets, check that the received ID is a valid preset ID + // + auto it = std::find_if( + mMptzPresetHelpers.begin(), mMptzPresetHelpers.end(), + [preset](const CameraAvSettingsUserLevelManagement::MPTZPresetHelper & mptzph) { return mptzph.GetPresetID() == preset; }); + + VerifyOrReturnError( + it != mMptzPresetHelpers.end(), Status::NotFound, + ChipLogError(Zcl, + "CameraAVSettingsUserLevelMgmt[ep=%d]: No matching presets, MoveToPreset not possible for provided preset: %d", + mEndpointId, preset)); + + // If the camera is still in motion, then return Busy. Subsequently check with the delegate that we're in a position to change + // any of the PTZ values which may not be possible for other reasons + // + VerifyOrReturnError( + !IsMoving(), Status::Busy, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: cannot execute command as camera is busy with a physical movement", + mEndpointId)); + + VerifyOrReturnError( + mDelegate->CanChangeMPTZ(), Status::Busy, + ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Device not able to process move to MPTZ preset", mEndpointId)); + + auto presetValues = it->GetMptzPosition(); + + // Inform the delegate that the device is requested to move to PTZ values given by the selected preset id + Status status = mDelegate->MPTZMoveToPreset(preset, presetValues.pan, presetValues.tilt, presetValues.zoom, this); + + if (status != Status::Success) + { + return status; + } + + // We don't update the server persisted attributes until the delegate confirms via callback that the physical device movement is + // complete + // + mTargetPan = presetValues.pan; + mTargetTilt = presetValues.tilt; + mTargetZoom = presetValues.zoom; + SetMovementState(PhysicalMovementEnum::kMoving); + + return status; +} + +std::optional CameraAvSettingsUserLevelMgmtServerLogic::HandleMPTZSavePreset( + CommandHandler & handler, const ConcreteCommandPath & commandPath, + const CameraAvSettingsUserLevelManagement::Commands::MPTZSavePreset::DecodableType & commandData) +{ + Status status = Status::Success; + + Optional preset = commandData.presetID; + chip::CharSpan presetName = commandData.name; + uint8_t presetToUse = mCurrentPresetID; + + // Do we have a user provided preset ID? If yes, is it in range? + // + if (preset.HasValue()) + { + VerifyOrReturnError((preset.Value() <= mMaxPresets) && (preset.Value() >= 1), Status::ConstraintError, + ChipLogError(Zcl, + "CameraAVSettingsUserLevelMgmt[ep=%d]: Provided preset ID is out of range. Preset: %d", + mEndpointId, preset.Value())); + presetToUse = preset.Value(); + } + + // Does the preset equate to an already known stored preset? If so we're updating that one rather than creating a new one + // + auto it = std::find_if(mMptzPresetHelpers.begin(), mMptzPresetHelpers.end(), + [presetToUse](const CameraAvSettingsUserLevelManagement::MPTZPresetHelper & mptzph) { + return mptzph.GetPresetID() == presetToUse; + }); + + // If the current preset ID results in an entry from the current known set and there was a provided preset then we're updating + // an existing preset. Only check for exhausting max presets if we're NOT updating. + // It is possible that mCurrentPresetID equates to a current preset in cases where the collection of presets is full + // + bool updatingExistingPreset = (it != mMptzPresetHelpers.end()) && (preset.HasValue()); + + if (!updatingExistingPreset) + { + // Make sure that the vector will not exceed the max size + // + VerifyOrReturnError( + mMptzPresetHelpers.size() != mMaxPresets, Status::ResourceExhausted, + ChipLogError(Zcl, + "CameraAVSettingsUserLevelMgmt[ep=%d]: No more space for additional presets, MPTZSavePreset not possible", + mEndpointId)); + } + + // Call the delegate, make sure that it is ok to save a new preset, given the current + // delegate aware values for MPTZ + // + status = mDelegate->MPTZSavePreset(presetToUse); + + if (status != Status::Success) + { + return status; + } + + // Capture the current MPTZ values in the preset + // + CameraAvSettingsUserLevelManagement::MPTZPresetHelper aMptzPresetHelper; + + aMptzPresetHelper.SetPresetID(presetToUse); + aMptzPresetHelper.SetName(presetName); + aMptzPresetHelper.SetMptzPosition(mMptzPosition); + + // If an update, replace what is at the iterator, otherwise add to the set as tis is new + // + if (updatingExistingPreset) + { + ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Updating existing MPTZ Preset. Preset ID = %d. Preset Name = %s", + mEndpointId, presetToUse, aMptzPresetHelper.GetName().c_str()); + *it = aMptzPresetHelper; + } + else + { + ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Saving new MPTZ Preset. Preset ID = %d. Preset Name = %s", + mEndpointId, presetToUse, aMptzPresetHelper.GetName().c_str()); + mMptzPresetHelpers.push_back(aMptzPresetHelper); + } + + // Update the current preset ID to the next available only if we actually used the current value. A user provided preset + // could have any value between 1 and MaxPresets + // + if (presetToUse == mCurrentPresetID) + { + UpdatePresetID(); + } + + MarkDirty(Attributes::MPTZPresets::Id); + + return Status::Success; +} + +std::optional CameraAvSettingsUserLevelMgmtServerLogic::HandleMPTZRemovePreset( + CommandHandler & handler, const ConcreteCommandPath & commandPath, + const CameraAvSettingsUserLevelManagement::Commands::MPTZRemovePreset::DecodableType & commandData) +{ + uint8_t presetToRemove = commandData.presetID; + + // Verify the provided presetID is within spec limits + // + VerifyOrReturnError((presetToRemove <= mMaxPresets) && (presetToRemove >= 1), Status::ConstraintError, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Preset to remove is out of range. Preset: %d", + mEndpointId, presetToRemove)); + + // Is the provided ID known to us? + // + auto it = std::find_if(mMptzPresetHelpers.begin(), mMptzPresetHelpers.end(), + [presetToRemove](const CameraAvSettingsUserLevelManagement::MPTZPresetHelper & mptzph) { + return mptzph.GetPresetID() == presetToRemove; + }); + + VerifyOrReturnError( + it != mMptzPresetHelpers.end(), Status::NotFound, + ChipLogError(Zcl, + "CameraAVSettingsUserLevelMgmt[ep=%d]: No matching presets, RemovePreset not possible for provided preset: %d", + mEndpointId, presetToRemove)); + + // Call the delegate to ensure that it is ok to remove the preset indicated. + // + Status status = mDelegate->MPTZRemovePreset(presetToRemove); + + if (status != Status::Success) + { + return status; + } + + // Remove the identified item from the known set of presets + // + mMptzPresetHelpers.erase(it); + MarkDirty(Attributes::MPTZPresets::Id); + + return Status::Success; +} + +std::optional CameraAvSettingsUserLevelMgmtServerLogic::HandleDPTZSetViewport( + CommandHandler & handler, const ConcreteCommandPath & commandPath, + const CameraAvSettingsUserLevelManagement::Commands::DPTZSetViewport::DecodableType & commandData) +{ + uint16_t videoStreamID = commandData.videoStreamID; + Globals::Structs::ViewportStruct::Type viewport = commandData.viewport; + + // Is this a video stream ID of which we have already been informed? + // If not, fail. + // + VerifyOrReturnError(KnownVideoStreamID(videoStreamID), Status::NotFound, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Unknown Video Stream ID provided. ID: %d", + mEndpointId, videoStreamID)); + + // Call the delegate + Status status = mDelegate->DPTZSetViewport(videoStreamID, viewport); + + if (status == Status::Success) + { + // Update the viewport of our stream in DPTZStreams + // + UpdateMoveCapableVideoStream(videoStreamID, viewport); + } + + return status; +} + +std::optional CameraAvSettingsUserLevelMgmtServerLogic::HandleDPTZRelativeMove( + CommandHandler & handler, const ConcreteCommandPath & commandPath, + const CameraAvSettingsUserLevelManagement::Commands::DPTZRelativeMove::DecodableType & commandData) +{ + uint16_t videoStreamID = commandData.videoStreamID; + Optional deltaX = commandData.deltaX; + Optional deltaY = commandData.deltaY; + Optional zoomDelta = commandData.zoomDelta; + + // Verify that a received Zoom Delta is within constraints + // + if (zoomDelta.HasValue()) + { + int8_t zoomDeltaValue = zoomDelta.Value(); + VerifyOrReturnError( + zoomDeltaValue >= -100 && zoomDeltaValue <= 100, Status::ConstraintError, + ChipLogError(Zcl, + "CameraAVSettingsUserLevelMgmt[ep=%d]: Provided Digital Zoom Delta is out of range. Provided Zoom: %d", + mEndpointId, zoomDeltaValue)); + } + // Is this a video stream ID of which we have already been informed via DPTZSetViewport. We can't relative move on a + // viewport that hasn't already been set, hence we fail if the provided id is not found. + // + VerifyOrReturnError(KnownVideoStreamID(videoStreamID), Status::NotFound, + ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]. Unknown Video Stream ID provided. ID=%d.", + mEndpointId, videoStreamID)); + + // Create a viewport and call the delegate; on success update our Stream Viewport with that which was set + Globals::Structs::ViewportStruct::Type viewport; + Status status = mDelegate->DPTZRelativeMove(videoStreamID, deltaX, deltaY, zoomDelta, viewport); + + if (status == Status::Success) + { + UpdateMoveCapableVideoStream(videoStreamID, viewport); + } + + return status; +} + +// Physical device movement callback +// +void CameraAvSettingsUserLevelMgmtServerLogic::OnPhysicalMovementComplete(Status status) +{ + // Make sure we're running in the Matter thread + assertChipStackLockedByCurrentThread(); + + if (status == Status::Success) + { + SetPan(mTargetPan); + SetTilt(mTargetTilt); + SetZoom(mTargetZoom); + } + else + { + ChipLogError( + Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]. Camera failed to move to new requested values of Pan, Tilt, and/or Zoom.", + mEndpointId); + } + + SetMovementState(PhysicalMovementEnum::kIdle); +} + +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementLogic.h b/src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementLogic.h new file mode 100644 index 00000000000..42a13ec5757 --- /dev/null +++ b/src/app/clusters/camera-av-settings-user-level-management-server/CameraAvSettingsUserLevelManagementLogic.h @@ -0,0 +1,256 @@ +/* + * + * Copyright (c) 2025 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 +#include + +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { + +class CameraAvSettingsUserLevelManagementDelegate; + +// Callback type for notifying attribute changes +using MarkDirtyCallback = std::function; + +class CameraAvSettingsUserLevelMgmtServerLogic : public CameraAvSettingsUserLevelManagement::PhysicalPTZCallback +{ +public: + /** + * Creates a server instance. The Init() function needs to be called for this instance to be registered and + * called by the interaction model at the appropriate times. + * @param aEndpointId The endpoint on which this cluster exists. This must match the zap configuration. + * @param aFeatures The bitflags value that identifies which features are supported by this instance. + + * Note: the caller must ensure that the delegate lives throughout the instance's lifetime. + */ + CameraAvSettingsUserLevelMgmtServerLogic(EndpointId aEndpointId, + BitFlags aFeatures, uint8_t aMaxPresets); + ~CameraAvSettingsUserLevelMgmtServerLogic(); + + void SetDelegate(CameraAvSettingsUserLevelManagementDelegate * delegate) + { + mDelegate = delegate; + if (mDelegate == nullptr) + { + ChipLogError(Zcl, "CameraAVSettingsUserLevelManagement: Trying to set delegate to null"); + } + } + + void SetMarkDirtyCallback(MarkDirtyCallback callback) { mMarkDirtyCallback = std::move(callback); } + + EndpointId mEndpointId = kInvalidEndpointId; + + BitFlags mFeatures; + + // Next available preset ID + uint8_t mCurrentPresetID = 1; + + // My known values for MPTZ. + CameraAvSettingsUserLevelManagement::Structs::MPTZStruct::Type mMptzPosition; + + // Note, where assigned, these are the extreme ends of the spec defined range (or a default if there is one), potentially + // overwritten by the delegate. Exception is MaxPresets that is an F quality attribute and assigned by the constructor + const uint8_t mMaxPresets = 5; + int16_t mPanMin = CameraAvSettingsUserLevelManagement::kPanMinMinValue; + int16_t mPanMax = CameraAvSettingsUserLevelManagement::kPanMaxMaxValue; + int16_t mTiltMin = CameraAvSettingsUserLevelManagement::kTiltMinMinValue; + int16_t mTiltMax = CameraAvSettingsUserLevelManagement::kTiltMaxMaxValue; + uint8_t mZoomMax = CameraAvSettingsUserLevelManagement::kZoomMaxMaxValue; + + CameraAvSettingsUserLevelManagement::PhysicalMovementEnum mMovementState; + + std::vector mMptzPresetHelpers; + std::vector mDptzStreams; + + CHIP_ERROR Init() { return CHIP_NO_ERROR; } + + CHIP_ERROR Startup(); + + // Handle any dynamic cleanup required prior to the destructor being called on an app shutdown. To be invoked by + // an app as part of its own shutdown sequence and prior to the destruction of the app/delegate. + void Shutdown(); + + bool HasFeature(CameraAvSettingsUserLevelManagement::Feature aFeature) const; + + // Returns the commands accepted depending on the Feature Flags that are set + CHIP_ERROR AcceptedCommands(ReadOnlyBufferBuilder & builder); + + // Returns supported depending on the Feature Flags that are set + CHIP_ERROR Attributes(ReadOnlyBufferBuilder & builder); + + // Attribute Accessors and Mutators + CHIP_ERROR SetTiltMin(int16_t aTiltMin); + + CHIP_ERROR SetTiltMax(int16_t aTiltMax); + + CHIP_ERROR SetPanMin(int16_t aPanMin); + + CHIP_ERROR SetPanMax(int16_t aPanMax); + + CHIP_ERROR SetZoomMax(uint8_t aZoomMax); + + const CameraAvSettingsUserLevelManagement::Structs::MPTZStruct::Type & GetMptzPosition() const { return mMptzPosition; } + + uint8_t GetMaxPresets() const { return mMaxPresets; } + + const std::vector GetDptzRelativeMove() const + { + return mDptzStreams; + } + + uint8_t GetZoomMax() const { return mZoomMax; } + + int16_t GetTiltMin() const { return mTiltMin; } + + int16_t GetTiltMax() const { return mTiltMax; } + + int16_t GetPanMin() const { return mPanMin; } + + int16_t GetPanMax() const { return mPanMax; } + + /** + * Allows for a delegate or application to set the pan value given physical changes on the device itself, possibly due to direct + * user changes + */ + void SetPan(Optional aPan); + + /** + * Allows for a delegate or application to set the tilt value given physical changes on the device itself, possibly due to + * direct user changes + */ + void SetTilt(Optional aTilt); + + /** + * Allows for a delegate or application to set the zoom value given physical changes on the device itself, possibly due to + * direct user changes + */ + void SetZoom(Optional aZoom); + + // Command handlers + std::optional + HandleMPTZSetPosition(CommandHandler & handler, const ConcreteCommandPath & commandPath, + const CameraAvSettingsUserLevelManagement::Commands::MPTZSetPosition::DecodableType & commandData); + std::optional + HandleMPTZRelativeMove(CommandHandler & handler, const ConcreteCommandPath & commandPath, + const CameraAvSettingsUserLevelManagement::Commands::MPTZRelativeMove::DecodableType & commandData); + std::optional + HandleMPTZMoveToPreset(CommandHandler & handler, const ConcreteCommandPath & commandPath, + const CameraAvSettingsUserLevelManagement::Commands::MPTZMoveToPreset::DecodableType & commandData); + std::optional + HandleMPTZSavePreset(CommandHandler & handler, const ConcreteCommandPath & commandPath, + const CameraAvSettingsUserLevelManagement::Commands::MPTZSavePreset::DecodableType & commandData); + std::optional + HandleMPTZRemovePreset(CommandHandler & handler, const ConcreteCommandPath & commandPath, + const CameraAvSettingsUserLevelManagement::Commands::MPTZRemovePreset::DecodableType & commandData); + std::optional + HandleDPTZSetViewport(CommandHandler & handler, const ConcreteCommandPath & commandPath, + const CameraAvSettingsUserLevelManagement::Commands::DPTZSetViewport::DecodableType & commandData); + std::optional + HandleDPTZRelativeMove(CommandHandler & handler, const ConcreteCommandPath & commandPath, + const CameraAvSettingsUserLevelManagement::Commands::DPTZRelativeMove::DecodableType & commandData); + + /** + * Allows for a delegate or application to provide the ID and default Viewport of an allocated video stream that is capable of + * digital movement. This should be invoked by a delegate on the conclusion of allocating a video stream via the AV Stream + * Management cluster. + */ + void AddMoveCapableVideoStream(uint16_t aVideoStreamID, Globals::Structs::ViewportStruct::Type aViewport); + + /** + * Allows for a delegate or application to update the viewport of an already allocated video stream. + * This should be invoked whenever a viewport is updated by DPTZSetVewport or DPTZRelativeMove + */ + void UpdateMoveCapableVideoStream(uint16_t aVideoStreamID, Globals::Structs::ViewportStruct::Type aViewport); + + /** + * Allows for a delegate or application to update all of the viewports for all of the allocated video streams. + * This should be invoked whenever the device default viewport is updated via a write to Viewport on the + * AV Stream Management Cluster + */ + void UpdateMoveCapableVideoStreams(Globals::Structs::ViewportStruct::Type aViewport); + + /** + * Allows for a delegate or application to remove a video stream from the set that is capable of digital movement. + * This should be invoked by a delegate on the conclusion of deallocating a video stream via the AV Stream Management cluster. + */ + void RemoveMoveCapableVideoStream(uint16_t aVideoStreamID); + + // Physical PTZ Interface + void OnPhysicalMovementComplete(Protocols::InteractionModel::Status status) override; + + // Is a command already being processed + bool IsMoving() const { return mMovementState == CameraAvSettingsUserLevelManagement::PhysicalMovementEnum::kMoving; } + +private: + CameraAvSettingsUserLevelManagementDelegate * mDelegate = nullptr; + MarkDirtyCallback mMarkDirtyCallback; + + // Holding variables for values subject to successful physical movement + Optional mTargetPan; + Optional mTargetTilt; + Optional mTargetZoom; + + // Helper Read functions for complex attribute types + CHIP_ERROR ReadAndEncodeMPTZPresets(AttributeValueEncoder & encoder); + CHIP_ERROR ReadAndEncodeDPTZStreams(AttributeValueEncoder & encoder); + + CHIP_ERROR StoreMPTZPosition(const CameraAvSettingsUserLevelManagement::Structs::MPTZStruct::Type & mptzPosition); + CHIP_ERROR LoadMPTZPosition(CameraAvSettingsUserLevelManagement::Structs::MPTZStruct::Type & mptzPosition); + + /** + * Helper function that loads all the persistent attributes from the KVS. + */ + void LoadPersistentAttributes(); + + /** + * Helper function that manages preset IDs + */ + void UpdatePresetID(); + + /** + * Helper function that validates whether a given video stream ID is already known + */ + bool KnownVideoStreamID(uint16_t aVideoStreamID); + + /** + * Mutator for MovementState, only accessible by the server instance + */ + void SetMovementState(CameraAvSettingsUserLevelManagement::PhysicalMovementEnum aMovementState); + /** + * Helper function for attribute handlers to mark the attribute as dirty + */ + void MarkDirty(AttributeId aAttributeId); +}; + +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/examples/camera-app/camera-common/include/webrtc-provider-controller/webrtc-provider-controller.h b/src/app/clusters/camera-av-settings-user-level-management-server/CodegenIntegration.cpp similarity index 52% rename from examples/camera-app/camera-common/include/webrtc-provider-controller/webrtc-provider-controller.h rename to src/app/clusters/camera-av-settings-user-level-management-server/CodegenIntegration.cpp index 99a5372aedb..4cfb0faa6aa 100644 --- a/examples/camera-app/camera-common/include/webrtc-provider-controller/webrtc-provider-controller.h +++ b/src/app/clusters/camera-av-settings-user-level-management-server/CodegenIntegration.cpp @@ -16,27 +16,17 @@ * limitations under the License. */ -#pragma once +#include -#include +// These callbacks are required by the Ember/codegen integration but are not +// needed for the server cluster interface implementation. -namespace chip { -namespace app { -namespace Clusters { -namespace WebRTCTransportProvider { - -/** - * The application interface to define the options & implement commands. - */ -class WebRTCTransportProviderController +void MatterCameraAvSettingsUserLevelManagementPluginServerInitCallback() { -public: - virtual ~WebRTCTransportProviderController() = default; + ChipLogProgress(Zcl, "Initializing Camera AV Settings User Level Management cluster."); +} - virtual void SetWebRTCTransportProvider(std::unique_ptr webRTCTransportProvider) = 0; -}; - -} // namespace WebRTCTransportProvider -} // namespace Clusters -} // namespace app -} // namespace chip +void MatterCameraAvSettingsUserLevelManagementPluginServerShutdownCallback() +{ + ChipLogProgress(Zcl, "Shutdown Camera AV Settings User Level Management cluster."); +} diff --git a/src/app/clusters/camera-av-settings-user-level-management-server/app_config_dependent_sources.cmake b/src/app/clusters/camera-av-settings-user-level-management-server/app_config_dependent_sources.cmake index 94da74ffc56..64fa023541d 100644 --- a/src/app/clusters/camera-av-settings-user-level-management-server/app_config_dependent_sources.cmake +++ b/src/app/clusters/camera-av-settings-user-level-management-server/app_config_dependent_sources.cmake @@ -16,6 +16,9 @@ TARGET_SOURCES( ${APP_TARGET} PRIVATE - "${CLUSTER_DIR}/camera-av-settings-user-level-management-server.cpp" - "${CLUSTER_DIR}/camera-av-settings-user-level-management-server.h" + "${CLUSTER_DIR}/CameraAvSettingsUserLevelManagementCluster.cpp" + "${CLUSTER_DIR}/CameraAvSettingsUserLevelManagementCluster.h" + "${CLUSTER_DIR}/camera-av-settings-user-level-management-logic.cpp" + "${CLUSTER_DIR}/camera-av-settings-user-level-management-logic.h" + "${CLUSTER_DIR}/CodegenIntegration.cpp" ) \ No newline at end of file diff --git a/src/app/clusters/camera-av-settings-user-level-management-server/app_config_dependent_sources.gni b/src/app/clusters/camera-av-settings-user-level-management-server/app_config_dependent_sources.gni index f5559bbe5cf..2c3232e2a4b 100644 --- a/src/app/clusters/camera-av-settings-user-level-management-server/app_config_dependent_sources.gni +++ b/src/app/clusters/camera-av-settings-user-level-management-server/app_config_dependent_sources.gni @@ -11,7 +11,4 @@ # 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. -app_config_dependent_sources = [ - "camera-av-settings-user-level-management-server.cpp", - "camera-av-settings-user-level-management-server.h", -] +app_config_dependent_sources = [ "CodegenIntegration.cpp" ] diff --git a/src/app/clusters/camera-av-settings-user-level-management-server/camera-av-settings-user-level-management-server.cpp b/src/app/clusters/camera-av-settings-user-level-management-server/camera-av-settings-user-level-management-server.cpp deleted file mode 100644 index c115b97ceae..00000000000 --- a/src/app/clusters/camera-av-settings-user-level-management-server/camera-av-settings-user-level-management-server.cpp +++ /dev/null @@ -1,1391 +0,0 @@ -/** - * - * Copyright (c) 2025 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace chip; -using namespace chip::app; -using namespace chip::app::Clusters; -using namespace chip::app::Clusters::CameraAvSettingsUserLevelManagement; -using namespace chip::app::Clusters::CameraAvSettingsUserLevelManagement::Structs; -using namespace chip::app::Clusters::CameraAvSettingsUserLevelManagement::Attributes; -using namespace Protocols::InteractionModel; - -namespace chip { -namespace app { -namespace Clusters { -namespace CameraAvSettingsUserLevelManagement { - -CameraAvSettingsUserLevelMgmtServer::CameraAvSettingsUserLevelMgmtServer(EndpointId aEndpointId, Delegate & aDelegate, - BitFlags aFeatures, - BitFlags aOptionalAttrs, - uint8_t aMaxPresets) : - AttributeAccessInterface(MakeOptional(aEndpointId), CameraAvSettingsUserLevelManagement::Id), - CommandHandlerInterface(MakeOptional(aEndpointId), CameraAvSettingsUserLevelManagement::Id), mDelegate(aDelegate), - mEndpointId(aEndpointId), mFeatures(aFeatures), mOptionalAttrs(aOptionalAttrs), mMaxPresets(aMaxPresets) -{ - mDelegate.SetServer(this); -} - -CameraAvSettingsUserLevelMgmtServer::~CameraAvSettingsUserLevelMgmtServer() -{ - // Unregister command handler and attribute access interfaces - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); - AttributeAccessInterfaceRegistry::Instance().Unregister(this); - mDelegate.SetServer(nullptr); -} - -CHIP_ERROR CameraAvSettingsUserLevelMgmtServer::Init() -{ - // Make sure mandated Features are set - // - VerifyOrReturnError(HasFeature(Feature::kMechanicalPan) || HasFeature(Feature::kMechanicalTilt) || - HasFeature(Feature::kMechanicalZoom) || HasFeature(Feature::kDigitalPTZ), - CHIP_ERROR_INVALID_ARGUMENT, - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: Feature configuration error. At least one of " - "Mechanical Pan, Tilt, Zoom or Digital PTZ must be supported", - mEndpointId)); - - // All of the attributes are dependent on Feature Flags being set, ensure that this is the case - // - if (SupportsOptAttr(OptionalAttributes::kMptzPosition) != - (HasFeature(Feature::kMechanicalPan) || HasFeature(Feature::kMechanicalTilt) || HasFeature(Feature::kMechanicalZoom))) - { - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: Feature configuration error. If MPTZPosition is enabled " - "then one of Pan, Tilt, or Zoom is required and vice versa", - mEndpointId); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - if (SupportsOptAttr(OptionalAttributes::kMaxPresets) != HasFeature(Feature::kMechanicalPresets)) - { - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: Feature configuration error. If MaxPresets " - "is enabled, then MechanicalPresets feature is required and vice versa", - mEndpointId); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - if (SupportsOptAttr(OptionalAttributes::kMptzPresets) != HasFeature(Feature::kMechanicalPresets)) - { - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: Feature configuration error. If MPTZPresets " - "is enabled, then MechanicalPresets feature is required", - mEndpointId); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - if (SupportsOptAttr(OptionalAttributes::kDptzStreams) != HasFeature(Feature::kDigitalPTZ)) - { - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: Feature configuration error. If " - "DPTZStreams is enabled, then DigitalPTZ feature is required and vice versa", - mEndpointId); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - if (SupportsOptAttr(OptionalAttributes::kZoomMax) != HasFeature(Feature::kMechanicalZoom)) - { - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: Feature configuration error. If ZoomMax is " - "enabled, then MechanicalZoom feature is required and vice versa", - mEndpointId); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - if (SupportsOptAttr(OptionalAttributes::kTiltMin) != HasFeature(Feature::kMechanicalTilt)) - { - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: Feature configuration error. If TiltMin is " - "enabled, then MechanicalTilt feature is required and vice versa", - mEndpointId); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - if (SupportsOptAttr(OptionalAttributes::kTiltMax) != HasFeature(Feature::kMechanicalTilt)) - { - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: Feature configuration error. If TiltMax is " - "enabled, then MechanicalTilt feature is required and vice versa", - mEndpointId); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - if (SupportsOptAttr(OptionalAttributes::kPanMin) != HasFeature(Feature::kMechanicalPan)) - { - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: Feature configuration error. If PanMin is " - "enabled, then MechanicalPan feature is required and vice versa", - mEndpointId); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - if (SupportsOptAttr(OptionalAttributes::kPanMax) != HasFeature(Feature::kMechanicalPan)) - { - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: Feature configuration error. If PanMax is " - "enabled, then MechanicalPan feature is required and vice versa", - mEndpointId); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - if (SupportsOptAttr(OptionalAttributes::kMovementState) != - (HasFeature(Feature::kMechanicalPan) || HasFeature(Feature::kMechanicalTilt) || HasFeature(Feature::kMechanicalZoom))) - { - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: Feature configuration error. If MovementState is enabled " - "then one of Pan, Tilt, or Zoom is required and vice versa", - mEndpointId); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - // Set up our defaults - SetPan(MakeOptional(kDefaultPan)); - SetTilt(MakeOptional(kDefaultTilt)); - SetZoom(MakeOptional(kDefaultZoom)); - - SetMovementState(PhysicalMovementEnum::kIdle); - - LoadPersistentAttributes(); - - VerifyOrReturnError(AttributeAccessInterfaceRegistry::Instance().Register(this), CHIP_ERROR_INTERNAL); - ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(this)); - return CHIP_NO_ERROR; -} - -void CameraAvSettingsUserLevelMgmtServer::Shutdown() -{ - mDelegate.ShutdownApp(); -} - -bool CameraAvSettingsUserLevelMgmtServer::HasFeature(Feature aFeature) const -{ - return mFeatures.Has(aFeature); -} - -bool CameraAvSettingsUserLevelMgmtServer::SupportsOptAttr(OptionalAttributes aOptionalAttr) const -{ - return mOptionalAttrs.Has(aOptionalAttr); -} - -void CameraAvSettingsUserLevelMgmtServer::MarkDirty(AttributeId aAttributeId) -{ - MatterReportingAttributeChangeCallback(mEndpointId, CameraAvSettingsUserLevelManagement::Id, aAttributeId); -} - -CHIP_ERROR CameraAvSettingsUserLevelMgmtServer::StoreMPTZPosition(const MPTZStructType & mptzPosition) -{ - uint8_t buffer[kMptzPositionStructMaxSerializedSize]; - MutableByteSpan bufferSpan(buffer); - TLV::TLVWriter writer; - - writer.Init(bufferSpan); - ReturnErrorOnFailure(mptzPosition.Encode(writer, TLV::AnonymousTag())); - - auto path = ConcreteAttributePath(mEndpointId, CameraAvSettingsUserLevelManagement::Id, Attributes::MPTZPosition::Id); - bufferSpan.reduce_size(writer.GetLengthWritten()); - - return GetSafeAttributePersistenceProvider()->SafeWriteValue(path, bufferSpan); -} - -CHIP_ERROR CameraAvSettingsUserLevelMgmtServer::LoadMPTZPosition(MPTZStructType & mptzPosition) -{ - uint8_t buffer[kMptzPositionStructMaxSerializedSize]; - MutableByteSpan bufferSpan(buffer); - - auto path = ConcreteAttributePath(mEndpointId, CameraAvSettingsUserLevelManagement::Id, Attributes::MPTZPosition::Id); - ReturnErrorOnFailure(GetSafeAttributePersistenceProvider()->SafeReadValue(path, bufferSpan)); - - TLV::TLVReader reader; - - reader.Init(bufferSpan); - ReturnErrorOnFailure(reader.Next(TLV::AnonymousTag())); - ReturnErrorOnFailure(mptzPosition.Decode(reader)); - - return CHIP_NO_ERROR; -} - -/** - * Attribute mutators. In all cases, given that these may not have been enabled depending on the Feature Flags that are set, - * the associated Feature presence is checked. The attributes are updated, and marked dirty, only if there is a change in the - * attribute value after constraint checking has been completed. - */ -CHIP_ERROR CameraAvSettingsUserLevelMgmtServer::SetTiltMin(int16_t aTiltMin) -{ - if (!HasFeature(Feature::kMechanicalTilt)) - { - return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); - } - - if ((aTiltMin < kMinTiltValue) || (aTiltMin > kMaxTiltValue - 1) || (aTiltMin > mTiltMax)) - { - return CHIP_IM_GLOBAL_STATUS(ConstraintError); - } - - if (aTiltMin != mTiltMin) - { - mTiltMin = aTiltMin; - MarkDirty(Attributes::TiltMin::Id); - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR CameraAvSettingsUserLevelMgmtServer::SetTiltMax(int16_t aTiltMax) -{ - if (!HasFeature(Feature::kMechanicalTilt)) - { - return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); - } - - if ((aTiltMax > kMaxTiltValue) || (aTiltMax < kMinTiltValue + 1) || (aTiltMax < mTiltMin)) - { - return CHIP_IM_GLOBAL_STATUS(ConstraintError); - } - - if (aTiltMax != mTiltMax) - { - mTiltMax = aTiltMax; - MarkDirty(Attributes::TiltMax::Id); - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR CameraAvSettingsUserLevelMgmtServer::SetPanMin(int16_t aPanMin) -{ - if (!HasFeature(Feature::kMechanicalPan)) - { - return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); - } - - if ((aPanMin < kMinPanValue) || (aPanMin > kMaxPanValue - 1) || (aPanMin > mPanMax)) - { - return CHIP_IM_GLOBAL_STATUS(ConstraintError); - } - - if (aPanMin != mPanMin) - { - mPanMin = aPanMin; - MarkDirty(Attributes::PanMin::Id); - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR CameraAvSettingsUserLevelMgmtServer::SetPanMax(int16_t aPanMax) -{ - if (!HasFeature(Feature::kMechanicalPan)) - { - return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); - } - - if ((aPanMax > kMaxPanValue) || (aPanMax < kMinPanValue + 1) || (aPanMax < mPanMin)) - { - return CHIP_IM_GLOBAL_STATUS(ConstraintError); - } - - if (aPanMax != mPanMax) - { - mPanMax = aPanMax; - MarkDirty(Attributes::PanMax::Id); - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR CameraAvSettingsUserLevelMgmtServer::SetZoomMax(uint8_t aZoomMax) -{ - if (!HasFeature(Feature::kMechanicalZoom)) - { - return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); - } - - if ((aZoomMax > kMaxZoomValue) || (aZoomMax < kMinZoomValue + 1)) - { - return CHIP_IM_GLOBAL_STATUS(ConstraintError); - } - - if (aZoomMax != mZoomMax) - { - mZoomMax = aZoomMax; - MarkDirty(Attributes::ZoomMax::Id); - } - - return CHIP_NO_ERROR; -} - -/** - * Mutators for server copies of Pan, Tilt, and Zoom that may be invoked by a delegate or the server itself in responding to command - * callbacks, or due to local on device changes. - * Only set the value if the Feature Flag is set. - * It is entirely possible for a mutator to be called with a parameter that has no value. Case in point an invoke of - * MPTZSetPosition, this will be handled and the attributes updated if at least one of the three pan, tilt, or zoom have a value, - * with all three params passed through once validation is complete. An empty value is just ignored. - */ -void CameraAvSettingsUserLevelMgmtServer::SetPan(Optional aPan) -{ - if (HasFeature(Feature::kMechanicalPan)) - { - if (aPan.HasValue()) - { - mMptzPosition.pan = aPan; - StoreMPTZPosition(mMptzPosition); - MarkDirty(Attributes::MPTZPosition::Id); - } - } -} - -void CameraAvSettingsUserLevelMgmtServer::SetTilt(Optional aTilt) -{ - if (HasFeature(Feature::kMechanicalTilt)) - { - if (aTilt.HasValue()) - { - mMptzPosition.tilt = aTilt; - StoreMPTZPosition(mMptzPosition); - MarkDirty(Attributes::MPTZPosition::Id); - } - } -} - -void CameraAvSettingsUserLevelMgmtServer::SetZoom(Optional aZoom) -{ - if (HasFeature(Feature::kMechanicalZoom)) - { - if (aZoom.HasValue()) - { - mMptzPosition.zoom = aZoom; - StoreMPTZPosition(mMptzPosition); - MarkDirty(Attributes::MPTZPosition::Id); - } - } -} - -void CameraAvSettingsUserLevelMgmtServer::SetMovementState(PhysicalMovementEnum aMovementState) -{ - if (HasFeature(Feature::kMechanicalPan) || HasFeature(Feature::kMechanicalTilt) || HasFeature(Feature::kMechanicalZoom)) - { - // The attribute is only ever changed to a new value, so this will always be dirty - mMovementState = aMovementState; - MarkDirty(Attributes::MovementState::Id); - } -} - -/** - * Methods handling known video stream IDs, the addition and removal thereof. - */ -void CameraAvSettingsUserLevelMgmtServer::AddMoveCapableVideoStream(uint16_t aVideoStreamID, - Globals::Structs::ViewportStruct::Type aViewport) -{ - DPTZStruct dptzEntry; - dptzEntry.videoStreamID = aVideoStreamID; - dptzEntry.viewport = aViewport; - mDptzStreams.push_back(dptzEntry); - MarkDirty(Attributes::DPTZStreams::Id); -} - -void CameraAvSettingsUserLevelMgmtServer::UpdateMoveCapableVideoStream(uint16_t aVideoStreamID, - Globals::Structs::ViewportStruct::Type aViewport) -{ - auto it = std::find_if(mDptzStreams.begin(), mDptzStreams.end(), - [aVideoStreamID](const DPTZStruct & dptzs) { return dptzs.videoStreamID == aVideoStreamID; }); - - if (it == mDptzStreams.end()) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]. No matching video stream ID, update not possible. ID=%d.", - mEndpointId, aVideoStreamID); - return; - } - - it->viewport = aViewport; - MarkDirty(Attributes::DPTZStreams::Id); -} - -void CameraAvSettingsUserLevelMgmtServer::UpdateMoveCapableVideoStreams(Globals::Structs::ViewportStruct::Type aViewport) -{ - for (auto & dptzStream : mDptzStreams) - { - dptzStream.viewport = aViewport; - } - - MarkDirty(Attributes::DPTZStreams::Id); -} - -void CameraAvSettingsUserLevelMgmtServer::RemoveMoveCapableVideoStream(uint16_t aVideoStreamID) -{ - // Verify that this is a known ID, if it is, remove from the list - // - auto it = std::find_if(mDptzStreams.begin(), mDptzStreams.end(), - [aVideoStreamID](const DPTZStruct & dptzs) { return dptzs.videoStreamID == aVideoStreamID; }); - - if (it == mDptzStreams.end()) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]. No matching video stream ID, removal not possible. ID=%d.", - mEndpointId, aVideoStreamID); - return; - } - - mDptzStreams.erase(it); - MarkDirty(Attributes::DPTZStreams::Id); -} - -/** - * @returns bool True if the provided video stream ID is known to the server. False if not. - */ -bool CameraAvSettingsUserLevelMgmtServer::KnownVideoStreamID(uint16_t aVideoStreamID) -{ - auto it = std::find_if(mDptzStreams.begin(), mDptzStreams.end(), - [aVideoStreamID](const DPTZStruct & dptzs) { return dptzs.videoStreamID == aVideoStreamID; }); - - return (it == mDptzStreams.end() ? false : true); -} - -/** - * Helper function for setting the next preset ID to use in advance of reception of an MPTZSavePreset. - * The method loops over the range of possible IDs, starting with the current ID, if the preset ID is in use, - * it continues to the next possible value, looping back to 1. The checking is needed as the preset IDs aren't - * solely server generated, they can also be provided by a client. - * If there are no free presets (which will happen if all slots are taken), the value is not updated. - */ -void CameraAvSettingsUserLevelMgmtServer::UpdatePresetID() -{ - uint8_t nextIDToCheck = mCurrentPresetID; - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: UpdatePresetID. Current Preset is %d.", mEndpointId, - mCurrentPresetID); - - do - { - nextIDToCheck = static_cast((nextIDToCheck % mMaxPresets) + 1); - - // Have we lapped back round to where we started? If so, break - // - if (nextIDToCheck == mCurrentPresetID) - { - break; - } - - auto it = std::find_if(mMptzPresetHelpers.begin(), mMptzPresetHelpers.end(), - [=](const MPTZPresetHelper & mptzph) { return mptzph.GetPresetID() == nextIDToCheck; }); - if (it == mMptzPresetHelpers.end()) - { - mCurrentPresetID = nextIDToCheck; - break; - } - } while (true); - - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Updated PresetID is %d.", mEndpointId, mCurrentPresetID); -} - -/** - * Helper Read functions for complex attribute types - */ -CHIP_ERROR CameraAvSettingsUserLevelMgmtServer::ReadAndEncodeMPTZPresets(AttributeValueEncoder & aEncoder) -{ - return aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR { - for (const auto & mptzPresets : mMptzPresetHelpers) - { - // Get the details to encode from the preset helper - // - MPTZPresetStructType presetStruct; - std::string name = mptzPresets.GetName(); - uint8_t preset = mptzPresets.GetPresetID(); - presetStruct.presetID = preset; - presetStruct.name = CharSpan(name.c_str(), name.size()); - presetStruct.settings = mptzPresets.GetMptzPosition(); - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Encoding an instance of MPTZPresetStruct. ID = %d. Name = %s", - mEndpointId, presetStruct.presetID, NullTerminated(presetStruct.name).c_str()); - ReturnErrorOnFailure(encoder.Encode(presetStruct)); - } - - return CHIP_NO_ERROR; - }); -} - -CHIP_ERROR CameraAvSettingsUserLevelMgmtServer::ReadAndEncodeDPTZStreams(AttributeValueEncoder & aEncoder) -{ - return aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR { - for (const auto & dptzStream : mDptzStreams) - { - ReturnErrorOnFailure(encoder.Encode(dptzStream)); - } - - return CHIP_NO_ERROR; - }); -} - -void CameraAvSettingsUserLevelMgmtServer::LoadPersistentAttributes() -{ - CHIP_ERROR err = CHIP_NO_ERROR; - // Load MPTZPosition - MPTZStructType storedMPTZPosition; - err = LoadMPTZPosition(storedMPTZPosition); - if (err == CHIP_NO_ERROR) - { - mMptzPosition = storedMPTZPosition; - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Loaded MPTZPosition", mEndpointId); - } - else - { - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Unable to load the MPTZPosition from the KVS.", mEndpointId); - } - - // Load MPTZPresets - err = mDelegate.LoadMPTZPresets(mMptzPresetHelpers); - if (err != CHIP_NO_ERROR) - { - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Unable to load the MPTZPresets from the KVS.", mEndpointId); - } - - // Load DPTZRelativeMove - err = mDelegate.LoadDPTZStreams(mDptzStreams); - if (err != CHIP_NO_ERROR) - { - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Unable to load the DPTZRelativeMove from the KVS.", mEndpointId); - } - - // Signal delegate that all persistent configuration attributes have been loaded. - mDelegate.PersistentAttributesLoadedCallback(); -} - -/** - * AttributeAccessInterface - */ -CHIP_ERROR CameraAvSettingsUserLevelMgmtServer::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) -{ - VerifyOrDie(aPath.mClusterId == CameraAvSettingsUserLevelManagement::Id); - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Camera AV Settings User Level Management: Reading", mEndpointId); - - switch (aPath.mAttributeId) - { - case FeatureMap::Id: - ReturnErrorOnFailure(aEncoder.Encode(mFeatures)); - break; - case MPTZPosition::Id: - VerifyOrReturnError( - HasFeature(Feature::kMechanicalPan) || HasFeature(Feature::kMechanicalTilt) || HasFeature(Feature::kMechanicalZoom), - CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: can not get MPTZPosition, feature is not supported", - mEndpointId)); - - ReturnErrorOnFailure(aEncoder.Encode(mMptzPosition)); - break; - case MaxPresets::Id: - VerifyOrReturnError(HasFeature(Feature::kMechanicalPresets), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: can not get MaxPresets, feature is not supported", - mEndpointId)); - - ReturnErrorOnFailure(aEncoder.Encode(mMaxPresets)); - break; - case MPTZPresets::Id: - VerifyOrReturnError(HasFeature(Feature::kMechanicalPresets), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: can not get MPTZPresets, feature is not supported", - mEndpointId)); - - return ReadAndEncodeMPTZPresets(aEncoder); - case DPTZStreams::Id: - VerifyOrReturnError( - HasFeature(Feature::kDigitalPTZ), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: can not get DPTZRelativeMove, feature is not supported", - mEndpointId)); - return ReadAndEncodeDPTZStreams(aEncoder); - case ZoomMax::Id: - VerifyOrReturnError( - HasFeature(Feature::kMechanicalZoom), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: can not get ZoomMax, feature is not supported", mEndpointId)); - ReturnErrorOnFailure(aEncoder.Encode(mZoomMax)); - break; - case TiltMin::Id: - VerifyOrReturnError( - HasFeature(Feature::kMechanicalTilt), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: can not get TiltMin, feature is not supported", mEndpointId)); - ReturnErrorOnFailure(aEncoder.Encode(mTiltMin)); - break; - case TiltMax::Id: - VerifyOrReturnError( - HasFeature(Feature::kMechanicalTilt), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: can not get TiltMax, feature is not supported", mEndpointId)); - ReturnErrorOnFailure(aEncoder.Encode(mTiltMax)); - break; - case PanMin::Id: - VerifyOrReturnError( - HasFeature(Feature::kMechanicalPan), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: can not get PanMin, feature is not supported", mEndpointId)); - ReturnErrorOnFailure(aEncoder.Encode(mPanMin)); - break; - case PanMax::Id: - VerifyOrReturnError( - HasFeature(Feature::kMechanicalPan), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: can not get PanMax, feature is not supported", mEndpointId)); - ReturnErrorOnFailure(aEncoder.Encode(mPanMax)); - break; - case MovementState::Id: - VerifyOrReturnError( - HasFeature(Feature::kMechanicalPan) || HasFeature(Feature::kMechanicalTilt) || HasFeature(Feature::kMechanicalZoom), - CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: can not get MovementState, feature is not supported", - mEndpointId)); - ReturnErrorOnFailure(aEncoder.Encode(mMovementState)); - } - - return CHIP_NO_ERROR; -} - -/** - * CommandHandlerInterface - */ -void CameraAvSettingsUserLevelMgmtServer::InvokeCommand(HandlerContext & handlerContext) -{ - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: InvokeCommand", mEndpointId); - - switch (handlerContext.mRequestPath.mCommandId) - { - case Commands::MPTZSetPosition::Id: - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Setting MPTZ Position", mEndpointId); - - if (!HasFeature(Feature::kMechanicalPan) && !HasFeature(Feature::kMechanicalTilt) && !HasFeature(Feature::kMechanicalZoom)) - { - handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); - } - else - { - HandleCommand( - handlerContext, - [this](HandlerContext & ctx, const auto & commandData) { HandleMPTZSetPosition(ctx, commandData); }); - } - return; - - case Commands::MPTZRelativeMove::Id: - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Relative move of MPTZ Position", mEndpointId); - - if (!HasFeature(Feature::kMechanicalPan) && !HasFeature(Feature::kMechanicalTilt) && !HasFeature(Feature::kMechanicalZoom)) - { - handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); - } - else - { - HandleCommand( - handlerContext, - [this](HandlerContext & ctx, const auto & commandData) { HandleMPTZRelativeMove(ctx, commandData); }); - } - return; - - case Commands::MPTZMoveToPreset::Id: - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Moving to an indicated MPTZ Preset", mEndpointId); - - if (!HasFeature(Feature::kMechanicalPresets)) - { - handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); - } - else - { - HandleCommand( - handlerContext, - [this](HandlerContext & ctx, const auto & commandData) { HandleMPTZMoveToPreset(ctx, commandData); }); - } - return; - - case Commands::MPTZSavePreset::Id: - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Saving MPTZ Preset", mEndpointId); - - if (!HasFeature(Feature::kMechanicalPresets)) - { - handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); - } - else - { - HandleCommand( - handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleMPTZSavePreset(ctx, commandData); }); - } - return; - - case Commands::MPTZRemovePreset::Id: - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Remove indicated MPTZ Preset", mEndpointId); - - if (!HasFeature(Feature::kMechanicalPresets)) - { - handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); - } - else - { - HandleCommand( - handlerContext, - [this](HandlerContext & ctx, const auto & commandData) { HandleMPTZRemovePreset(ctx, commandData); }); - } - return; - - case Commands::DPTZSetViewport::Id: - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Setting DPTZ Viewport", mEndpointId); - - if (!HasFeature(Feature::kDigitalPTZ)) - { - handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); - } - else - { - HandleCommand( - handlerContext, - [this](HandlerContext & ctx, const auto & commandData) { HandleDPTZSetViewport(ctx, commandData); }); - } - return; - - case Commands::DPTZRelativeMove::Id: - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Relative move within a defined DPTZ Viewport", mEndpointId); - - if (!HasFeature(Feature::kDigitalPTZ)) - { - handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); - } - else - { - HandleCommand( - handlerContext, - [this](HandlerContext & ctx, const auto & commandData) { HandleDPTZRelativeMove(ctx, commandData); }); - } - return; - } -} - -void CameraAvSettingsUserLevelMgmtServer::HandleMPTZSetPosition(HandlerContext & ctx, - const Commands::MPTZSetPosition::DecodableType & commandData) -{ - bool hasAtLeastOneValue = false; - - Optional pan = commandData.pan; - Optional tilt = commandData.tilt; - Optional zoom = commandData.zoom; - - // Validate the received command fields - // - if (pan.HasValue()) - { - if (!HasFeature(Feature::kMechanicalPan)) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Mechanical Pan not supported although pan value provided", - mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - return; - } - int16_t panValue = pan.Value(); - if ((panValue > mPanMax) || (panValue < mPanMin)) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Received Pan value out of range", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; - } - hasAtLeastOneValue = true; - } - - if (tilt.HasValue()) - { - if (!HasFeature(Feature::kMechanicalTilt)) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Mechanical Tilt not supported although tilt value provided", - mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - return; - } - int16_t tiltValue = tilt.Value(); - if ((tiltValue > mTiltMax) || (tiltValue < mTiltMin)) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Received Tilt value out of range", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; - } - hasAtLeastOneValue = true; - } - - if (zoom.HasValue()) - { - if (!HasFeature(Feature::kMechanicalZoom)) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Mechanical Zoom not supported although zoom value provided", - mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - return; - } - uint8_t zoomValue = zoom.Value(); - if ((zoomValue > mZoomMax) || (zoomValue < kMinZoomValue)) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Received Zoom value out of range", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; - } - hasAtLeastOneValue = true; - } - - // Was a value received in the command - if (!hasAtLeastOneValue) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: MPTZSetPosition command contains no actionable fields", - mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - return; - } - - // If the camera is still in motion, then return Busy. Subsequently check with the delegate that we're in a position to change - // any of the PTZ values which may not be possible for other reasons - // - if (IsMoving()) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Busy); - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: cannot execute command as camera is busy with a physical movement", - mEndpointId); - return; - } - - if (!mDelegate.CanChangeMPTZ()) - { - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Device not able to process MPTZ change", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Busy); - return; - } - - Status status = mDelegate.MPTZSetPosition(pan, tilt, zoom, this); - - if (status != Status::Success) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); - return; - } - - // We don't update the server persisted attributes until the delegate confirms via callback that the physical device movement is - // complete - // - mTargetPan = pan; - mTargetTilt = tilt; - mTargetZoom = zoom; - - SetMovementState(PhysicalMovementEnum::kMoving); - - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); -} - -void CameraAvSettingsUserLevelMgmtServer::HandleMPTZRelativeMove(HandlerContext & ctx, - const Commands::MPTZRelativeMove::DecodableType & commandData) -{ - bool hasAtLeastOneValue = false; - - Optional panDelta = commandData.panDelta; - Optional tiltDelta = commandData.tiltDelta; - Optional zoomDelta = commandData.zoomDelta; - - // These will all be set to actual values if there is a delta provided, and constraint checking passes. - Optional newPan; - Optional newTilt; - Optional newZoom; - - // Validate the received command fields - // - if (panDelta.HasValue()) - { - if (!HasFeature(Feature::kMechanicalPan)) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Mechanical Pan not supported although panDelta value provided", - mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - return; - } - int16_t panDeltaValue = panDelta.Value(); - if (panDeltaValue > (mPanMax - mPanMin) || panDeltaValue < -(mPanMax - mPanMin)) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: PanDelta value received is out of range.", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; - } - - // If we're here, then we'll also have an existing Pan value in MPTZPosition - // Note that newPan is always between -180 and 180; and the panDeltaValue is constrained to -360 to 360 by the - // code above, so the addition sum can never overflow int16_t. - // - int16_t newPanValue = static_cast(mMptzPosition.pan.Value() + panDeltaValue); - if (newPanValue > mPanMax) - { - newPanValue = mPanMax; - } - if (newPanValue < mPanMin) - { - newPanValue = mPanMin; - } - - newPan.Emplace(newPanValue); - - hasAtLeastOneValue = true; - } - - if (tiltDelta.HasValue()) - { - if (!HasFeature(Feature::kMechanicalTilt)) - { - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: Mechanical Tilt not supported although tiltDelta value provided", - mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - return; - } - int16_t tiltDeltaValue = tiltDelta.Value(); - if (tiltDeltaValue > (mTiltMax - mTiltMin) || tiltDeltaValue < -(mTiltMax - mTiltMin)) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: TiltDelta value received is out of range.", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; - } - - // If we're here, then we'll also have an existing Tilt value in MPTZPosition - // Note that newTilt is always between -180 and 180; and the tiltDeltaValue is constrained to -360 to 360 by the - // code above, so the addition sum can never overflow int16_t. - // - int16_t newTiltValue = static_cast(mMptzPosition.tilt.Value() + tiltDeltaValue); - if (newTiltValue > mTiltMax) - { - newTiltValue = mTiltMax; - } - if (newTiltValue < mTiltMin) - { - newTiltValue = mTiltMin; - } - - newTilt.Emplace(newTiltValue); - - hasAtLeastOneValue = true; - } - - if (zoomDelta.HasValue()) - { - if (!HasFeature(Feature::kMechanicalZoom)) - { - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: Mechanical Zoom not supported although zoomDelta value provided", - mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - return; - } - int8_t zoomDeltaValue = zoomDelta.Value(); - if (zoomDeltaValue > (mZoomMax - 1) || zoomDeltaValue < -(mZoomMax - 1)) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: ZoomDelta value received is out of range.", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; - } - - // If we're here, then we'll also have an existing Zoom value in MPTZPosition. The zoom values are constrained such that - // we won't overflow newZoomValue - // - int newZoomValue = static_cast(mMptzPosition.zoom.Value()) + zoomDeltaValue; - - if (newZoomValue > mZoomMax) - { - newZoomValue = static_cast(mZoomMax); - } - if (newZoomValue < 1) - { - newZoomValue = 1; - } - - newZoom.Emplace(static_cast(newZoomValue)); - - hasAtLeastOneValue = true; - } - - // Was a value received in the command - if (!hasAtLeastOneValue) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: MPTZRelativeMove command contains no actionable fields", - mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - return; - } - - // If the camera is still in motion, then return Busy. Subsequently check with the delegate that we're in a position to change - // any of the PTZ values which may not be possible for other reasons - // - if (IsMoving()) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Busy); - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: cannot execute command as camera is busy with a physical movement", - mEndpointId); - return; - } - - if (!mDelegate.CanChangeMPTZ()) - { - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Device not able to process MPTZ relative value change", - mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Busy); - return; - } - - Status status = mDelegate.MPTZRelativeMove(newPan, newTilt, newZoom, this); - - if (status != Status::Success) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); - return; - } - - // We don't update the server persisted attributes until the delegate confirms via callback that the physical device movement is - // complete - // - mTargetPan = newPan; - mTargetTilt = newTilt; - mTargetZoom = newZoom; - SetMovementState(PhysicalMovementEnum::kMoving); - - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); -} - -void CameraAvSettingsUserLevelMgmtServer::HandleMPTZMoveToPreset(HandlerContext & ctx, - const Commands::MPTZMoveToPreset::DecodableType & commandData) -{ - uint8_t preset = commandData.presetID; - - // Verify the provided presetID is within spec limits - // - if ((preset > mMaxPresets) || (preset < 1)) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Preset provided is out of range. Preset: %d", mEndpointId, preset); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; - } - // Do we have any presets? - // - if (mMptzPresetHelpers.empty()) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: No stored presets, MoveToPreset not possible", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); - return; - } - - // We have presets, check that the received ID is a valid preset ID - // - auto it = std::find_if(mMptzPresetHelpers.begin(), mMptzPresetHelpers.end(), - [preset](const MPTZPresetHelper & mptzph) { return mptzph.GetPresetID() == preset; }); - - if (it == mMptzPresetHelpers.end()) - { - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: No matching presets, MoveToPreset not possible for provided preset: %d", - mEndpointId, preset); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); - return; - } - - // If the camera is still in motion, then return Busy. Subsequently check with the delegate that we're in a position to change - // any of the PTZ values which may not be possible for other reasons - // - if (IsMoving()) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Busy); - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: cannot execute command as camera is busy with a physical movement", - mEndpointId); - return; - } - - if (!mDelegate.CanChangeMPTZ()) - { - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Device not able to process move to MPTZ preset", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Busy); - return; - } - - auto presetValues = it->GetMptzPosition(); - - // Inform the delegate that the device is requested to move to PTZ values given by the selected preset id - Status status = mDelegate.MPTZMoveToPreset(preset, presetValues.pan, presetValues.tilt, presetValues.zoom, this); - - if (status != Status::Success) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); - return; - } - - // We don't update the server persisted attributes until the delegate confirms via callback that the physical device movement is - // complete - // - mTargetPan = presetValues.pan; - mTargetTilt = presetValues.tilt; - mTargetZoom = presetValues.zoom; - SetMovementState(PhysicalMovementEnum::kMoving); - - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); -} - -void CameraAvSettingsUserLevelMgmtServer::HandleMPTZSavePreset(HandlerContext & ctx, - const Commands::MPTZSavePreset::DecodableType & commandData) -{ - Status status = Status::Success; - - Optional preset = commandData.presetID; - chip::CharSpan presetName = commandData.name; - uint8_t presetToUse = mCurrentPresetID; - - // Do we have a user provided preset ID? If yes, is it in range? - // - if (preset.HasValue()) - { - if ((preset.Value() > mMaxPresets) || (preset.Value() < 1)) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Provided preset ID is out of range. Preset: %d", mEndpointId, - preset.Value()); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; - } - presetToUse = preset.Value(); - } - - // Does the preset equate to an already known stored preset? If so we're updating that one rather than creating a new one - // - auto it = std::find_if(mMptzPresetHelpers.begin(), mMptzPresetHelpers.end(), - [presetToUse](const MPTZPresetHelper & mptzph) { return mptzph.GetPresetID() == presetToUse; }); - - // If the current preset ID results in an entry from the current known set and there was a provided preset then we're updating - // an existing preset. Only check for exhausting max presets if we're NOT updating. - // It is possible that mCurrentPresetID equates to a current preset in cases where the collection of presets is full - // - bool updatingExistingPreset = (it != mMptzPresetHelpers.end()) && (preset.HasValue()); - - if (!updatingExistingPreset) - { - // Make sure that the vector will not exceed the max size - // - if (mMptzPresetHelpers.size() == mMaxPresets) - { - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: No more space for additional presets, MPTZSavePreset not possible", - mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ResourceExhausted); - return; - } - } - - // Call the delegate, make sure that it is ok to save a new preset, given the current - // delegate aware values for MPTZ - // - status = mDelegate.MPTZSavePreset(presetToUse); - - if (status != Status::Success) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); - return; - } - - // Capture the current MPTZ values in the preset - // - MPTZPresetHelper aMptzPresetHelper; - - aMptzPresetHelper.SetPresetID(presetToUse); - aMptzPresetHelper.SetName(presetName); - aMptzPresetHelper.SetMptzPosition(mMptzPosition); - - // If an update, replace what is at the iterator, otherwise add to the set as tis is new - // - if (updatingExistingPreset) - { - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Updating existing MPTZ Preset. Preset ID = %d. Preset Name = %s", - mEndpointId, presetToUse, aMptzPresetHelper.GetName().c_str()); - *it = aMptzPresetHelper; - } - else - { - ChipLogDetail(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Saving new MPTZ Preset. Preset ID = %d. Preset Name = %s", - mEndpointId, presetToUse, aMptzPresetHelper.GetName().c_str()); - mMptzPresetHelpers.push_back(aMptzPresetHelper); - } - - // Update the current preset ID to the next available only if we actually used the current value. A user provided preset - // could have any value between 1 and MaxPresets - // - if (presetToUse == mCurrentPresetID) - { - UpdatePresetID(); - } - - MarkDirty(Attributes::MPTZPresets::Id); - - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Success); -} - -void CameraAvSettingsUserLevelMgmtServer::HandleMPTZRemovePreset(HandlerContext & ctx, - const Commands::MPTZRemovePreset::DecodableType & commandData) -{ - uint8_t presetToRemove = commandData.presetID; - - // Verify the provided presetID is within spec limits - // - if ((presetToRemove > mMaxPresets) || (presetToRemove < 1)) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Preset to remove is out of range. Preset: %d", mEndpointId, - presetToRemove); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; - } - - // Is the provided ID known to us? - // - auto it = std::find_if(mMptzPresetHelpers.begin(), mMptzPresetHelpers.end(), - [presetToRemove](const MPTZPresetHelper & mptzph) { return mptzph.GetPresetID() == presetToRemove; }); - - if (it == mMptzPresetHelpers.end()) - { - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: No matching presets, RemovePreset not possible for provided preset: %d", - mEndpointId, presetToRemove); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); - return; - } - - // Call the delegate to ensure that it is ok to remove the preset indicated. - // - Status status = mDelegate.MPTZRemovePreset(presetToRemove); - - if (status != Status::Success) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); - return; - } - - // Remove the identified item from the known set of presets - // - mMptzPresetHelpers.erase(it); - MarkDirty(Attributes::MPTZPresets::Id); - - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Success); -} - -void CameraAvSettingsUserLevelMgmtServer::HandleDPTZSetViewport(HandlerContext & ctx, - const Commands::DPTZSetViewport::DecodableType & commandData) -{ - uint16_t videoStreamID = commandData.videoStreamID; - Globals::Structs::ViewportStruct::Type viewport = commandData.viewport; - - // Is this a video stream ID of which we have already been informed? - // If not, fail. - // - if (!KnownVideoStreamID(videoStreamID)) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]: Unknown Video Stream ID provided. ID: %d", mEndpointId, - videoStreamID); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); - return; - } - - // Call the delegate - Status status = mDelegate.DPTZSetViewport(videoStreamID, viewport); - - if (status == Status::Success) - { - // Update the viewport of our stream in DPTZStreams - // - UpdateMoveCapableVideoStream(videoStreamID, viewport); - } - - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); -} - -void CameraAvSettingsUserLevelMgmtServer::HandleDPTZRelativeMove(HandlerContext & ctx, - const Commands::DPTZRelativeMove::DecodableType & commandData) -{ - uint16_t videoStreamID = commandData.videoStreamID; - Optional deltaX = commandData.deltaX; - Optional deltaY = commandData.deltaY; - Optional zoomDelta = commandData.zoomDelta; - - // Verify that a received Zoom Delta is within constraints - // - if (zoomDelta.HasValue()) - { - int8_t zoomDeltaValue = zoomDelta.Value(); - if (zoomDeltaValue < -100 || zoomDeltaValue > 100) - { - ChipLogError(Zcl, - "CameraAVSettingsUserLevelMgmt[ep=%d]: Provided Digital Zoom Delta is out of range. Provided Zoom: %d", - mEndpointId, zoomDeltaValue); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; - } - } - // Is this a video stream ID of which we have already been informed via DPTZSetViewport. We can't relative move on a - // viewport that hasn't already been set, hence we fail if the provided id is not found. - // - if (!KnownVideoStreamID(videoStreamID)) - { - ChipLogError(Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]. Unknown Video Stream ID provided. ID=%d.", mEndpointId, - videoStreamID); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); - return; - } - - // Create a viewport and call the delegate; on success update our Stream Viewport with that which was set - Globals::Structs::ViewportStruct::Type viewport; - Status status = mDelegate.DPTZRelativeMove(videoStreamID, deltaX, deltaY, zoomDelta, viewport); - - if (status == Status::Success) - { - UpdateMoveCapableVideoStream(videoStreamID, viewport); - } - - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); -} - -// Physical device movement callback -// -void CameraAvSettingsUserLevelMgmtServer::OnPhysicalMovementComplete(Status status) -{ - // Make sure we're running in the Matter thread - assertChipStackLockedByCurrentThread(); - - if (status == Status::Success) - { - SetPan(mTargetPan); - SetTilt(mTargetTilt); - SetZoom(mTargetZoom); - } - else - { - ChipLogError( - Zcl, "CameraAVSettingsUserLevelMgmt[ep=%d]. Camera failed to move to new requested values of Pan, Tilt, and/or Zoom.", - mEndpointId); - } - - SetMovementState(PhysicalMovementEnum::kIdle); -} - -} // namespace CameraAvSettingsUserLevelManagement -} // namespace Clusters -} // namespace app -} // namespace chip - -/** @brief Camera AV Settings User Level Management Cluster Server Init - * - * Server Init - * - */ -void MatterCameraAvSettingsUserLevelManagementPluginServerInitCallback() {} diff --git a/src/app/clusters/camera-av-settings-user-level-management-server/tests/BUILD.gn b/src/app/clusters/camera-av-settings-user-level-management-server/tests/BUILD.gn new file mode 100644 index 00000000000..16dea4e9ea4 --- /dev/null +++ b/src/app/clusters/camera-av-settings-user-level-management-server/tests/BUILD.gn @@ -0,0 +1,35 @@ +# Copyright (c) 2025 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +import("${chip_root}/build/chip/chip_test_suite.gni") + +chip_test_suite("tests") { + output_name = "libTestCameraAvSettingsUserLevelManagementCluster" + + # Comment out unit tests due to dependencies that aren't in the 1.5 branch + # test_sources = [ "TestCameraAvSettingsUserLevelManagementCluster.cpp" ] + + cflags = [ "-Wconversion" ] + + public_deps = [ + "${chip_root}/src/app/clusters/camera-av-settings-user-level-management-server", + "${chip_root}/src/app/server-cluster/testing", + "${chip_root}/src/lib/core:string-builder-adapters", + "${chip_root}/src/lib/support", + "${chip_root}/src/protocols", + ] +} diff --git a/src/app/clusters/camera-av-settings-user-level-management-server/tests/TestCameraAvSettingsUserLevelManagementCluster.cpp b/src/app/clusters/camera-av-settings-user-level-management-server/tests/TestCameraAvSettingsUserLevelManagementCluster.cpp new file mode 100644 index 00000000000..3bd41f166aa --- /dev/null +++ b/src/app/clusters/camera-av-settings-user-level-management-server/tests/TestCameraAvSettingsUserLevelManagementCluster.cpp @@ -0,0 +1,728 @@ +/* + * Copyright (c) 2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::CameraAvSettingsUserLevelManagement; + +using namespace Protocols::InteractionModel; +using namespace chip::Testing; + +using chip::Testing::IsAcceptedCommandsListEqualTo; +using chip::Testing::IsAttributesListEqualTo; + +static constexpr chip::EndpointId kTestEndpointId = 1; +static constexpr uint8_t testMaxPresets = 5; + +// Minimal mock delegate for testing +class MockCameraAvSettingsUserLevelManagementDelegate : public CameraAvSettingsUserLevelManagementDelegate +{ +public: + void ShutdownApp() {} + + bool CanChangeMPTZ() { return true; } + + void VideoStreamAllocated(uint16_t aStreamID) {} + void VideoStreamDeallocated(uint16_t aStreamID) {} + void DefaultViewportUpdated(Globals::Structs::ViewportStruct::Type aViewport) {} + + Status MPTZSetPosition(Optional aPan, Optional aTilt, Optional aZoom, PhysicalPTZCallback * callback) + { + return Status::Success; + } + + Status MPTZRelativeMove(Optional aPan, Optional aTilt, Optional aZoom, + PhysicalPTZCallback * callback) + { + return Status::Success; + } + + Status MPTZMoveToPreset(uint8_t aPreset, Optional aPan, Optional aTilt, Optional aZoom, + PhysicalPTZCallback * callback) + { + return Status::Success; + } + + Status MPTZSavePreset(uint8_t aPreset) { return Status::Success; } + + Status MPTZRemovePreset(uint8_t aPreset) { return Status::Success; } + + Status DPTZSetViewport(uint16_t aVideoStreamID, Globals::Structs::ViewportStruct::Type aViewport) { return Status::Success; } + + Status DPTZRelativeMove(uint16_t aVideoStreamID, Optional aDeltaX, Optional aDeltaY, + Optional aZoomDelta, Globals::Structs::ViewportStruct::Type & aViewport) + { + return Status::Success; + } + + virtual CHIP_ERROR PersistentAttributesLoadedCallback() { return CHIP_NO_ERROR; } + + CHIP_ERROR LoadMPTZPresets(std::vector & mptzPresetHelpers) { return CHIP_NO_ERROR; } + CHIP_ERROR LoadDPTZStreams(std::vector & dptzStreams) { return CHIP_NO_ERROR; } +}; + +struct TestCameraAvSettingsUserLevelManagementCluster : public ::testing::Test +{ + static void SetUpTestSuite() { ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR); } + static void TearDownTestSuite() { chip::Platform::MemoryShutdown(); } + + TestCameraAvSettingsUserLevelManagementCluster() : + mServer(kTestEndpointId, + chip::BitFlags(Feature::kDigitalPTZ, Feature::kMechanicalPan, Feature::kMechanicalTilt, + Feature::kMechanicalZoom, Feature::kMechanicalPresets), + testMaxPresets), + mClusterTester(mServer) + {} + + void SetUp() override + { + VerifyOrDie(mPersistenceProvider.Init(&mClusterTester.GetServerClusterContext().storage) == CHIP_NO_ERROR); + SetAttributePersistenceProvider(&mPersistenceProvider); + mServer.SetDelegate(&mMockDelegate); + EXPECT_EQ(mServer.Startup(mClusterTester.GetServerClusterContext()), CHIP_NO_ERROR); + } + + void TearDown() override + { + SetAttributePersistenceProvider(nullptr); + mServer.Shutdown(ClusterShutdownType::kClusterShutdown); + } + + MockCameraAvSettingsUserLevelManagementDelegate mMockDelegate; + CameraAvSettingsUserLevelManagementCluster mServer; + ClusterTester mClusterTester; + DefaultAttributePersistenceProvider mPersistenceProvider; +}; + +TEST_F(TestCameraAvSettingsUserLevelManagementCluster, TestAttributes) +{ + ASSERT_TRUE(IsAttributesListEqualTo(mServer, + { + Attributes::MPTZPosition::kMetadataEntry, + Attributes::MaxPresets::kMetadataEntry, + Attributes::MPTZPresets::kMetadataEntry, + Attributes::DPTZStreams::kMetadataEntry, + Attributes::ZoomMax::kMetadataEntry, + Attributes::TiltMin::kMetadataEntry, + Attributes::TiltMax::kMetadataEntry, + Attributes::PanMin::kMetadataEntry, + Attributes::PanMax::kMetadataEntry, + Attributes::MovementState::kMetadataEntry, + })); +} + +TEST_F(TestCameraAvSettingsUserLevelManagementCluster, TestCommands) +{ + ASSERT_TRUE(IsAcceptedCommandsListEqualTo(mServer, + { + Commands::MPTZSetPosition::kMetadataEntry, + Commands::MPTZRelativeMove::kMetadataEntry, + Commands::MPTZMoveToPreset::kMetadataEntry, + Commands::MPTZSavePreset::kMetadataEntry, + Commands::MPTZRemovePreset::kMetadataEntry, + Commands::DPTZSetViewport::kMetadataEntry, + Commands::DPTZRelativeMove::kMetadataEntry, + })); +} + +TEST_F(TestCameraAvSettingsUserLevelManagementCluster, ReadAllAttributesWithClusterTesterTest) +{ + uint8_t maxPresets = 0; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MaxPresets::Id, maxPresets), CHIP_NO_ERROR); + ASSERT_EQ(testMaxPresets, maxPresets); + + uint8_t zoomMax = 0; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::ZoomMax::Id, zoomMax), CHIP_NO_ERROR); + ASSERT_LE(zoomMax, kZoomMaxMaxValue); + ASSERT_GE(zoomMax, kZoomMaxMinValue); + + int16_t tiltMin = 0; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::TiltMin::Id, tiltMin), CHIP_NO_ERROR); + ASSERT_LE(tiltMin, kTiltMinMaxValue); + ASSERT_GE(tiltMin, kTiltMinMinValue); + + int16_t tiltMax = 0; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::TiltMax::Id, tiltMax), CHIP_NO_ERROR); + ASSERT_LE(tiltMax, kTiltMaxMaxValue); + ASSERT_GE(tiltMax, kTiltMaxMinValue); + + int16_t panMin = 0; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::PanMin::Id, panMin), CHIP_NO_ERROR); + ASSERT_LE(panMin, kPanMinMaxValue); + ASSERT_GE(panMin, kPanMinMinValue); + + int16_t panMax = 0; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::PanMax::Id, panMax), CHIP_NO_ERROR); + ASSERT_LE(panMax, kPanMaxMaxValue); + ASSERT_GE(panMax, kPanMaxMinValue); + + Structs::MPTZStruct::DecodableType mptzPosition; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MPTZPosition::Id, mptzPosition), CHIP_NO_ERROR); + ASSERT_LE(mptzPosition.pan.Value(), panMax); + ASSERT_GE(mptzPosition.pan.Value(), panMin); + ASSERT_LE(mptzPosition.tilt.Value(), tiltMax); + ASSERT_GE(mptzPosition.tilt.Value(), tiltMin); + ASSERT_LE(mptzPosition.zoom.Value(), zoomMax); + ASSERT_GE(mptzPosition.zoom.Value(), kZoomMinValue); + + // No commands have been invoked, we should be Idle + PhysicalMovementEnum movementState; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MovementState::Id, movementState), CHIP_NO_ERROR); + ASSERT_EQ(movementState, PhysicalMovementEnum::kIdle); + + // On startup there should be no presets and no streams set + Attributes::MPTZPresets::TypeInfo::DecodableType mptzPresets; + size_t presetsSize; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MPTZPresets::Id, mptzPresets), CHIP_NO_ERROR); + TEMPORARY_RETURN_IGNORED mptzPresets.ComputeSize(&presetsSize); + ASSERT_EQ(presetsSize, static_cast(0)); + + Attributes::DPTZStreams::TypeInfo::DecodableType dptzStreams; + size_t streamsSize; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::DPTZStreams::Id, dptzStreams), CHIP_NO_ERROR); + TEMPORARY_RETURN_IGNORED mptzPresets.ComputeSize(&streamsSize); + ASSERT_EQ(streamsSize, static_cast(0)); +} + +TEST_F(TestCameraAvSettingsUserLevelManagementCluster, ExecuteMPTZSetPositionCommandTest) +{ + Testing::MockCommandHandler commandHandler; + commandHandler.SetFabricIndex(1); + ConcreteCommandPath kCommandPath{ 1, Clusters::CameraAvSettingsUserLevelManagement::Id, Commands::MPTZSetPosition::Id }; + Commands::MPTZSetPosition::DecodableType commandData; + + // Set new values of pan, tilt, zoom to be the mid-point of their allowed ranges + int16_t testPan = (kPanMaxMaxValue - kPanMinMinValue) / 2; + int16_t testTilt = (kTiltMaxMaxValue - kTiltMinMinValue) / 2; + uint8_t testZoom = (kZoomMaxMaxValue - kZoomMinValue) / 2; + + commandData.pan.Emplace(testPan); + commandData.tilt.Emplace(testTilt); + commandData.zoom.Emplace(testZoom); + + auto response = mServer.GetLogic().HandleMPTZSetPosition(commandHandler, kCommandPath, commandData); + + // The response should contain an ActionReturnStatus. We're explicitly checking as clang complains on use + // of Optional without checking if a form ASSERT_TRUE(response.has_value()) is used. + if (response.has_value()) + { + ASSERT_TRUE(response.value().IsSuccess()); + } + else + { + // Fail the test case + FAIL(); + } + + // Server should think the device is moving until the app callsback, verify that the MovementState is correct + PhysicalMovementEnum movementState; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MovementState::Id, movementState), CHIP_NO_ERROR); + ASSERT_EQ(movementState, PhysicalMovementEnum::kMoving); + + // Fake the delegate callback + mServer.GetLogic().OnPhysicalMovementComplete(Status::Success); + + // Verify that the values in the attribute are the values set by the command + Structs::MPTZStruct::DecodableType mptzPosition; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MPTZPosition::Id, mptzPosition), CHIP_NO_ERROR); + ASSERT_EQ(mptzPosition.pan.Value(), testPan); + ASSERT_EQ(mptzPosition.tilt.Value(), testTilt); + ASSERT_EQ(mptzPosition.zoom.Value(), testZoom); + + // Verify that the MovementState has returned to Idle + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MovementState::Id, movementState), CHIP_NO_ERROR); + ASSERT_EQ(movementState, PhysicalMovementEnum::kIdle); +} + +TEST_F(TestCameraAvSettingsUserLevelManagementCluster, ExecuteMPTZRelativeMoveCommandTest) +{ + Testing::MockCommandHandler commandHandler; + commandHandler.SetFabricIndex(1); + ConcreteCommandPath kCommandPath{ 1, Clusters::CameraAvSettingsUserLevelManagement::Id, Commands::MPTZRelativeMove::Id }; + Commands::MPTZRelativeMove::DecodableType commandData; + + // Get the current values of MPTZ, these should be the server defaults (0,0,1) + Structs::MPTZStruct::DecodableType startingMptzPosition; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MPTZPosition::Id, startingMptzPosition), CHIP_NO_ERROR); + + // Set relative values of pan, tilt, zoom to be the +10 + int16_t relativePan = 10; + int16_t relativeTilt = 10; + int8_t relativeZoom = 10; + + commandData.panDelta.Emplace(relativePan); + commandData.tiltDelta.Emplace(relativeTilt); + commandData.zoomDelta.Emplace(relativeZoom); + + auto response = mServer.GetLogic().HandleMPTZRelativeMove(commandHandler, kCommandPath, commandData); + + // The response should contain an ActionReturnStatus + if (response.has_value()) + { + ASSERT_TRUE(response.value().IsSuccess()); + } + else + { + FAIL(); + } + + // Server should think the device is moving until the app callsback, verify that the MovementState is correct + PhysicalMovementEnum movementState; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MovementState::Id, movementState), CHIP_NO_ERROR); + ASSERT_EQ(movementState, PhysicalMovementEnum::kMoving); + + // Fake the delegate callback + mServer.GetLogic().OnPhysicalMovementComplete(Status::Success); + + // Verify that the values in the attribute are the values set by the command + Structs::MPTZStruct::DecodableType movedMptzPosition; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MPTZPosition::Id, movedMptzPosition), CHIP_NO_ERROR); + ASSERT_EQ(movedMptzPosition.pan.Value(), startingMptzPosition.pan.Value() + relativePan); + ASSERT_EQ(movedMptzPosition.tilt.Value(), startingMptzPosition.tilt.Value() + relativeTilt); + ASSERT_EQ(movedMptzPosition.zoom.Value(), startingMptzPosition.zoom.Value() + relativeZoom); + + // Verify that the MovementState has returned to Idle + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MovementState::Id, movementState), CHIP_NO_ERROR); + ASSERT_EQ(movementState, PhysicalMovementEnum::kIdle); +} + +TEST_F(TestCameraAvSettingsUserLevelManagementCluster, ExecuteMPTZSavePresetCommandTest) +{ + Testing::MockCommandHandler commandHandler; + commandHandler.SetFabricIndex(1); + ConcreteCommandPath kCommandPath{ 1, Clusters::CameraAvSettingsUserLevelManagement::Id, Commands::MPTZSavePreset::Id }; + Commands::MPTZSavePreset::DecodableType commandData; + + // Presets attribute should be empty + Attributes::MPTZPresets::TypeInfo::DecodableType mptzPresets; + size_t presetsSize; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MPTZPresets::Id, mptzPresets), CHIP_NO_ERROR); + TEMPORARY_RETURN_IGNORED mptzPresets.ComputeSize(&presetsSize); + ASSERT_EQ(presetsSize, static_cast(0)); + + // Get the current values of MPTZ, these should be the server defaults (0,0,1) + Structs::MPTZStruct::DecodableType currentMptzPosition; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MPTZPosition::Id, currentMptzPosition), CHIP_NO_ERROR); + + // Save the current values as a preset + chip::CharSpan presetName("DefaultPreset"_span); + uint8_t presetIDAsInt = 2; + + commandData.name = presetName; + commandData.presetID.Emplace(presetIDAsInt); + auto response = mServer.GetLogic().HandleMPTZSavePreset(commandHandler, kCommandPath, commandData); + + // The response should contain an ActionReturnStatus + if (response.has_value()) + { + ASSERT_TRUE(response.value().IsSuccess()); + } + else + { + FAIL(); + } + + // Verify that there is a single saved preset. The values match those of the current MPTZ Position + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MPTZPresets::Id, mptzPresets), CHIP_NO_ERROR); + TEMPORARY_RETURN_IGNORED mptzPresets.ComputeSize(&presetsSize); + ASSERT_EQ(presetsSize, static_cast(1)); + + auto it = mptzPresets.begin(); + while (it.Next()) + { + ASSERT_EQ(*it.GetValue().name.data(), *presetName.data()); + ASSERT_EQ(it.GetValue().presetID, presetIDAsInt); + } + + // As we provided a Preset ID of 2, the next Preset to use should still be 1 + ASSERT_EQ(mServer.GetLogic().mCurrentPresetID, 1); +} + +TEST_F(TestCameraAvSettingsUserLevelManagementCluster, ExecuteMPTZMoveToPresetCommandTest) +{ + Testing::MockCommandHandler commandHandler; + commandHandler.SetFabricIndex(1); + ConcreteCommandPath kCommandPathMove{ 1, Clusters::CameraAvSettingsUserLevelManagement::Id, Commands::MPTZMoveToPreset::Id }; + Commands::MPTZMoveToPreset::DecodableType moveToPresetCommandData; + ConcreteCommandPath kCommandPathMPTZSet{ 1, Clusters::CameraAvSettingsUserLevelManagement::Id, Commands::MPTZSetPosition::Id }; + Commands::MPTZSetPosition::DecodableType mptzSetCommandData; + ConcreteCommandPath kCommandPathMPTZSave{ 1, Clusters::CameraAvSettingsUserLevelManagement::Id, Commands::MPTZSavePreset::Id }; + Commands::MPTZSavePreset::DecodableType savePresetCommandData; + + // Presets attribute should be empty + Attributes::MPTZPresets::TypeInfo::DecodableType mptzPresets; + size_t presetsSize; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MPTZPresets::Id, mptzPresets), CHIP_NO_ERROR); + TEMPORARY_RETURN_IGNORED mptzPresets.ComputeSize(&presetsSize); + ASSERT_EQ(presetsSize, static_cast(0)); + + // Try to move to a preset, this should fail with NOT FOUND + uint8_t presetIDAsInt = 2; + + moveToPresetCommandData.presetID = presetIDAsInt; + auto moveResponse = mServer.GetLogic().HandleMPTZMoveToPreset(commandHandler, kCommandPathMove, moveToPresetCommandData); + + // The response should contain an ActionReturnStatus + if (moveResponse.has_value()) + { + ASSERT_EQ(moveResponse.value().GetStatusCode().GetStatus(), Status::NotFound); + } + else + { + FAIL(); + } + + // Save the current values of MPTZ as a preset + chip::CharSpan presetName("DefaultPreset"_span); + savePresetCommandData.name = presetName; + savePresetCommandData.presetID.Emplace(presetIDAsInt); + auto saveResponse = mServer.GetLogic().HandleMPTZSavePreset(commandHandler, kCommandPathMPTZSave, savePresetCommandData); + + // The response should contain an ActionReturnStatus + if (saveResponse.has_value()) + { + ASSERT_TRUE(saveResponse.value().IsSuccess()); + } + else + { + FAIL(); + } + + // Save the stored preset settings; we know there is only one entry + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MPTZPresets::Id, mptzPresets), CHIP_NO_ERROR); + + int16_t presetPan; + int16_t presetTilt; + uint8_t presetZoom; + + auto it = mptzPresets.begin(); + while (it.Next()) + { + presetPan = it.GetValue().settings.pan.Value(); + presetTilt = it.GetValue().settings.tilt.Value(); + presetZoom = it.GetValue().settings.zoom.Value(); + } + + // Set the MPTZ position to be the mid-points of the allowed ranges + int16_t testPan = (kPanMaxMaxValue - kPanMinMinValue) / 2; + int16_t testTilt = (kTiltMaxMaxValue - kTiltMinMinValue) / 2; + uint8_t testZoom = (kZoomMaxMaxValue - kZoomMinValue) / 2; + + mptzSetCommandData.pan.Emplace(testPan); + mptzSetCommandData.tilt.Emplace(testTilt); + mptzSetCommandData.zoom.Emplace(testZoom); + + auto setResponse = mServer.GetLogic().HandleMPTZSetPosition(commandHandler, kCommandPathMPTZSet, mptzSetCommandData); + + // The response should contain an ActionReturnStatus + if (setResponse.has_value()) + { + ASSERT_TRUE(setResponse.value().IsSuccess()); + } + else + { + FAIL(); + } + + // Fake the delegate callback + mServer.GetLogic().OnPhysicalMovementComplete(Status::Success); + + // Verify that the values in the attribute are the values set by the command + Structs::MPTZStruct::DecodableType mptzPosition; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MPTZPosition::Id, mptzPosition), CHIP_NO_ERROR); + ASSERT_EQ(mptzPosition.pan.Value(), testPan); + ASSERT_EQ(mptzPosition.tilt.Value(), testTilt); + ASSERT_EQ(mptzPosition.zoom.Value(), testZoom); + + // Move to the preset + moveResponse = mServer.GetLogic().HandleMPTZMoveToPreset(commandHandler, kCommandPathMove, moveToPresetCommandData); + + // The response should contain an ActionReturnStatus + if (moveResponse.has_value()) + { + ASSERT_TRUE(moveResponse.value().IsSuccess()); + } + else + { + FAIL(); + } + + // Ensure we're "moving" + PhysicalMovementEnum movementState; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MovementState::Id, movementState), CHIP_NO_ERROR); + ASSERT_EQ(movementState, PhysicalMovementEnum::kMoving); + + // Fake the callback + mServer.GetLogic().OnPhysicalMovementComplete(Status::Success); + + // Ensure we've reverted to idle + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MovementState::Id, movementState), CHIP_NO_ERROR); + ASSERT_EQ(movementState, PhysicalMovementEnum::kIdle); + + // Ensure the values in MPTZPosition are those of the Preset + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MPTZPosition::Id, mptzPosition), CHIP_NO_ERROR); + ASSERT_EQ(mptzPosition.pan.Value(), presetPan); + ASSERT_EQ(mptzPosition.tilt.Value(), presetTilt); + ASSERT_EQ(mptzPosition.zoom.Value(), presetZoom); +} + +TEST_F(TestCameraAvSettingsUserLevelManagementCluster, ExecuteMPTZRemovePresetCommandTest) +{ + Testing::MockCommandHandler commandHandler; + commandHandler.SetFabricIndex(1); + ConcreteCommandPath kCommandPathRemove{ 1, Clusters::CameraAvSettingsUserLevelManagement::Id, Commands::MPTZRemovePreset::Id }; + Commands::MPTZRemovePreset::DecodableType removePresetCommandData; + ConcreteCommandPath kCommandPathMPTZSave{ 1, Clusters::CameraAvSettingsUserLevelManagement::Id, Commands::MPTZSavePreset::Id }; + Commands::MPTZSavePreset::DecodableType savePresetCommandData; + + // Presets attribute should be empty + Attributes::MPTZPresets::TypeInfo::DecodableType mptzPresets; + size_t presetsSize; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MPTZPresets::Id, mptzPresets), CHIP_NO_ERROR); + TEMPORARY_RETURN_IGNORED mptzPresets.ComputeSize(&presetsSize); + ASSERT_EQ(presetsSize, static_cast(0)); + + // Try to remove a preset, this should fail with NOT FOUND + uint8_t presetIDAsInt = 2; + + removePresetCommandData.presetID = presetIDAsInt; + auto removeResponse = mServer.GetLogic().HandleMPTZRemovePreset(commandHandler, kCommandPathRemove, removePresetCommandData); + + // The response should contain an ActionReturnStatus + if (removeResponse.has_value()) + { + ASSERT_EQ(removeResponse.value().GetStatusCode().GetStatus(), Status::NotFound); + } + else + { + FAIL(); + } + + // Save the current values of MPTZ as a preset + chip::CharSpan presetName("DefaultPreset"_span); + savePresetCommandData.name = presetName; + savePresetCommandData.presetID.Emplace(presetIDAsInt); + auto saveResponse = mServer.GetLogic().HandleMPTZSavePreset(commandHandler, kCommandPathMPTZSave, savePresetCommandData); + + // The response should contain an ActionReturnStatus + if (saveResponse.has_value()) + { + ASSERT_TRUE(saveResponse.value().IsSuccess()); + } + else + { + FAIL(); + } + + // Verify that there is a single saved preset. The values match those of the current MPTZ Position + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MPTZPresets::Id, mptzPresets), CHIP_NO_ERROR); + TEMPORARY_RETURN_IGNORED mptzPresets.ComputeSize(&presetsSize); + ASSERT_EQ(presetsSize, static_cast(1)); + + // Try to remove again, verify success + removePresetCommandData.presetID = presetIDAsInt; + removeResponse = mServer.GetLogic().HandleMPTZRemovePreset(commandHandler, kCommandPathRemove, removePresetCommandData); + + // The response should contain an ActionReturnStatus + if (removeResponse.has_value()) + { + ASSERT_TRUE(removeResponse.value().IsSuccess()); + } + else + { + FAIL(); + } + + // Verify that there are no saved presets. The values match those of the current MPTZ Position + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::MPTZPresets::Id, mptzPresets), CHIP_NO_ERROR); + TEMPORARY_RETURN_IGNORED mptzPresets.ComputeSize(&presetsSize); + ASSERT_EQ(presetsSize, static_cast(0)); +} + +TEST_F(TestCameraAvSettingsUserLevelManagementCluster, ExecuteDPTZSetViewportCommandTest) +{ + Testing::MockCommandHandler commandHandler; + commandHandler.SetFabricIndex(1); + ConcreteCommandPath kCommandPath{ 1, Clusters::CameraAvSettingsUserLevelManagement::Id, Commands::DPTZSetViewport::Id }; + Commands::DPTZSetViewport::DecodableType commandData; + + // DPTZStreams attribute starts empty + Attributes::DPTZStreams::TypeInfo::DecodableType dptzStreams; + size_t streamsSize; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::DPTZStreams::Id, dptzStreams), CHIP_NO_ERROR); + TEMPORARY_RETURN_IGNORED dptzStreams.ComputeSize(&streamsSize); + ASSERT_EQ(streamsSize, static_cast(0)); + + // Try to set the viewport when no streams exist, this should fail with NOT FOUND + uint8_t videoStreamID = 1; + Globals::Structs::ViewportStruct::Type viewPort = { 0, 0, 1920, 1080 }; + commandData.videoStreamID = videoStreamID; + commandData.viewport = viewPort; + auto response = mServer.GetLogic().HandleDPTZSetViewport(commandHandler, kCommandPath, commandData); + + // The response should contain an ActionReturnStatus + if (response.has_value()) + { + ASSERT_EQ(response.value().GetStatusCode().GetStatus(), Status::NotFound); + } + else + { + FAIL(); + } + + // Allocate a video stream + mServer.GetLogic().AddMoveCapableVideoStream(videoStreamID, viewPort); + + // Verify that DPTZStreams is now populated correctly + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::DPTZStreams::Id, dptzStreams), CHIP_NO_ERROR); + TEMPORARY_RETURN_IGNORED dptzStreams.ComputeSize(&streamsSize); + ASSERT_EQ(streamsSize, static_cast(1)); + + auto it = dptzStreams.begin(); + while (it.Next()) + { + ASSERT_EQ(it.GetValue().videoStreamID, videoStreamID); + ASSERT_EQ(it.GetValue().viewport.x1, viewPort.x1); + ASSERT_EQ(it.GetValue().viewport.x2, viewPort.x2); + ASSERT_EQ(it.GetValue().viewport.y1, viewPort.y1); + ASSERT_EQ(it.GetValue().viewport.y2, viewPort.y2); + } + + // Try to set the viewport + Globals::Structs::ViewportStruct::Type newViewPort = { 0, 0, 1280, 720 }; + commandData.viewport = newViewPort; + + response = mServer.GetLogic().HandleDPTZSetViewport(commandHandler, kCommandPath, commandData); + + // The response should contain an ActionReturnStatus + if (response.has_value()) + { + ASSERT_TRUE(response.value().IsSuccess()); + } + else + { + FAIL(); + } + + // Verify this new viewport is in DPTZStreams + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::DPTZStreams::Id, dptzStreams), CHIP_NO_ERROR); + + it = dptzStreams.begin(); + while (it.Next()) + { + ASSERT_EQ(it.GetValue().videoStreamID, videoStreamID); + ASSERT_EQ(it.GetValue().viewport.x1, newViewPort.x1); + ASSERT_EQ(it.GetValue().viewport.x2, newViewPort.x2); + ASSERT_EQ(it.GetValue().viewport.y1, newViewPort.y1); + ASSERT_EQ(it.GetValue().viewport.y2, newViewPort.y2); + } +} + +TEST_F(TestCameraAvSettingsUserLevelManagementCluster, ExecuteDPTZRelativeMoveCommandTest) +{ + Testing::MockCommandHandler commandHandler; + commandHandler.SetFabricIndex(1); + ConcreteCommandPath kCommandPath{ 1, Clusters::CameraAvSettingsUserLevelManagement::Id, Commands::DPTZRelativeMove::Id }; + Commands::DPTZRelativeMove::DecodableType commandData; + + // DPTZStreams attribute starts empty + Attributes::DPTZStreams::TypeInfo::DecodableType dptzStreams; + size_t streamsSize; + ASSERT_EQ(mClusterTester.ReadAttribute(Attributes::DPTZStreams::Id, dptzStreams), CHIP_NO_ERROR); + TEMPORARY_RETURN_IGNORED dptzStreams.ComputeSize(&streamsSize); + ASSERT_EQ(streamsSize, static_cast(0)); + + // Try to move the viewport when no streams exist, this should fail with NOT FOUND + uint8_t videoStreamID = 1; + int16_t deltaX = 100; + int16_t deltaY = 100; + int8_t zoomDelta = -50; + int8_t zoomDeltaFail = 120; + + commandData.videoStreamID = videoStreamID; + commandData.deltaX.Emplace(deltaX); + commandData.deltaY.Emplace(deltaY); + commandData.zoomDelta.Emplace(zoomDelta); + + auto response = mServer.GetLogic().HandleDPTZRelativeMove(commandHandler, kCommandPath, commandData); + + // The response should contain an ActionReturnStatus + if (response.has_value()) + { + ASSERT_EQ(response.value().GetStatusCode().GetStatus(), Status::NotFound); + } + else + { + FAIL(); + } + + // Allocate a video stream + Globals::Structs::ViewportStruct::Type viewPort = { 0, 0, 1920, 1080 }; + mServer.GetLogic().AddMoveCapableVideoStream(videoStreamID, viewPort); + + // Try to move the viewport + response = mServer.GetLogic().HandleDPTZRelativeMove(commandHandler, kCommandPath, commandData); + + // The response should contain an ActionReturnStatus + if (response.has_value()) + { + ASSERT_TRUE(response.value().IsSuccess()); + } + else + { + FAIL(); + } + + // The mock delegate has no means to verify the proposed change as the values needed are part of CameraAVStreams, + // as such, the command above should just be successful as long as the delta is in range. + + // Try to move the viewport with an out of range zoomDelta + commandData.zoomDelta.Emplace(zoomDeltaFail); + response = mServer.GetLogic().HandleDPTZRelativeMove(commandHandler, kCommandPath, commandData); + + if (response.has_value()) + { + ASSERT_EQ(response.value().GetStatusCode().GetStatus(), Status::ConstraintError); + } + else + { + FAIL(); + } +} + +} // namespace diff --git a/src/app/clusters/camera-av-stream-management-server/BUILD.gn b/src/app/clusters/camera-av-stream-management-server/BUILD.gn index 6351cfca81b..18033e6f25b 100644 --- a/src/app/clusters/camera-av-stream-management-server/BUILD.gn +++ b/src/app/clusters/camera-av-stream-management-server/BUILD.gn @@ -11,5 +11,32 @@ # 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. -group("camera-av-stream-management-server") { +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +source_set("camera-av-stream-management-server") { + sources = [ + "CameraAVStreamManagementCluster.cpp", + "CameraAVStreamManagementCluster.h", + ] + + deps = [ + "${chip_root}/src/app/persistence:singleton", + "${chip_root}/src/lib/core", + "${chip_root}/src/lib/support", + ] + + public_deps = [ ":camera-av-stream-management-cluster" ] +} + +source_set("camera-av-stream-management-cluster") { + public_deps = [ + "${chip_root}/src/app:constants", + "${chip_root}/src/app:interaction-model", + "${chip_root}/src/app/data-model-provider", + "${chip_root}/src/app/persistence", + "${chip_root}/src/app/server", + "${chip_root}/src/app/server-cluster", + "${chip_root}/zzz_generated/app-common/clusters/CameraAvStreamManagement", + ] } diff --git a/src/app/clusters/camera-av-stream-management-server/camera-av-stream-management-server.cpp b/src/app/clusters/camera-av-stream-management-server/CameraAVStreamManagementCluster.cpp similarity index 63% rename from src/app/clusters/camera-av-stream-management-server/camera-av-stream-management-server.cpp rename to src/app/clusters/camera-av-stream-management-server/CameraAVStreamManagementCluster.cpp index 1f3d9859689..96f80f4fa63 100644 --- a/src/app/clusters/camera-av-stream-management-server/camera-av-stream-management-server.cpp +++ b/src/app/clusters/camera-av-stream-management-server/CameraAVStreamManagementCluster.cpp @@ -20,12 +20,15 @@ #include #include #include -#include +#include #include #include #include -#include +#include #include +#include +#include +#include #include #include #include @@ -49,8 +52,8 @@ namespace app { namespace Clusters { namespace CameraAvStreamManagement { -CameraAVStreamMgmtServer::CameraAVStreamMgmtServer( - CameraAVStreamMgmtDelegate & aDelegate, EndpointId aEndpointId, const BitFlags aFeatures, +CameraAVStreamManagementCluster::CameraAVStreamManagementCluster( + CameraAVStreamManagementDelegate & aDelegate, EndpointId aEndpointId, const BitFlags aFeatures, const BitFlags aOptionalAttrs, uint8_t aMaxConcurrentEncoders, uint32_t aMaxEncodedPixelRate, const VideoSensorParamsStruct & aVideoSensorParams, bool aNightVisionUsesInfrared, const VideoResolutionStruct & aMinViewPortRes, @@ -60,39 +63,34 @@ CameraAVStreamMgmtServer::CameraAVStreamMgmtServer( const std::vector & aSnapshotCapabilities, uint32_t aMaxNetworkBandwidth, const std::vector & aSupportedStreamUsages, const std::vector & aStreamUsagePriorities) : - CommandHandlerInterface(MakeOptional(aEndpointId), CameraAvStreamManagement::Id), - AttributeAccessInterface(MakeOptional(aEndpointId), CameraAvStreamManagement::Id), mDelegate(aDelegate), - mEndpointId(aEndpointId), mFeatures(aFeatures), mOptionalAttrs(aOptionalAttrs), mMaxConcurrentEncoders(aMaxConcurrentEncoders), - mMaxEncodedPixelRate(aMaxEncodedPixelRate), mVideoSensorParams(aVideoSensorParams), - mNightVisionUsesInfrared(aNightVisionUsesInfrared), mMinViewPortResolution(aMinViewPortRes), - mRateDistortionTradeOffPointsList(aRateDistortionTradeOffPoints), mMaxContentBufferSize(aMaxContentBufferSize), - mMicrophoneCapabilities(aMicrophoneCapabilities), mSpeakerCapabilities(aSpeakerCapabilities), - mTwoWayTalkSupport(aTwoWayTalkSupport), mSnapshotCapabilitiesList(aSnapshotCapabilities), - mMaxNetworkBandwidth(aMaxNetworkBandwidth), mSupportedStreamUsages(aSupportedStreamUsages), - mStreamUsagePriorities(aStreamUsagePriorities) + DefaultServerCluster({ aEndpointId, CameraAvStreamManagement::Id }), + mDelegate(aDelegate), mEnabledFeatures(aFeatures), mOptionalAttrs(aOptionalAttrs), + mMaxConcurrentEncoders(aMaxConcurrentEncoders), mMaxEncodedPixelRate(aMaxEncodedPixelRate), + mVideoSensorParams(aVideoSensorParams), mNightVisionUsesInfrared(aNightVisionUsesInfrared), + mMinViewPortResolution(aMinViewPortRes), mRateDistortionTradeOffPointsList(aRateDistortionTradeOffPoints), + mMaxContentBufferSize(aMaxContentBufferSize), mMicrophoneCapabilities(aMicrophoneCapabilities), + mSpeakerCapabilities(aSpeakerCapabilities), mTwoWayTalkSupport(aTwoWayTalkSupport), + mSnapshotCapabilitiesList(aSnapshotCapabilities), mMaxNetworkBandwidth(aMaxNetworkBandwidth), + mSupportedStreamUsages(aSupportedStreamUsages), mStreamUsagePriorities(aStreamUsagePriorities) { - mDelegate.SetCameraAVStreamMgmtServer(this); + mDelegate.SetCameraAVStreamManagementCluster(this); } -CameraAVStreamMgmtServer::~CameraAVStreamMgmtServer() +CameraAVStreamManagementCluster::~CameraAVStreamManagementCluster() { - // Explicitly set the CameraAVStreamMgmtServer pointer in the Delegate to + // Explicitly set the CameraAVStreamManagementCluster pointer in the Delegate to // null. - mDelegate.SetCameraAVStreamMgmtServer(nullptr); - - // Unregister command handler and attribute access interfaces - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); - AttributeAccessInterfaceRegistry::Instance().Unregister(this); + mDelegate.SetCameraAVStreamManagementCluster(nullptr); } -CHIP_ERROR CameraAVStreamMgmtServer::Init() +CHIP_ERROR CameraAVStreamManagementCluster::Init() { // Constraint checks for RateDistortionTardeOffPoints vector for (const auto & rateDistortionTradeOffPoints : mRateDistortionTradeOffPointsList) { VerifyOrReturnError( rateDistortionTradeOffPoints.minBitRate >= 1, CHIP_ERROR_INVALID_ARGUMENT, - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: RateDistortionTradeOffPoints configuration error", mEndpointId)); + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: RateDistortionTradeOffPoints configuration error", mPath.mEndpointId)); } // At least one of Video, Audio or Snapshot needs to be supported. @@ -101,7 +99,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Init() ChipLogError( Zcl, "CameraAVStreamMgmt[ep=%d]: Feature configuration error. At least one of Audio, Video, or Snapshot feature required", - mEndpointId)); + mPath.mEndpointId)); // Verify cross-feature dependencies if (HasFeature(Feature::kImageControl) || HasFeature(Feature::kWatermark) || HasFeature(Feature::kOnScreenDisplay) || @@ -111,7 +109,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Init() ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Feature configuration error. if ImageControl, Watermark, " "OnScreenDisplay or HighDynamicRange, then Video or Snapshot feature required", - mEndpointId)); + mPath.mEndpointId)); } if (HasFeature(Feature::kSpeaker)) @@ -120,7 +118,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Init() ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Feature configuration error. if Speaker is enabled, then " "Audio feature required", - mEndpointId)); + mPath.mEndpointId)); } // Ensure Optional attribute bits have been correctly passed and have supporting feature bits set. @@ -131,7 +129,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Init() ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Feature configuration error. if NIghtVisionIllum is enabled, then " "NightVision feature required", - mEndpointId)); + mPath.mEndpointId)); } if (SupportsOptAttr(OptionalAttribute::kMicrophoneAGCEnabled)) @@ -140,7 +138,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Init() HasFeature(Feature::kAudio), CHIP_ERROR_INVALID_ARGUMENT, ChipLogError( Zcl, "CameraAVStreamMgmt[ep=%d]: Feature configuration error. if MicrophoneAGCEnabled, then Audio feature required", - mEndpointId)); + mPath.mEndpointId)); } // If any of the image control attributes are present, we must have the feature. @@ -153,7 +151,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Init() ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Feature configuration error. if ImageFlip or Rotation enabled, then " "ImageControl feature required", - mEndpointId)); + mPath.mEndpointId)); } if (HasFeature(Feature::kImageControl)) @@ -165,33 +163,31 @@ CHIP_ERROR CameraAVStreamMgmtServer::Init() ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Feature configuration error. if ImageControl feature supported, then " "at least one of the ImageFlip or Rotation attributes shall be supported", - mEndpointId)); + mPath.mEndpointId)); } LoadPersistentAttributes(); - VerifyOrReturnError(AttributeAccessInterfaceRegistry::Instance().Register(this), CHIP_ERROR_INTERNAL); - ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(this)); return CHIP_NO_ERROR; } -bool CameraAVStreamMgmtServer::HasFeature(Feature feature) const +bool CameraAVStreamManagementCluster::HasFeature(Feature feature) const { - return mFeatures.Has(feature); + return mEnabledFeatures.Has(feature); } -bool CameraAVStreamMgmtServer::SupportsOptAttr(OptionalAttribute aOptionalAttr) const +bool CameraAVStreamManagementCluster::SupportsOptAttr(OptionalAttribute aOptionalAttr) const { return mOptionalAttrs.Has(aOptionalAttr); } -bool CameraAVStreamMgmtServer::IsLocalVideoRecordingEnabled() const +bool CameraAVStreamManagementCluster::IsLocalVideoRecordingEnabled() const { return mLocalVideoRecordingEnabled; } CHIP_ERROR -CameraAVStreamMgmtServer::ReadAndEncodeRateDistortionTradeOffPoints(const AttributeValueEncoder::ListEncodeHelper & encoder) +CameraAVStreamManagementCluster::ReadAndEncodeRateDistortionTradeOffPoints(const AttributeValueEncoder::ListEncodeHelper & encoder) { for (const auto & rateDistortionTradeOffPoints : mRateDistortionTradeOffPointsList) { @@ -201,7 +197,8 @@ CameraAVStreamMgmtServer::ReadAndEncodeRateDistortionTradeOffPoints(const Attrib return CHIP_NO_ERROR; } -CHIP_ERROR CameraAVStreamMgmtServer::ReadAndEncodeSnapshotCapabilities(const AttributeValueEncoder::ListEncodeHelper & encoder) +CHIP_ERROR +CameraAVStreamManagementCluster::ReadAndEncodeSnapshotCapabilities(const AttributeValueEncoder::ListEncodeHelper & encoder) { for (const auto & snapshotCapabilities : mSnapshotCapabilitiesList) { @@ -211,7 +208,8 @@ CHIP_ERROR CameraAVStreamMgmtServer::ReadAndEncodeSnapshotCapabilities(const Att return CHIP_NO_ERROR; } -CHIP_ERROR CameraAVStreamMgmtServer::ReadAndEncodeSupportedStreamUsages(const AttributeValueEncoder::ListEncodeHelper & encoder) +CHIP_ERROR +CameraAVStreamManagementCluster::ReadAndEncodeSupportedStreamUsages(const AttributeValueEncoder::ListEncodeHelper & encoder) { for (const auto & supportedStreamUsage : mSupportedStreamUsages) { @@ -221,7 +219,8 @@ CHIP_ERROR CameraAVStreamMgmtServer::ReadAndEncodeSupportedStreamUsages(const At return CHIP_NO_ERROR; } -CHIP_ERROR CameraAVStreamMgmtServer::ReadAndEncodeAllocatedVideoStreams(const AttributeValueEncoder::ListEncodeHelper & encoder) +CHIP_ERROR +CameraAVStreamManagementCluster::ReadAndEncodeAllocatedVideoStreams(const AttributeValueEncoder::ListEncodeHelper & encoder) { CHIP_FAULT_INJECT(chip::FaultInjection::kFault_ClearInMemoryAllocatedVideoStreams, mAllocatedVideoStreams.clear();); CHIP_FAULT_INJECT(chip::FaultInjection::kFault_LoadPersistentCameraAVSMAttributes, LoadPersistentAttributes();); @@ -234,7 +233,8 @@ CHIP_ERROR CameraAVStreamMgmtServer::ReadAndEncodeAllocatedVideoStreams(const At return CHIP_NO_ERROR; } -CHIP_ERROR CameraAVStreamMgmtServer::ReadAndEncodeAllocatedAudioStreams(const AttributeValueEncoder::ListEncodeHelper & encoder) +CHIP_ERROR +CameraAVStreamManagementCluster::ReadAndEncodeAllocatedAudioStreams(const AttributeValueEncoder::ListEncodeHelper & encoder) { CHIP_FAULT_INJECT(chip::FaultInjection::kFault_ClearInMemoryAllocatedAudioStreams, mAllocatedAudioStreams.clear();); CHIP_FAULT_INJECT(chip::FaultInjection::kFault_LoadPersistentCameraAVSMAttributes, LoadPersistentAttributes();); @@ -247,7 +247,8 @@ CHIP_ERROR CameraAVStreamMgmtServer::ReadAndEncodeAllocatedAudioStreams(const At return CHIP_NO_ERROR; } -CHIP_ERROR CameraAVStreamMgmtServer::ReadAndEncodeAllocatedSnapshotStreams(const AttributeValueEncoder::ListEncodeHelper & encoder) +CHIP_ERROR +CameraAVStreamManagementCluster::ReadAndEncodeAllocatedSnapshotStreams(const AttributeValueEncoder::ListEncodeHelper & encoder) { CHIP_FAULT_INJECT(chip::FaultInjection::kFault_ClearInMemoryAllocatedSnapshotStreams, mAllocatedSnapshotStreams.clear();); CHIP_FAULT_INJECT(chip::FaultInjection::kFault_LoadPersistentCameraAVSMAttributes, LoadPersistentAttributes();); @@ -261,7 +262,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::ReadAndEncodeAllocatedSnapshotStreams(const } CHIP_ERROR -CameraAVStreamMgmtServer::ReadAndEncodeStreamUsagePriorities(const AttributeValueEncoder::ListEncodeHelper & encoder) +CameraAVStreamManagementCluster::ReadAndEncodeStreamUsagePriorities(const AttributeValueEncoder::ListEncodeHelper & encoder) { for (const auto & streamUsage : mStreamUsagePriorities) { @@ -271,18 +272,17 @@ CameraAVStreamMgmtServer::ReadAndEncodeStreamUsagePriorities(const AttributeValu return CHIP_NO_ERROR; } -CHIP_ERROR CameraAVStreamMgmtServer::SetStreamUsagePriorities(const std::vector & newPriorities) +CHIP_ERROR CameraAVStreamManagementCluster::SetStreamUsagePriorities(const std::vector & newPriorities) { mStreamUsagePriorities = newPriorities; ReturnErrorOnFailure(StoreStreamUsagePriorities()); - auto path = ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::StreamUsagePriorities::Id); mDelegate.OnAttributeChanged(Attributes::StreamUsagePriorities::Id); - MatterReportingAttributeChangeCallback(path); + NotifyAttributeChanged(Attributes::StreamUsagePriorities::Id); return CHIP_NO_ERROR; } -std::optional CameraAVStreamMgmtServer::GetReusableVideoStreamId(const VideoStreamStruct & requestedArgs) const +std::optional CameraAVStreamManagementCluster::GetReusableVideoStreamId(const VideoStreamStruct & requestedArgs) const { for (const auto & stream : mAllocatedVideoStreams) { @@ -324,15 +324,15 @@ std::optional CameraAVStreamMgmtServer::GetReusableVideoStreamId(const return std::nullopt; } -CHIP_ERROR CameraAVStreamMgmtServer::AddVideoStream(const VideoStreamStruct & videoStream) +CHIP_ERROR CameraAVStreamManagementCluster::AddVideoStream(const VideoStreamStruct & videoStream) { mAllocatedVideoStreams.push_back(videoStream); return PersistAndNotify(); } -CHIP_ERROR CameraAVStreamMgmtServer::UpdateVideoStreamRangeParams(VideoStreamStruct & videoStreamToUpdate, - const VideoStreamStruct & videoStream, bool & wasModified) +CHIP_ERROR CameraAVStreamManagementCluster::UpdateVideoStreamRangeParams(VideoStreamStruct & videoStreamToUpdate, + const VideoStreamStruct & videoStream, bool & wasModified) { // Store original values to detect changes uint16_t origMinFrameRate = videoStreamToUpdate.minFrameRate; @@ -371,7 +371,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::UpdateVideoStreamRangeParams(VideoStreamStr return CHIP_NO_ERROR; } -CHIP_ERROR CameraAVStreamMgmtServer::RemoveVideoStream(uint16_t videoStreamId) +CHIP_ERROR CameraAVStreamManagementCluster::RemoveVideoStream(uint16_t videoStreamId) { mAllocatedVideoStreams.erase( std::remove_if(mAllocatedVideoStreams.begin(), mAllocatedVideoStreams.end(), @@ -381,14 +381,14 @@ CHIP_ERROR CameraAVStreamMgmtServer::RemoveVideoStream(uint16_t videoStreamId) return PersistAndNotify(); } -CHIP_ERROR CameraAVStreamMgmtServer::AddAudioStream(const AudioStreamStruct & audioStream) +CHIP_ERROR CameraAVStreamManagementCluster::AddAudioStream(const AudioStreamStruct & audioStream) { mAllocatedAudioStreams.push_back(audioStream); return PersistAndNotify(); } -CHIP_ERROR CameraAVStreamMgmtServer::RemoveAudioStream(uint16_t audioStreamId) +CHIP_ERROR CameraAVStreamManagementCluster::RemoveAudioStream(uint16_t audioStreamId) { mAllocatedAudioStreams.erase( std::remove_if(mAllocatedAudioStreams.begin(), mAllocatedAudioStreams.end(), @@ -398,8 +398,8 @@ CHIP_ERROR CameraAVStreamMgmtServer::RemoveAudioStream(uint16_t audioStreamId) return PersistAndNotify(); } -std::optional CameraAVStreamMgmtServer::GetReusableSnapshotStreamId( - const CameraAVStreamMgmtDelegate::SnapshotStreamAllocateArgs & requestedArgs) const +std::optional CameraAVStreamManagementCluster::GetReusableSnapshotStreamId( + const CameraAVStreamManagementDelegate::SnapshotStreamAllocateArgs & requestedArgs) const { for (const auto & stream : mAllocatedSnapshotStreams) { @@ -435,15 +435,16 @@ std::optional CameraAVStreamMgmtServer::GetReusableSnapshotStreamId( return std::nullopt; } -CHIP_ERROR CameraAVStreamMgmtServer::AddSnapshotStream(const SnapshotStreamStruct & snapshotStream) +CHIP_ERROR CameraAVStreamManagementCluster::AddSnapshotStream(const SnapshotStreamStruct & snapshotStream) { mAllocatedSnapshotStreams.push_back(snapshotStream); return PersistAndNotify(); } -CHIP_ERROR CameraAVStreamMgmtServer::UpdateSnapshotStreamRangeParams( - SnapshotStreamStruct & snapshotStreamToUpdate, const CameraAVStreamMgmtDelegate::SnapshotStreamAllocateArgs & snapshotStream) +CHIP_ERROR CameraAVStreamManagementCluster::UpdateSnapshotStreamRangeParams( + SnapshotStreamStruct & snapshotStreamToUpdate, + const CameraAVStreamManagementDelegate::SnapshotStreamAllocateArgs & snapshotStream) { // Store original values to detect changes uint16_t origMinResWidth = snapshotStreamToUpdate.minResolution.width; @@ -476,7 +477,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::UpdateSnapshotStreamRangeParams( return CHIP_NO_ERROR; } -CHIP_ERROR CameraAVStreamMgmtServer::RemoveSnapshotStream(uint16_t snapshotStreamId) +CHIP_ERROR CameraAVStreamManagementCluster::RemoveSnapshotStream(uint16_t snapshotStreamId) { mAllocatedSnapshotStreams.erase( std::remove_if(mAllocatedSnapshotStreams.begin(), mAllocatedSnapshotStreams.end(), @@ -486,7 +487,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::RemoveSnapshotStream(uint16_t snapshotStrea return PersistAndNotify(); } -CHIP_ERROR CameraAVStreamMgmtServer::UpdateVideoStreamRefCount(uint16_t videoStreamId, bool shouldIncrement) +CHIP_ERROR CameraAVStreamManagementCluster::UpdateVideoStreamRefCount(uint16_t videoStreamId, bool shouldIncrement) { auto it = std::find_if(mAllocatedVideoStreams.begin(), mAllocatedVideoStreams.end(), [videoStreamId](const VideoStreamStruct & vStream) { return vStream.videoStreamID == videoStreamId; }); @@ -504,7 +505,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::UpdateVideoStreamRefCount(uint16_t videoStr return (it->referenceCount > 0) ? (it->referenceCount--, CHIP_NO_ERROR) : CHIP_ERROR_INVALID_INTEGER_VALUE; } -CHIP_ERROR CameraAVStreamMgmtServer::UpdateAudioStreamRefCount(uint16_t audioStreamId, bool shouldIncrement) +CHIP_ERROR CameraAVStreamManagementCluster::UpdateAudioStreamRefCount(uint16_t audioStreamId, bool shouldIncrement) { auto it = std::find_if(mAllocatedAudioStreams.begin(), mAllocatedAudioStreams.end(), [audioStreamId](const AudioStreamStruct & aStream) { return aStream.audioStreamID == audioStreamId; }); @@ -522,7 +523,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::UpdateAudioStreamRefCount(uint16_t audioStr return (it->referenceCount > 0) ? (it->referenceCount--, CHIP_NO_ERROR) : CHIP_ERROR_INVALID_INTEGER_VALUE; } -CHIP_ERROR CameraAVStreamMgmtServer::UpdateSnapshotStreamRefCount(uint16_t snapshotStreamId, bool shouldIncrement) +CHIP_ERROR CameraAVStreamManagementCluster::UpdateSnapshotStreamRefCount(uint16_t snapshotStreamId, bool shouldIncrement) { auto it = std::find_if( mAllocatedSnapshotStreams.begin(), mAllocatedSnapshotStreams.end(), @@ -541,36 +542,42 @@ CHIP_ERROR CameraAVStreamMgmtServer::UpdateSnapshotStreamRefCount(uint16_t snaps return (it->referenceCount > 0) ? (it->referenceCount--, CHIP_NO_ERROR) : CHIP_ERROR_INVALID_INTEGER_VALUE; } -// AttributeAccessInterface -CHIP_ERROR CameraAVStreamMgmtServer::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) +DataModel::ActionReturnStatus CameraAVStreamManagementCluster::ReadAttribute(const DataModel::ReadAttributeRequest & request, + AttributeValueEncoder & aEncoder) { - VerifyOrDie(aPath.mClusterId == CameraAvStreamManagement::Id); - ChipLogProgress(Zcl, "Camera AVStream Management[ep=%d]: Reading", mEndpointId); + VerifyOrDie(request.path.mClusterId == CameraAvStreamManagement::Id); + ChipLogProgress(Zcl, "Camera AVStream Management[ep=%d]: Reading", mPath.mEndpointId); - switch (aPath.mAttributeId) + switch (request.path.mAttributeId) { case FeatureMap::Id: - ReturnErrorOnFailure(aEncoder.Encode(mFeatures)); + ReturnErrorOnFailure(aEncoder.Encode(mEnabledFeatures)); + break; + + case ClusterRevision::Id: + ReturnErrorOnFailure(aEncoder.Encode(CameraAvStreamManagement::kRevision)); break; + case MaxConcurrentEncoders::Id: VerifyOrReturnError(HasFeature(Feature::kVideo), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get MaxConcurrentEncoders, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mMaxConcurrentEncoders)); break; case MaxEncodedPixelRate::Id: - VerifyOrReturnError( - HasFeature(Feature::kVideo), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get MaxEncodedPixelRate, feature is not supported", mEndpointId)); + VerifyOrReturnError(HasFeature(Feature::kVideo), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, + "CameraAVStreamMgmt[ep=%d]: can not get MaxEncodedPixelRate, feature is not supported", + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mMaxEncodedPixelRate)); break; case VideoSensorParams::Id: - VerifyOrReturnError( - HasFeature(Feature::kVideo), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get VideoSensorParams, feature is not supported", mEndpointId)); + VerifyOrReturnError(HasFeature(Feature::kVideo), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get VideoSensorParams, feature is not supported", + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mVideoSensorParams)); break; @@ -578,21 +585,21 @@ CHIP_ERROR CameraAVStreamMgmtServer::Read(const ConcreteReadAttributePath & aPat VerifyOrReturnError(HasFeature(Feature::kNightVision), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get NightVisionUsesInfrared, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mNightVisionUsesInfrared)); break; case MinViewportResolution::Id: VerifyOrReturnError(HasFeature(Feature::kVideo), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get MinViewportResolution, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mMinViewPortResolution)); break; case RateDistortionTradeOffPoints::Id: VerifyOrReturnError( HasFeature(Feature::kVideo), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get RateDistortionTradeOffPoints, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.EncodeList( [this](const auto & encoder) -> CHIP_ERROR { return this->ReadAndEncodeRateDistortionTradeOffPoints(encoder); })); break; @@ -603,26 +610,27 @@ CHIP_ERROR CameraAVStreamMgmtServer::Read(const ConcreteReadAttributePath & aPat VerifyOrReturnError(HasFeature(Feature::kAudio), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get MicrophoneCapabilities, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mMicrophoneCapabilities)); break; case SpeakerCapabilities::Id: - VerifyOrReturnError( - HasFeature(Feature::kSpeaker), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get SpeakerCapabilities, feature is not supported", mEndpointId)); + VerifyOrReturnError(HasFeature(Feature::kSpeaker), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, + "CameraAVStreamMgmt[ep=%d]: can not get SpeakerCapabilities, feature is not supported", + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mSpeakerCapabilities)); break; case TwoWayTalkSupport::Id: - VerifyOrReturnError( - HasFeature(Feature::kSpeaker), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get TwoWayTalkSupport, feature is not supported", mEndpointId)); + VerifyOrReturnError(HasFeature(Feature::kSpeaker), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get TwoWayTalkSupport, feature is not supported", + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mTwoWayTalkSupport)); break; case SnapshotCapabilities::Id: VerifyOrReturnError(HasFeature(Feature::kSnapshot), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get SnapshotCapabilities, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.EncodeList( [this](const auto & encoder) -> CHIP_ERROR { return this->ReadAndEncodeSnapshotCapabilities(encoder); })); break; @@ -630,15 +638,15 @@ CHIP_ERROR CameraAVStreamMgmtServer::Read(const ConcreteReadAttributePath & aPat ReturnErrorOnFailure(aEncoder.Encode(mMaxNetworkBandwidth)); break; case CurrentFrameRate::Id: - VerifyOrReturnError( - HasFeature(Feature::kVideo), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get CurrentFrameRate, feature is not supported", mEndpointId)); + VerifyOrReturnError(HasFeature(Feature::kVideo), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get CurrentFrameRate, feature is not supported", + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mCurrentFrameRate)); break; case HDRModeEnabled::Id: - VerifyOrReturnError( - HasFeature(Feature::kHighDynamicRange), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get HDRModeEnabled, feature is not supported", mEndpointId)); + VerifyOrReturnError(HasFeature(Feature::kHighDynamicRange), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get HDRModeEnabled, feature is not supported", + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mHDRModeEnabled)); break; case SupportedStreamUsages::Id: @@ -649,7 +657,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Read(const ConcreteReadAttributePath & aPat VerifyOrReturnError(HasFeature(Feature::kVideo), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get AllocatedVideoStreams, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.EncodeList( [this](const auto & encoder) -> CHIP_ERROR { return this->ReadAndEncodeAllocatedVideoStreams(encoder); })); @@ -658,7 +666,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Read(const ConcreteReadAttributePath & aPat VerifyOrReturnError(HasFeature(Feature::kAudio), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get AllocatedAudioStreams, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.EncodeList( [this](const auto & encoder) -> CHIP_ERROR { return this->ReadAndEncodeAllocatedAudioStreams(encoder); })); @@ -667,7 +675,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Read(const ConcreteReadAttributePath & aPat VerifyOrReturnError( HasFeature(Feature::kSnapshot), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get AllocatedSnapshotStreams, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.EncodeList( [this](const auto & encoder) -> CHIP_ERROR { return this->ReadAndEncodeAllocatedSnapshotStreams(encoder); })); @@ -680,143 +688,144 @@ CHIP_ERROR CameraAVStreamMgmtServer::Read(const ConcreteReadAttributePath & aPat VerifyOrReturnError( HasFeature(Feature::kPrivacy), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get SoftRecordingPrivacyModeEnabled, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mSoftRecordingPrivacyModeEnabled)); break; case SoftLivestreamPrivacyModeEnabled::Id: VerifyOrReturnError( HasFeature(Feature::kPrivacy), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get SoftLivestreamPrivacyModeEnabled, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mSoftLivestreamPrivacyModeEnabled)); break; case HardPrivacyModeOn::Id: - VerifyOrReturnError( - SupportsOptAttr(OptionalAttribute::kHardPrivacyModeOn), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get HardPrivacyModeOn, attribute is not supported", mEndpointId)); + VerifyOrReturnError(SupportsOptAttr(OptionalAttribute::kHardPrivacyModeOn), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, + "CameraAVStreamMgmt[ep=%d]: can not get HardPrivacyModeOn, attribute is not supported", + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mHardPrivacyModeOn)); break; case NightVision::Id: VerifyOrReturnError( HasFeature(Feature::kNightVision), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get NightVision, attribute is not supported", mEndpointId)); + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get NightVision, attribute is not supported", mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mNightVision)); break; case NightVisionIllum::Id: VerifyOrReturnError( SupportsOptAttr(OptionalAttribute::kNightVisionIllum), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get NightVisionIllumination, attribute is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mNightVisionIllum)); break; case Viewport::Id: VerifyOrReturnError( HasFeature(Feature::kVideo), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get Viewport, feature is not supported", mEndpointId)); + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get Viewport, feature is not supported", mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mViewport)); break; case SpeakerMuted::Id: VerifyOrReturnError( HasFeature(Feature::kSpeaker), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get SpeakerMuted, feature is not supported", mEndpointId)); + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get SpeakerMuted, feature is not supported", mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mSpeakerMuted)); break; case SpeakerVolumeLevel::Id: - VerifyOrReturnError( - HasFeature(Feature::kSpeaker), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get SpeakerVolumeLevel, feature is not supported", mEndpointId)); + VerifyOrReturnError(HasFeature(Feature::kSpeaker), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get SpeakerVolumeLevel, feature is not supported", + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mSpeakerVolumeLevel)); break; case SpeakerMaxLevel::Id: - VerifyOrReturnError( - HasFeature(Feature::kSpeaker), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get SpeakerMaxLevel, feature is not supported", mEndpointId)); + VerifyOrReturnError(HasFeature(Feature::kSpeaker), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get SpeakerMaxLevel, feature is not supported", + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mSpeakerMaxLevel)); break; case SpeakerMinLevel::Id: - VerifyOrReturnError( - HasFeature(Feature::kSpeaker), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get SpeakerMinLevel, feature is not supported", mEndpointId)); + VerifyOrReturnError(HasFeature(Feature::kSpeaker), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get SpeakerMinLevel, feature is not supported", + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mSpeakerMinLevel)); break; case MicrophoneMuted::Id: - VerifyOrReturnError( - HasFeature(Feature::kAudio), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get MicrophoneMuted, feature is not supported", mEndpointId)); + VerifyOrReturnError(HasFeature(Feature::kAudio), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get MicrophoneMuted, feature is not supported", + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mMicrophoneMuted)); break; case MicrophoneVolumeLevel::Id: VerifyOrReturnError(HasFeature(Feature::kAudio), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get MicrophoneVolumeLevel, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mMicrophoneVolumeLevel)); break; case MicrophoneMaxLevel::Id: - VerifyOrReturnError( - HasFeature(Feature::kAudio), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get MicrophoneMaxLevel, feature is not supported", mEndpointId)); + VerifyOrReturnError(HasFeature(Feature::kAudio), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get MicrophoneMaxLevel, feature is not supported", + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mMicrophoneMaxLevel)); break; case MicrophoneMinLevel::Id: - VerifyOrReturnError( - HasFeature(Feature::kAudio), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get MicrophoneMinLevel, feature is not supported", mEndpointId)); + VerifyOrReturnError(HasFeature(Feature::kAudio), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get MicrophoneMinLevel, feature is not supported", + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mMicrophoneMinLevel)); break; case MicrophoneAGCEnabled::Id: VerifyOrReturnError(SupportsOptAttr(OptionalAttribute::kMicrophoneAGCEnabled), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get MicrophoneAGCEnabled, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mMicrophoneAGCEnabled)); break; case ImageRotation::Id: - VerifyOrReturnError( - SupportsOptAttr(OptionalAttribute::kImageRotation), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get ImageRotation, attribute is not supported", mEndpointId)); + VerifyOrReturnError(SupportsOptAttr(OptionalAttribute::kImageRotation), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get ImageRotation, attribute is not supported", + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mImageRotation)); break; case ImageFlipHorizontal::Id: VerifyOrReturnError(SupportsOptAttr(OptionalAttribute::kImageFlipHorizontal), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get ImageFlipHorizontal, attribute is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mImageFlipHorizontal)); break; case ImageFlipVertical::Id: VerifyOrReturnError(SupportsOptAttr(OptionalAttribute::kImageFlipVertical), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get ImageFlipHorizontal, attribute is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mImageFlipVertical)); break; case LocalVideoRecordingEnabled::Id: VerifyOrReturnError( HasFeature(Feature::kVideo) && HasFeature(Feature::kLocalStorage), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get LocalVideoRecordingEnabled, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mLocalVideoRecordingEnabled)); break; case LocalSnapshotRecordingEnabled::Id: VerifyOrReturnError( HasFeature(Feature::kSnapshot) && HasFeature(Feature::kLocalStorage), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get LocalSnapshotRecordingEnabled, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mLocalSnapshotRecordingEnabled)); break; case StatusLightEnabled::Id: VerifyOrReturnError(SupportsOptAttr(OptionalAttribute::kStatusLightEnabled), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get StatusLightEnabled, attribute is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mStatusLightEnabled)); break; case StatusLightBrightness::Id: VerifyOrReturnError(SupportsOptAttr(OptionalAttribute::kStatusLightBrightness), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not get StatusLightBrightness, attribute is not supported", - mEndpointId)); + mPath.mEndpointId)); ReturnErrorOnFailure(aEncoder.Encode(mStatusLightBrightness)); break; } @@ -824,16 +833,17 @@ CHIP_ERROR CameraAVStreamMgmtServer::Read(const ConcreteReadAttributePath & aPat return CHIP_NO_ERROR; } -CHIP_ERROR CameraAVStreamMgmtServer::Write(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder) +DataModel::ActionReturnStatus CameraAVStreamManagementCluster::WriteAttribute(const DataModel::WriteAttributeRequest & request, + AttributeValueDecoder & aDecoder) { - VerifyOrDie(aPath.mClusterId == CameraAvStreamManagement::Id); + VerifyOrDie(request.path.mClusterId == CameraAvStreamManagement::Id); - switch (aPath.mAttributeId) + switch (request.path.mAttributeId) { case HDRModeEnabled::Id: { - VerifyOrReturnError( - HasFeature(Feature::kHighDynamicRange), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set HDRModeEnabled, feature is not supported", mEndpointId)); + VerifyOrReturnError(HasFeature(Feature::kHighDynamicRange), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set HDRModeEnabled, feature is not supported", + mPath.mEndpointId)); bool hdrModeEnabled; ReturnErrorOnFailure(aDecoder.Decode(hdrModeEnabled)); @@ -843,7 +853,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Write(const ConcreteDataAttributePath & aPa VerifyOrReturnError( HasFeature(Feature::kPrivacy), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set SoftRecordingPrivacyModeEnabled, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); bool softRecPrivModeEnabled; ReturnErrorOnFailure(aDecoder.Decode(softRecPrivModeEnabled)); @@ -853,7 +863,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Write(const ConcreteDataAttributePath & aPa VerifyOrReturnError( HasFeature(Feature::kPrivacy), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set SoftLivestreamPrivacyModeEnabled, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); bool softLivestreamPrivModeEnabled; ReturnErrorOnFailure(aDecoder.Decode(softLivestreamPrivModeEnabled)); @@ -862,7 +872,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Write(const ConcreteDataAttributePath & aPa case NightVision::Id: { VerifyOrReturnError( HasFeature(Feature::kNightVision), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set NightVision, feature is not supported", mEndpointId)); + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set NightVision, feature is not supported", mPath.mEndpointId)); TriStateAutoEnum nightVision; ReturnErrorOnFailure(aDecoder.Decode(nightVision)); @@ -872,7 +882,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Write(const ConcreteDataAttributePath & aPa VerifyOrReturnError(SupportsOptAttr(OptionalAttribute::kNightVisionIllum), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set NightVisionIllumination, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); TriStateAutoEnum nightVisionIllum; ReturnErrorOnFailure(aDecoder.Decode(nightVisionIllum)); @@ -881,7 +891,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Write(const ConcreteDataAttributePath & aPa case Viewport::Id: { VerifyOrReturnError( HasFeature(Feature::kVideo), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set Viewport, feature is not supported", mEndpointId)); + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set Viewport, feature is not supported", mPath.mEndpointId)); Globals::Structs::ViewportStruct::Type viewPort; ReturnErrorOnFailure(aDecoder.Decode(viewPort)); return SetViewport(viewPort); @@ -889,23 +899,23 @@ CHIP_ERROR CameraAVStreamMgmtServer::Write(const ConcreteDataAttributePath & aPa case SpeakerMuted::Id: { VerifyOrReturnError( HasFeature(Feature::kSpeaker), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set SpeakerMuted, feature is not supported", mEndpointId)); + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set SpeakerMuted, feature is not supported", mPath.mEndpointId)); bool speakerMuted; ReturnErrorOnFailure(aDecoder.Decode(speakerMuted)); return SetSpeakerMuted(speakerMuted); } case SpeakerVolumeLevel::Id: { - VerifyOrReturnError( - HasFeature(Feature::kSpeaker), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set SpeakerVolumeLevel, feature is not supported", mEndpointId)); + VerifyOrReturnError(HasFeature(Feature::kSpeaker), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set SpeakerVolumeLevel, feature is not supported", + mPath.mEndpointId)); uint8_t speakerVolLevel; ReturnErrorOnFailure(aDecoder.Decode(speakerVolLevel)); return SetSpeakerVolumeLevel(speakerVolLevel); } case MicrophoneMuted::Id: { - VerifyOrReturnError( - HasFeature(Feature::kAudio), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set MicrophoneMuted, feature is not supported", mEndpointId)); + VerifyOrReturnError(HasFeature(Feature::kAudio), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set MicrophoneMuted, feature is not supported", + mPath.mEndpointId)); bool micMuted; ReturnErrorOnFailure(aDecoder.Decode(micMuted)); return SetMicrophoneMuted(micMuted); @@ -914,7 +924,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Write(const ConcreteDataAttributePath & aPa VerifyOrReturnError(HasFeature(Feature::kAudio), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set MicrophoneVolumeLevel, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); uint8_t micVolLevel; ReturnErrorOnFailure(aDecoder.Decode(micVolLevel)); return SetMicrophoneVolumeLevel(micVolLevel); @@ -923,7 +933,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Write(const ConcreteDataAttributePath & aPa VerifyOrReturnError(SupportsOptAttr(OptionalAttribute::kMicrophoneAGCEnabled), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set MicrophoneAGCEnabled, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); bool micAGCEnabled; ReturnErrorOnFailure(aDecoder.Decode(micAGCEnabled)); return SetMicrophoneAGCEnabled(micAGCEnabled); @@ -931,23 +941,24 @@ CHIP_ERROR CameraAVStreamMgmtServer::Write(const ConcreteDataAttributePath & aPa case ImageRotation::Id: { VerifyOrReturnError( SupportsOptAttr(OptionalAttribute::kImageRotation), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set ImageRotation, feature is not supported", mEndpointId)); + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set ImageRotation, feature is not supported", mPath.mEndpointId)); uint16_t imageRotation; ReturnErrorOnFailure(aDecoder.Decode(imageRotation)); return SetImageRotation(imageRotation); } case ImageFlipHorizontal::Id: { - VerifyOrReturnError( - SupportsOptAttr(OptionalAttribute::kImageFlipHorizontal), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set ImageFlipHorizontal, feature is not supported", mEndpointId)); + VerifyOrReturnError(SupportsOptAttr(OptionalAttribute::kImageFlipHorizontal), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, + "CameraAVStreamMgmt[ep=%d]: can not set ImageFlipHorizontal, feature is not supported", + mPath.mEndpointId)); bool imageFlipHorizontal; ReturnErrorOnFailure(aDecoder.Decode(imageFlipHorizontal)); return SetImageFlipHorizontal(imageFlipHorizontal); } case ImageFlipVertical::Id: { - VerifyOrReturnError( - SupportsOptAttr(OptionalAttribute::kImageFlipVertical), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set ImageFlipVertical, feature is not supported", mEndpointId)); + VerifyOrReturnError(SupportsOptAttr(OptionalAttribute::kImageFlipVertical), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set ImageFlipVertical, feature is not supported", + mPath.mEndpointId)); bool imageFlipVertical; ReturnErrorOnFailure(aDecoder.Decode(imageFlipVertical)); return SetImageFlipVertical(imageFlipVertical); @@ -956,7 +967,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Write(const ConcreteDataAttributePath & aPa VerifyOrReturnError( HasFeature(Feature::kVideo) && HasFeature(Feature::kLocalStorage), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set LocalVideoRecordingEnabled, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); bool localVidRecEnabled; ReturnErrorOnFailure(aDecoder.Decode(localVidRecEnabled)); return SetLocalVideoRecordingEnabled(localVidRecEnabled); @@ -965,15 +976,15 @@ CHIP_ERROR CameraAVStreamMgmtServer::Write(const ConcreteDataAttributePath & aPa VerifyOrReturnError( HasFeature(Feature::kSnapshot) && HasFeature(Feature::kLocalStorage), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set LocalSnapshotRecordingEnabled, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); bool localSnapshotRecEnabled; ReturnErrorOnFailure(aDecoder.Decode(localSnapshotRecEnabled)); return SetLocalSnapshotRecordingEnabled(localSnapshotRecEnabled); } case StatusLightEnabled::Id: { - VerifyOrReturnError( - SupportsOptAttr(OptionalAttribute::kStatusLightEnabled), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set StatusLightEnabled, feature is not supported", mEndpointId)); + VerifyOrReturnError(SupportsOptAttr(OptionalAttribute::kStatusLightEnabled), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set StatusLightEnabled, feature is not supported", + mPath.mEndpointId)); bool statusLightEnabled; ReturnErrorOnFailure(aDecoder.Decode(statusLightEnabled)); return SetStatusLightEnabled(statusLightEnabled); @@ -982,7 +993,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::Write(const ConcreteDataAttributePath & aPa VerifyOrReturnError(SupportsOptAttr(OptionalAttribute::kStatusLightBrightness), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute), ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: can not set StatusLightBrightness, feature is not supported", - mEndpointId)); + mPath.mEndpointId)); Globals::ThreeLevelAutoEnum statusLightBrightness; ReturnErrorOnFailure(aDecoder.Decode(statusLightBrightness)); return SetStatusLightBrightness(statusLightBrightness); @@ -994,8 +1005,8 @@ CHIP_ERROR CameraAVStreamMgmtServer::Write(const ConcreteDataAttributePath & aPa } } -void CameraAVStreamMgmtServer::ModifyVideoStream(const uint16_t streamID, const Optional waterMarkEnabled, - const Optional osdEnabled) +void CameraAVStreamManagementCluster::ModifyVideoStream(const uint16_t streamID, const Optional waterMarkEnabled, + const Optional osdEnabled) { for (VideoStreamStruct & stream : mAllocatedVideoStreams) { @@ -1014,7 +1025,7 @@ void CameraAVStreamMgmtServer::ModifyVideoStream(const uint16_t streamID, const } if (wasModified) { - PersistAndNotify(); + TEMPORARY_RETURN_IGNORED PersistAndNotify(); ChipLogProgress(Camera, "Modified video stream with ID: %d", streamID); } return; @@ -1022,8 +1033,8 @@ void CameraAVStreamMgmtServer::ModifyVideoStream(const uint16_t streamID, const } } -void CameraAVStreamMgmtServer::ModifySnapshotStream(const uint16_t streamID, const Optional waterMarkEnabled, - const Optional osdEnabled) +void CameraAVStreamManagementCluster::ModifySnapshotStream(const uint16_t streamID, const Optional waterMarkEnabled, + const Optional osdEnabled) { for (SnapshotStreamStruct & stream : mAllocatedSnapshotStreams) { @@ -1042,7 +1053,7 @@ void CameraAVStreamMgmtServer::ModifySnapshotStream(const uint16_t streamID, con } if (wasModified) { - PersistAndNotify(); + TEMPORARY_RETURN_IGNORED PersistAndNotify(); ChipLogProgress(Camera, "Modified snapshot stream with ID: %d", streamID); } return; @@ -1050,62 +1061,62 @@ void CameraAVStreamMgmtServer::ModifySnapshotStream(const uint16_t streamID, con } } -CHIP_ERROR CameraAVStreamMgmtServer::SetCurrentFrameRate(uint16_t aCurrentFrameRate) +CHIP_ERROR CameraAVStreamManagementCluster::SetCurrentFrameRate(uint16_t aCurrentFrameRate) { return SetAttributeIfDifferent(mCurrentFrameRate, aCurrentFrameRate, Attributes::CurrentFrameRate::Id, /* shouldPersist = */ false); } -CHIP_ERROR CameraAVStreamMgmtServer::SetHDRModeEnabled(bool aHDRModeEnabled) +CHIP_ERROR CameraAVStreamManagementCluster::SetHDRModeEnabled(bool aHDRModeEnabled) { return SetAttributeIfDifferent(mHDRModeEnabled, aHDRModeEnabled, Attributes::HDRModeEnabled::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetSoftRecordingPrivacyModeEnabled(bool aSoftRecordingPrivacyModeEnabled) +CHIP_ERROR CameraAVStreamManagementCluster::SetSoftRecordingPrivacyModeEnabled(bool aSoftRecordingPrivacyModeEnabled) { return SetAttributeIfDifferent(mSoftRecordingPrivacyModeEnabled, aSoftRecordingPrivacyModeEnabled, Attributes::SoftRecordingPrivacyModeEnabled::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetSoftLivestreamPrivacyModeEnabled(bool aSoftLivestreamPrivacyModeEnabled) +CHIP_ERROR CameraAVStreamManagementCluster::SetSoftLivestreamPrivacyModeEnabled(bool aSoftLivestreamPrivacyModeEnabled) { return SetAttributeIfDifferent(mSoftLivestreamPrivacyModeEnabled, aSoftLivestreamPrivacyModeEnabled, Attributes::SoftLivestreamPrivacyModeEnabled::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetHardPrivacyModeOn(bool aHardPrivacyModeOn) +CHIP_ERROR CameraAVStreamManagementCluster::SetHardPrivacyModeOn(bool aHardPrivacyModeOn) { return SetAttributeIfDifferent(mHardPrivacyModeOn, aHardPrivacyModeOn, Attributes::HardPrivacyModeOn::Id, /* shouldPersist = */ false); } -CHIP_ERROR CameraAVStreamMgmtServer::SetNightVision(TriStateAutoEnum aNightVision) +CHIP_ERROR CameraAVStreamManagementCluster::SetNightVision(TriStateAutoEnum aNightVision) { if (mNightVision != aNightVision) { mNightVision = aNightVision; - auto path = ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::NightVision::Id); + auto path = ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::NightVision::Id); ReturnErrorOnFailure(GetSafeAttributePersistenceProvider()->WriteScalarValue(path, to_underlying(mNightVision))); mDelegate.OnAttributeChanged(Attributes::NightVision::Id); - MatterReportingAttributeChangeCallback(path); + NotifyAttributeChanged(Attributes::NightVision::Id); } return CHIP_NO_ERROR; } -CHIP_ERROR CameraAVStreamMgmtServer::SetNightVisionIllum(TriStateAutoEnum aNightVisionIllum) +CHIP_ERROR CameraAVStreamManagementCluster::SetNightVisionIllum(TriStateAutoEnum aNightVisionIllum) { if (mNightVisionIllum != aNightVisionIllum) { mNightVisionIllum = aNightVisionIllum; - auto path = ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::NightVisionIllum::Id); + auto path = ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::NightVisionIllum::Id); ReturnErrorOnFailure(GetSafeAttributePersistenceProvider()->WriteScalarValue(path, to_underlying(mNightVisionIllum))); mDelegate.OnAttributeChanged(Attributes::NightVisionIllum::Id); - MatterReportingAttributeChangeCallback(path); + NotifyAttributeChanged(Attributes::NightVisionIllum::Id); } return CHIP_NO_ERROR; } -CHIP_ERROR CameraAVStreamMgmtServer::SetViewport(const Globals::Structs::ViewportStruct::Type & aViewport) +CHIP_ERROR CameraAVStreamManagementCluster::SetViewport(const Globals::Structs::ViewportStruct::Type & aViewport) { // The following validation steps are required // 1. the new viewport is not larger than the sensor max @@ -1117,7 +1128,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::SetViewport(const Globals::Structs::Viewpor if ((requestedWidth < mMinViewPortResolution.width) || (requestedHeight < mMinViewPortResolution.height) || (requestedWidth > mVideoSensorParams.sensorWidth) || (requestedHeight > mVideoSensorParams.sensorHeight)) { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: SetViewport with invalid viewport dimensions", mEndpointId); + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: SetViewport with invalid viewport dimensions", mPath.mEndpointId); return CHIP_IM_GLOBAL_STATUS(ConstraintError); } @@ -1129,25 +1140,24 @@ CHIP_ERROR CameraAVStreamMgmtServer::SetViewport(const Globals::Structs::Viewpor // Ensure that the aspect ration of the viewport matches the aspect ratio of the sensor if (requestedAR != deviceAR) { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: SetViewport with mismatching aspect ratio.", mEndpointId); + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: SetViewport with mismatching aspect ratio.", mPath.mEndpointId); return CHIP_IM_GLOBAL_STATUS(ConstraintError); } mViewport = aViewport; - StoreViewport(mViewport); + TEMPORARY_RETURN_IGNORED StoreViewport(mViewport); mDelegate.OnAttributeChanged(Attributes::Viewport::Id); - auto path = ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::Viewport::Id); - MatterReportingAttributeChangeCallback(path); + NotifyAttributeChanged(Attributes::Viewport::Id); return CHIP_NO_ERROR; } -CHIP_ERROR CameraAVStreamMgmtServer::SetSpeakerMuted(bool aSpeakerMuted) +CHIP_ERROR CameraAVStreamManagementCluster::SetSpeakerMuted(bool aSpeakerMuted) { return SetAttributeIfDifferent(mSpeakerMuted, aSpeakerMuted, Attributes::SpeakerMuted::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetSpeakerVolumeLevel(uint8_t aSpeakerVolumeLevel) +CHIP_ERROR CameraAVStreamManagementCluster::SetSpeakerVolumeLevel(uint8_t aSpeakerVolumeLevel) { if (aSpeakerVolumeLevel < mSpeakerMinLevel || aSpeakerVolumeLevel > mSpeakerMaxLevel) { @@ -1157,7 +1167,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::SetSpeakerVolumeLevel(uint8_t aSpeakerVolum return SetAttributeIfDifferent(mSpeakerVolumeLevel, aSpeakerVolumeLevel, Attributes::SpeakerVolumeLevel::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetSpeakerMaxLevel(uint8_t aSpeakerMaxLevel) +CHIP_ERROR CameraAVStreamManagementCluster::SetSpeakerMaxLevel(uint8_t aSpeakerMaxLevel) { if (aSpeakerMaxLevel < mSpeakerMinLevel || aSpeakerMaxLevel > kMaxSpeakerLevel) { @@ -1167,7 +1177,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::SetSpeakerMaxLevel(uint8_t aSpeakerMaxLevel return SetAttributeIfDifferent(mSpeakerMaxLevel, aSpeakerMaxLevel, Attributes::SpeakerMaxLevel::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetSpeakerMinLevel(uint8_t aSpeakerMinLevel) +CHIP_ERROR CameraAVStreamManagementCluster::SetSpeakerMinLevel(uint8_t aSpeakerMinLevel) { if (aSpeakerMinLevel > mSpeakerMaxLevel) { @@ -1177,12 +1187,12 @@ CHIP_ERROR CameraAVStreamMgmtServer::SetSpeakerMinLevel(uint8_t aSpeakerMinLevel return SetAttributeIfDifferent(mSpeakerMinLevel, aSpeakerMinLevel, Attributes::SpeakerMinLevel::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetMicrophoneMuted(bool aMicrophoneMuted) +CHIP_ERROR CameraAVStreamManagementCluster::SetMicrophoneMuted(bool aMicrophoneMuted) { return SetAttributeIfDifferent(mMicrophoneMuted, aMicrophoneMuted, Attributes::MicrophoneMuted::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetMicrophoneVolumeLevel(uint8_t aMicrophoneVolumeLevel) +CHIP_ERROR CameraAVStreamManagementCluster::SetMicrophoneVolumeLevel(uint8_t aMicrophoneVolumeLevel) { if (aMicrophoneVolumeLevel < mMicrophoneMinLevel || aMicrophoneVolumeLevel > mMicrophoneMaxLevel) { @@ -1192,7 +1202,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::SetMicrophoneVolumeLevel(uint8_t aMicrophon return SetAttributeIfDifferent(mMicrophoneVolumeLevel, aMicrophoneVolumeLevel, Attributes::MicrophoneVolumeLevel::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetMicrophoneMaxLevel(uint8_t aMicrophoneMaxLevel) +CHIP_ERROR CameraAVStreamManagementCluster::SetMicrophoneMaxLevel(uint8_t aMicrophoneMaxLevel) { if (aMicrophoneMaxLevel < mMicrophoneMinLevel || aMicrophoneMaxLevel > kMaxMicrophoneLevel) { @@ -1202,7 +1212,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::SetMicrophoneMaxLevel(uint8_t aMicrophoneMa return SetAttributeIfDifferent(mMicrophoneMaxLevel, aMicrophoneMaxLevel, Attributes::MicrophoneMaxLevel::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetMicrophoneMinLevel(uint8_t aMicrophoneMinLevel) +CHIP_ERROR CameraAVStreamManagementCluster::SetMicrophoneMinLevel(uint8_t aMicrophoneMinLevel) { if (aMicrophoneMinLevel > mMicrophoneMaxLevel) { @@ -1212,12 +1222,12 @@ CHIP_ERROR CameraAVStreamMgmtServer::SetMicrophoneMinLevel(uint8_t aMicrophoneMi return SetAttributeIfDifferent(mMicrophoneMinLevel, aMicrophoneMinLevel, Attributes::MicrophoneMinLevel::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetMicrophoneAGCEnabled(bool aMicrophoneAGCEnabled) +CHIP_ERROR CameraAVStreamManagementCluster::SetMicrophoneAGCEnabled(bool aMicrophoneAGCEnabled) { return SetAttributeIfDifferent(mMicrophoneAGCEnabled, aMicrophoneAGCEnabled, Attributes::MicrophoneAGCEnabled::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetImageRotation(uint16_t aImageRotation) +CHIP_ERROR CameraAVStreamManagementCluster::SetImageRotation(uint16_t aImageRotation) { if (mImageRotation > kMaxImageRotationDegrees) { @@ -1227,156 +1237,157 @@ CHIP_ERROR CameraAVStreamMgmtServer::SetImageRotation(uint16_t aImageRotation) return SetAttributeIfDifferent(mImageRotation, aImageRotation, Attributes::ImageRotation::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetImageFlipHorizontal(bool aImageFlipHorizontal) +CHIP_ERROR CameraAVStreamManagementCluster::SetImageFlipHorizontal(bool aImageFlipHorizontal) { return SetAttributeIfDifferent(mImageFlipHorizontal, aImageFlipHorizontal, Attributes::ImageFlipHorizontal::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetImageFlipVertical(bool aImageFlipVertical) +CHIP_ERROR CameraAVStreamManagementCluster::SetImageFlipVertical(bool aImageFlipVertical) { return SetAttributeIfDifferent(mImageFlipVertical, aImageFlipVertical, Attributes::ImageFlipVertical::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetLocalVideoRecordingEnabled(bool aLocalVideoRecordingEnabled) +CHIP_ERROR CameraAVStreamManagementCluster::SetLocalVideoRecordingEnabled(bool aLocalVideoRecordingEnabled) { return SetAttributeIfDifferent(mLocalVideoRecordingEnabled, aLocalVideoRecordingEnabled, Attributes::LocalVideoRecordingEnabled::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetLocalSnapshotRecordingEnabled(bool aLocalSnapshotRecordingEnabled) +CHIP_ERROR CameraAVStreamManagementCluster::SetLocalSnapshotRecordingEnabled(bool aLocalSnapshotRecordingEnabled) { return SetAttributeIfDifferent(mLocalSnapshotRecordingEnabled, aLocalSnapshotRecordingEnabled, Attributes::LocalSnapshotRecordingEnabled::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetStatusLightEnabled(bool aStatusLightEnabled) +CHIP_ERROR CameraAVStreamManagementCluster::SetStatusLightEnabled(bool aStatusLightEnabled) { return SetAttributeIfDifferent(mStatusLightEnabled, aStatusLightEnabled, Attributes::StatusLightEnabled::Id); } -CHIP_ERROR CameraAVStreamMgmtServer::SetStatusLightBrightness(Globals::ThreeLevelAutoEnum aStatusLightBrightness) +CHIP_ERROR CameraAVStreamManagementCluster::SetStatusLightBrightness(Globals::ThreeLevelAutoEnum aStatusLightBrightness) { if (mStatusLightBrightness != aStatusLightBrightness) { mStatusLightBrightness = aStatusLightBrightness; - auto path = ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::StatusLightBrightness::Id); + auto path = ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::StatusLightBrightness::Id); ReturnErrorOnFailure(GetSafeAttributePersistenceProvider()->WriteScalarValue(path, to_underlying(mStatusLightBrightness))); mDelegate.OnAttributeChanged(Attributes::StatusLightBrightness::Id); - MatterReportingAttributeChangeCallback(path); + NotifyAttributeChanged(Attributes::StatusLightBrightness::Id); } return CHIP_NO_ERROR; } -void CameraAVStreamMgmtServer::LoadPersistentAttributes() +void CameraAVStreamManagementCluster::LoadPersistentAttributes() { CHIP_ERROR err = CHIP_NO_ERROR; // Load HDR Mode Enabled bool storedHDRModeEnabled = false; err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::HDRModeEnabled::Id), storedHDRModeEnabled); + ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::HDRModeEnabled::Id), + storedHDRModeEnabled); if (err == CHIP_NO_ERROR) { mHDRModeEnabled = storedHDRModeEnabled; - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded HDRModeEnabled as %u", mEndpointId, mHDRModeEnabled); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded HDRModeEnabled as %u", mPath.mEndpointId, mHDRModeEnabled); } else { ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the HDRModeEnabled from the KVS. Defaulting to %u", - mEndpointId, mHDRModeEnabled); + mPath.mEndpointId, mHDRModeEnabled); } // Load AllocatedVideoStreams err = LoadAllocatedStreams(); if (err != CHIP_NO_ERROR) { - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load allocated video streams from the KVS.", mEndpointId); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load allocated video streams from the KVS.", mPath.mEndpointId); } // Load AllocatedAudioStreams err = LoadAllocatedStreams(); if (err != CHIP_NO_ERROR) { - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load allocated audio streams from the KVS.", mEndpointId); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load allocated audio streams from the KVS.", mPath.mEndpointId); } // Load AllocatedSnapshotStreams err = LoadAllocatedStreams(); if (err != CHIP_NO_ERROR) { - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load allocated snapshot streams from the KVS.", mEndpointId); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load allocated snapshot streams from the KVS.", mPath.mEndpointId); } // Load StreamUsagePriorities err = LoadStreamUsagePriorities(); if (err != CHIP_NO_ERROR) { - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the StreamUsagePriorities from the KVS.", mEndpointId); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the StreamUsagePriorities from the KVS.", mPath.mEndpointId); } // Load SoftRecordingPrivacyModeEnabled bool softRecordingPrivacyModeEnabled = false; err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::SoftRecordingPrivacyModeEnabled::Id), + ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::SoftRecordingPrivacyModeEnabled::Id), softRecordingPrivacyModeEnabled); if (err == CHIP_NO_ERROR) { mSoftRecordingPrivacyModeEnabled = softRecordingPrivacyModeEnabled; - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded SoftRecordingPrivacyModeEnabled as %u", mEndpointId, + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded SoftRecordingPrivacyModeEnabled as %u", mPath.mEndpointId, mSoftRecordingPrivacyModeEnabled); } else { ChipLogDetail( Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the SoftRecordingPrivacyModeEnabled from the KVS. Defaulting to %u", - mEndpointId, mSoftRecordingPrivacyModeEnabled); + mPath.mEndpointId, mSoftRecordingPrivacyModeEnabled); } // Load SoftLivestreamPrivacyModeEnabled bool softLivestreamPrivacyModeEnabled = false; err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::SoftLivestreamPrivacyModeEnabled::Id), + ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::SoftLivestreamPrivacyModeEnabled::Id), softLivestreamPrivacyModeEnabled); if (err == CHIP_NO_ERROR) { mSoftLivestreamPrivacyModeEnabled = softLivestreamPrivacyModeEnabled; - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded SoftLivestreamPrivacyModeEnabled as %u", mEndpointId, + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded SoftLivestreamPrivacyModeEnabled as %u", mPath.mEndpointId, mSoftLivestreamPrivacyModeEnabled); } else { ChipLogDetail( Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the SoftLivestreamPrivacyModeEnabled from the KVS. Defaulting to %u", - mEndpointId, mSoftLivestreamPrivacyModeEnabled); + mPath.mEndpointId, mSoftLivestreamPrivacyModeEnabled); } // Load NightVision uint8_t nightVision = 0; err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::NightVision::Id), nightVision); + ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::NightVision::Id), nightVision); if (err == CHIP_NO_ERROR) { mNightVision = static_cast(nightVision); - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded NightVision as %d", mEndpointId, to_underlying(mNightVision)); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded NightVision as %d", mPath.mEndpointId, to_underlying(mNightVision)); } else { - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the NightVision from the KVS. Defaulting to %d", mEndpointId, - to_underlying(mNightVision)); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the NightVision from the KVS. Defaulting to %d", + mPath.mEndpointId, to_underlying(mNightVision)); } // Load NightVisionIllum uint8_t nightVisionIllum = 0; err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::NightVisionIllum::Id), nightVisionIllum); + ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::NightVisionIllum::Id), nightVisionIllum); if (err == CHIP_NO_ERROR) { mNightVisionIllum = static_cast(nightVisionIllum); - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded NightVisionIllum as %d", mEndpointId, + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded NightVisionIllum as %d", mPath.mEndpointId, to_underlying(mNightVisionIllum)); } else { ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the NightVisionIllum from the KVS. Defaulting to %d", - mEndpointId, to_underlying(mNightVisionIllum)); + mPath.mEndpointId, to_underlying(mNightVisionIllum)); } // Load Viewport @@ -1385,208 +1396,219 @@ void CameraAVStreamMgmtServer::LoadPersistentAttributes() if (err == CHIP_NO_ERROR) { mViewport = viewport; - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded Viewport", mEndpointId); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded Viewport", mPath.mEndpointId); } else { - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the Viewport from the KVS.", mEndpointId); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the Viewport from the KVS.", mPath.mEndpointId); } // Load SpeakerMuted bool speakerMuted = false; err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::SpeakerMuted::Id), speakerMuted); + ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::SpeakerMuted::Id), speakerMuted); if (err == CHIP_NO_ERROR) { mSpeakerMuted = speakerMuted; - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded SpeakerMuted as %u", mEndpointId, mSpeakerMuted); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded SpeakerMuted as %u", mPath.mEndpointId, mSpeakerMuted); } else { - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the SpeakerMuted from the KVS. Defaulting to %u", mEndpointId, - mSpeakerMuted); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the SpeakerMuted from the KVS. Defaulting to %u", + mPath.mEndpointId, mSpeakerMuted); } // Load SpeakerVolumeLevel uint8_t speakerVolumeLevel = 0; err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::SpeakerVolumeLevel::Id), speakerVolumeLevel); + ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::SpeakerVolumeLevel::Id), + speakerVolumeLevel); if (err == CHIP_NO_ERROR) { mSpeakerVolumeLevel = speakerVolumeLevel; - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded SpeakerVolumeLevel as %u", mEndpointId, mSpeakerVolumeLevel); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded SpeakerVolumeLevel as %u", mPath.mEndpointId, mSpeakerVolumeLevel); } else { ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the SpeakerVolumeLevel from the KVS. Defaulting to %u", - mEndpointId, mSpeakerVolumeLevel); + mPath.mEndpointId, mSpeakerVolumeLevel); } // Load MicrophoneMuted bool microphoneMuted = false; err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::MicrophoneMuted::Id), microphoneMuted); + ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::MicrophoneMuted::Id), microphoneMuted); if (err == CHIP_NO_ERROR) { mMicrophoneMuted = microphoneMuted; - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded MicrophoneMuted as %u", mEndpointId, mMicrophoneMuted); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded MicrophoneMuted as %u", mPath.mEndpointId, mMicrophoneMuted); } else { ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the MicrophoneMuted from the KVS. Defaulting to %u", - mEndpointId, mMicrophoneMuted); + mPath.mEndpointId, mMicrophoneMuted); } // Load MicrophoneVolumeLevel uint8_t microphoneVolumeLevel = 0; err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::MicrophoneVolumeLevel::Id), + ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::MicrophoneVolumeLevel::Id), microphoneVolumeLevel); if (err == CHIP_NO_ERROR) { mMicrophoneVolumeLevel = microphoneVolumeLevel; - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded MicrophoneVolumeLevel as %u", mEndpointId, mMicrophoneVolumeLevel); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded MicrophoneVolumeLevel as %u", mPath.mEndpointId, + mMicrophoneVolumeLevel); } else { ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the MicrophoneVolumeLevel from the KVS. Defaulting to %u", - mEndpointId, mMicrophoneVolumeLevel); + mPath.mEndpointId, mMicrophoneVolumeLevel); } // Load MicrophoneAGCEnabled bool microphoneAGCEnabled = false; err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::MicrophoneAGCEnabled::Id), + ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::MicrophoneAGCEnabled::Id), microphoneAGCEnabled); if (err == CHIP_NO_ERROR) { mMicrophoneAGCEnabled = microphoneAGCEnabled; - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded MicrophoneAGCEnabled as %u", mEndpointId, mMicrophoneAGCEnabled); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded MicrophoneAGCEnabled as %u", mPath.mEndpointId, + mMicrophoneAGCEnabled); } else { ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the MicrophoneAGCEnabled from the KVS. Defaulting to %u", - mEndpointId, mMicrophoneAGCEnabled); + mPath.mEndpointId, mMicrophoneAGCEnabled); } // Load ImageRotation uint16_t imageRotation = 0; err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::ImageRotation::Id), imageRotation); + ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::ImageRotation::Id), imageRotation); if (err == CHIP_NO_ERROR) { mImageRotation = imageRotation; - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded ImageRotation as %u", mEndpointId, mImageRotation); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded ImageRotation as %u", mPath.mEndpointId, mImageRotation); } else { ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the ImageRotation from the KVS. Defaulting to %u", - mEndpointId, mImageRotation); + mPath.mEndpointId, mImageRotation); } // Load ImageFlipHorizontal bool imageFlipHorizontal = false; err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::ImageFlipHorizontal::Id), imageFlipHorizontal); + ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::ImageFlipHorizontal::Id), + imageFlipHorizontal); if (err == CHIP_NO_ERROR) { mImageFlipHorizontal = imageFlipHorizontal; - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded ImageFlipHorizontal as %u", mEndpointId, mImageFlipHorizontal); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded ImageFlipHorizontal as %u", mPath.mEndpointId, mImageFlipHorizontal); } else { ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the ImageFlipHorizontal from the KVS. Defaulting to %u", - mEndpointId, mImageFlipHorizontal); + mPath.mEndpointId, mImageFlipHorizontal); } // Load ImageFlipVertical bool imageFlipVertical = false; err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::ImageFlipVertical::Id), imageFlipVertical); + ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::ImageFlipVertical::Id), + imageFlipVertical); if (err == CHIP_NO_ERROR) { mImageFlipVertical = imageFlipVertical; - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded ImageFlipVertical as %u", mEndpointId, mImageFlipVertical); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded ImageFlipVertical as %u", mPath.mEndpointId, mImageFlipVertical); } else { ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the ImageFlipVertical from the KVS. Defaulting to %u", - mEndpointId, mImageFlipVertical); + mPath.mEndpointId, mImageFlipVertical); } // Load LocalVideoRecordingEnabled bool localVideoRecordingEnabled = false; err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::LocalVideoRecordingEnabled::Id), + ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::LocalVideoRecordingEnabled::Id), localVideoRecordingEnabled); if (err == CHIP_NO_ERROR) { mLocalVideoRecordingEnabled = localVideoRecordingEnabled; - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded LocalVideoRecordingEnabled as %u", mEndpointId, + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded LocalVideoRecordingEnabled as %u", mPath.mEndpointId, mLocalVideoRecordingEnabled); } else { ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the LocalVideoRecordingEnabled from the KVS. Defaulting to %u", - mEndpointId, mLocalVideoRecordingEnabled); + mPath.mEndpointId, mLocalVideoRecordingEnabled); } // Load LocalSnapshotRecordingEnabled bool localSnapshotRecordingEnabled = false; err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::LocalSnapshotRecordingEnabled::Id), + ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::LocalSnapshotRecordingEnabled::Id), localSnapshotRecordingEnabled); if (err == CHIP_NO_ERROR) { mLocalSnapshotRecordingEnabled = localSnapshotRecordingEnabled; - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded LocalSnapshotRecordingEnabled as %u", mEndpointId, + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded LocalSnapshotRecordingEnabled as %u", mPath.mEndpointId, mLocalSnapshotRecordingEnabled); } else { ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the LocalSnapshotRecordingEnabled from the KVS. Defaulting to %u", - mEndpointId, mLocalSnapshotRecordingEnabled); + mPath.mEndpointId, mLocalSnapshotRecordingEnabled); } // Load StatusLightEnabled bool statusLightEnabled = false; err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::StatusLightEnabled::Id), statusLightEnabled); + ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::StatusLightEnabled::Id), + statusLightEnabled); if (err == CHIP_NO_ERROR) { mStatusLightEnabled = statusLightEnabled; - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded StatusLightEnabled as %u", mEndpointId, mStatusLightEnabled); + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded StatusLightEnabled as %u", mPath.mEndpointId, mStatusLightEnabled); } else { ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the StatusLightEnabled from the KVS. Defaulting to %u", - mEndpointId, mStatusLightEnabled); + mPath.mEndpointId, mStatusLightEnabled); } // Load StatusLightBrightness uint8_t statusLightBrightness = 0; err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::StatusLightBrightness::Id), + ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::StatusLightBrightness::Id), statusLightBrightness); if (err == CHIP_NO_ERROR) { mStatusLightBrightness = static_cast(statusLightBrightness); - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded StatusLightBrightness as %d", mEndpointId, + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Loaded StatusLightBrightness as %d", mPath.mEndpointId, to_underlying(mStatusLightBrightness)); } else { ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Unable to load the StatusLightBrightness from the KVS. Defaulting to %d", - mEndpointId, to_underlying(mStatusLightBrightness)); + mPath.mEndpointId, to_underlying(mStatusLightBrightness)); } // Signal delegate that all persistent configuration attributes have been loaded. - mDelegate.PersistentAttributesLoadedCallback(); + CHIP_ERROR cbErr = mDelegate.PersistentAttributesLoadedCallback(); + if (cbErr != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: PersistentAttributesLoadedCallback() failed with error %" CHIP_ERROR_FORMAT, + mPath.mEndpointId, cbErr.Format()); + } } -CHIP_ERROR CameraAVStreamMgmtServer::StoreViewport(const Globals::Structs::ViewportStruct::Type & viewport) +CHIP_ERROR CameraAVStreamManagementCluster::StoreViewport(const Globals::Structs::ViewportStruct::Type & viewport) { uint8_t buffer[kViewportStructMaxSerializedSize]; MutableByteSpan bufferSpan(buffer); @@ -1595,18 +1617,18 @@ CHIP_ERROR CameraAVStreamMgmtServer::StoreViewport(const Globals::Structs::Viewp writer.Init(bufferSpan); ReturnErrorOnFailure(viewport.Encode(writer, TLV::AnonymousTag())); - auto path = ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::Viewport::Id); + auto path = ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::Viewport::Id); bufferSpan.reduce_size(writer.GetLengthWritten()); return GetSafeAttributePersistenceProvider()->SafeWriteValue(path, bufferSpan); } -CHIP_ERROR CameraAVStreamMgmtServer::LoadViewport(Globals::Structs::ViewportStruct::Type & viewport) +CHIP_ERROR CameraAVStreamManagementCluster::LoadViewport(Globals::Structs::ViewportStruct::Type & viewport) { uint8_t buffer[kViewportStructMaxSerializedSize]; MutableByteSpan bufferSpan(buffer); - auto path = ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::Viewport::Id); + auto path = ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::Viewport::Id); ReturnErrorOnFailure(GetSafeAttributePersistenceProvider()->SafeReadValue(path, bufferSpan)); TLV::TLVReader reader; @@ -1618,7 +1640,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::LoadViewport(Globals::Structs::ViewportStru return CHIP_NO_ERROR; } -CHIP_ERROR CameraAVStreamMgmtServer::StoreStreamUsagePriorities() +CHIP_ERROR CameraAVStreamManagementCluster::StoreStreamUsagePriorities() { uint8_t buffer[kStreamUsagePrioritiesTlvSize]; MutableByteSpan bufferSpan(buffer); @@ -1636,16 +1658,16 @@ CHIP_ERROR CameraAVStreamMgmtServer::StoreStreamUsagePriorities() bufferSpan.reduce_size(writer.GetLengthWritten()); - auto path = ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::StreamUsagePriorities::Id); + auto path = ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::StreamUsagePriorities::Id); return GetSafeAttributePersistenceProvider()->SafeWriteValue(path, bufferSpan); } -CHIP_ERROR CameraAVStreamMgmtServer::LoadStreamUsagePriorities() +CHIP_ERROR CameraAVStreamManagementCluster::LoadStreamUsagePriorities() { uint8_t buffer[kStreamUsagePrioritiesTlvSize]; MutableByteSpan bufferSpan(buffer); - auto path = ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, Attributes::StreamUsagePriorities::Id); + auto path = ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, Attributes::StreamUsagePriorities::Id); ReturnErrorOnFailure(GetSafeAttributePersistenceProvider()->SafeReadValue(path, bufferSpan)); TLV::TLVReader reader; @@ -1682,7 +1704,7 @@ struct StreamTraits using StreamStructType = VideoStreamStruct; static constexpr size_t kMaxSerializedSize = kMaxAllocatedVideoStreamsSerializedSize; static constexpr StreamType kStreamType = StreamType::kVideo; - static constexpr auto kStreamVectorMember = &CameraAVStreamMgmtServer::mAllocatedVideoStreams; + static constexpr auto kStreamVectorMember = &CameraAVStreamManagementCluster::mAllocatedVideoStreams; }; template <> @@ -1691,7 +1713,7 @@ struct StreamTraits using StreamStructType = AudioStreamStruct; static constexpr size_t kMaxSerializedSize = kMaxAllocatedAudioStreamsSerializedSize; static constexpr StreamType kStreamType = StreamType::kAudio; - static constexpr auto kStreamVectorMember = &CameraAVStreamMgmtServer::mAllocatedAudioStreams; + static constexpr auto kStreamVectorMember = &CameraAVStreamManagementCluster::mAllocatedAudioStreams; }; template <> @@ -1700,24 +1722,23 @@ struct StreamTraits using StreamStructType = SnapshotStreamStruct; static constexpr size_t kMaxSerializedSize = kMaxAllocatedSnapshotStreamsSerializedSize; static constexpr StreamType kStreamType = StreamType::kSnapshot; - static constexpr auto kStreamVectorMember = &CameraAVStreamMgmtServer::mAllocatedSnapshotStreams; + static constexpr auto kStreamVectorMember = &CameraAVStreamManagementCluster::mAllocatedSnapshotStreams; }; template -CHIP_ERROR CameraAVStreamMgmtServer::PersistAndNotify() +CHIP_ERROR CameraAVStreamManagementCluster::PersistAndNotify() { ReturnErrorAndLogOnFailure(StoreAllocatedStreams(), Zcl, - "CameraAVStreamMgmt[ep=%d]: Failed to persist allocated streams", mEndpointId); + "CameraAVStreamMgmt[ep=%d]: Failed to persist allocated streams", mPath.mEndpointId); - auto path = ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, TAttributeId); mDelegate.OnAttributeChanged(TAttributeId); - MatterReportingAttributeChangeCallback(path); + NotifyAttributeChanged(TAttributeId); return CHIP_NO_ERROR; } template -CHIP_ERROR CameraAVStreamMgmtServer::StoreAllocatedStreams() +CHIP_ERROR CameraAVStreamManagementCluster::StoreAllocatedStreams() { using Traits = StreamTraits; @@ -1738,7 +1759,7 @@ CHIP_ERROR CameraAVStreamMgmtServer::StoreAllocatedStreams() size_t len = writer.GetLengthWritten(); - auto path = ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, attributeId); + auto path = ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, attributeId); ReturnErrorOnFailure(GetAttributePersistenceProvider()->WriteValue(path, ByteSpan(buffer, len))); ChipLogProgress(Zcl, "Saved %u %s streams", static_cast(streams.size()), StreamTypeToString(Traits::kStreamType)); @@ -1746,14 +1767,14 @@ CHIP_ERROR CameraAVStreamMgmtServer::StoreAllocatedStreams() } template -CHIP_ERROR CameraAVStreamMgmtServer::LoadAllocatedStreams() +CHIP_ERROR CameraAVStreamManagementCluster::LoadAllocatedStreams() { using Traits = StreamTraits; uint8_t buffer[Traits::kMaxSerializedSize]; MutableByteSpan span(buffer); - auto path = ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, attributeId); + auto path = ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, attributeId); auto & streams = (*this).*Traits::kStreamVectorMember; CHIP_ERROR err = GetAttributePersistenceProvider()->ReadValue(path, span); @@ -1790,151 +1811,205 @@ CHIP_ERROR CameraAVStreamMgmtServer::LoadAllocatedStreams() return reader.VerifyEndOfContainer(); } -// CommandHandlerInterface -void CameraAVStreamMgmtServer::InvokeCommand(HandlerContext & handlerContext) +CHIP_ERROR CameraAVStreamManagementCluster::AcceptedCommands(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) { - switch (handlerContext.mRequestPath.mCommandId) + if (HasFeature(Feature::kAudio)) { - case Commands::VideoStreamAllocate::Id: - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Allocating Video Stream", mEndpointId); + ReturnErrorOnFailure(builder.AppendElements( + { Commands::AudioStreamAllocate::kMetadataEntry, Commands::AudioStreamDeallocate::kMetadataEntry })); + } - if (!HasFeature(Feature::kVideo)) - { - handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); - } - else - { - HandleCommand( - handlerContext, - [this](HandlerContext & ctx, const auto & commandData) { HandleVideoStreamAllocate(ctx, commandData); }); - } - return; + if (HasFeature(Feature::kVideo)) + { + ReturnErrorOnFailure(builder.AppendElements( + { Commands::VideoStreamAllocate::kMetadataEntry, Commands::VideoStreamDeallocate::kMetadataEntry })); + } - case Commands::VideoStreamModify::Id: - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Modifying Video Stream", mEndpointId); + if (HasFeature(Feature::kVideo) && (HasFeature(Feature::kWatermark) || HasFeature(Feature::kOnScreenDisplay))) + { + ReturnErrorOnFailure(builder.AppendElements({ Commands::VideoStreamModify::kMetadataEntry })); + } - // VideoStreamModify should have either the WMARK or OSD feature supported - VerifyOrReturn(HasFeature(Feature::kVideo) && (HasFeature(Feature::kWatermark) || HasFeature(Feature::kOnScreenDisplay)), - handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand)); + if (HasFeature(Feature::kSnapshot) && (HasFeature(Feature::kWatermark) || HasFeature(Feature::kOnScreenDisplay))) + { + ReturnErrorOnFailure(builder.AppendElements({ Commands::SnapshotStreamModify::kMetadataEntry })); + } - HandleCommand( - handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleVideoStreamModify(ctx, commandData); }); + if (HasFeature(Feature::kSnapshot)) + { + ReturnErrorOnFailure(builder.AppendElements({ Commands::SnapshotStreamAllocate::kMetadataEntry, + Commands::SnapshotStreamDeallocate::kMetadataEntry, + Commands::CaptureSnapshot::kMetadataEntry })); + } - return; + ReturnErrorOnFailure(builder.AppendElements({ Commands::SetStreamPriorities::kMetadataEntry })); - case Commands::VideoStreamDeallocate::Id: - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Deallocating Video Stream", mEndpointId); + return CHIP_NO_ERROR; +} - if (!HasFeature(Feature::kVideo)) - { - handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); - } - else - { - HandleCommand( - handlerContext, - [this](HandlerContext & ctx, const auto & commandData) { HandleVideoStreamDeallocate(ctx, commandData); }); - } - return; +CHIP_ERROR CameraAVStreamManagementCluster::GeneratedCommands(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) +{ + if (HasFeature(Feature::kAudio)) + { + ReturnErrorOnFailure(builder.AppendElements({ Commands::AudioStreamAllocateResponse::Id })); + } - case Commands::AudioStreamAllocate::Id: - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Allocating Audio Stream", mEndpointId); + if (HasFeature(Feature::kVideo)) + { + ReturnErrorOnFailure(builder.AppendElements({ Commands::VideoStreamAllocateResponse::Id })); + } - if (!HasFeature(Feature::kAudio)) - { - handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); - } - else - { - HandleCommand( - handlerContext, - [this](HandlerContext & ctx, const auto & commandData) { HandleAudioStreamAllocate(ctx, commandData); }); - } - return; + if (HasFeature(Feature::kSnapshot)) + { + ReturnErrorOnFailure( + builder.AppendElements({ Commands::SnapshotStreamAllocateResponse::Id, Commands::CaptureSnapshotResponse::Id })); + } - case Commands::AudioStreamDeallocate::Id: - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Deallocating Audio Stream", mEndpointId); + return CHIP_NO_ERROR; +} - if (!HasFeature(Feature::kAudio)) - { - handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); - } - else - { - HandleCommand( - handlerContext, - [this](HandlerContext & ctx, const auto & commandData) { HandleAudioStreamDeallocate(ctx, commandData); }); - } - return; +std::optional +CameraAVStreamManagementCluster::InvokeCommand(const DataModel::InvokeRequest & aRequest, TLV::TLVReader & aInputArgs, + CommandHandler * aHandler) +{ + switch (aRequest.path.mCommandId) + { + case Commands::VideoStreamAllocate::Id: { + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Allocating Video Stream", mPath.mEndpointId); - case Commands::SnapshotStreamAllocate::Id: - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Allocating Snapshot Stream", mEndpointId); + Commands::VideoStreamAllocate::DecodableType commandData; + ReturnErrorOnFailure(commandData.Decode(aInputArgs)); + return HandleVideoStreamAllocate(*aHandler, aRequest.path, commandData); + } - if (!HasFeature(Feature::kSnapshot)) - { - handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); - } - else - { - HandleCommand( - handlerContext, - [this](HandlerContext & ctx, const auto & commandData) { HandleSnapshotStreamAllocate(ctx, commandData); }); - } - return; + case Commands::VideoStreamModify::Id: { + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Modifying Video Stream", mPath.mEndpointId); - case Commands::SnapshotStreamModify::Id: - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Modifying Snapshot Stream", mEndpointId); + Commands::VideoStreamModify::DecodableType commandData; + ReturnErrorOnFailure(commandData.Decode(aInputArgs)); + return HandleVideoStreamModify(commandData); + } - // SnapshotStreamModify should have either the WMARK or OSD feature supported - VerifyOrReturn(HasFeature(Feature::kSnapshot) && (HasFeature(Feature::kWatermark) || HasFeature(Feature::kOnScreenDisplay)), - handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand)); + case Commands::VideoStreamDeallocate::Id: { + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Deallocating Video Stream", mPath.mEndpointId); - HandleCommand( - handlerContext, - [this](HandlerContext & ctx, const auto & commandData) { HandleSnapshotStreamModify(ctx, commandData); }); + Commands::VideoStreamDeallocate::DecodableType commandData; + ReturnErrorOnFailure(commandData.Decode(aInputArgs)); + return HandleVideoStreamDeallocate(commandData); + } - return; + case Commands::AudioStreamAllocate::Id: { + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Allocating Audio Stream", mPath.mEndpointId); - case Commands::SnapshotStreamDeallocate::Id: - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Deallocating Snapshot Stream", mEndpointId); + Commands::AudioStreamAllocate::DecodableType commandData; + ReturnErrorOnFailure(commandData.Decode(aInputArgs)); + return HandleAudioStreamAllocate(*aHandler, aRequest.path, commandData); + } - if (!HasFeature(Feature::kSnapshot)) - { - handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); - } - else - { - HandleCommand( - handlerContext, - [this](HandlerContext & ctx, const auto & commandData) { HandleSnapshotStreamDeallocate(ctx, commandData); }); - } - return; + case Commands::AudioStreamDeallocate::Id: { + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Deallocating Audio Stream", mPath.mEndpointId); - case Commands::SetStreamPriorities::Id: - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Set Stream Priorities", mEndpointId); - HandleCommand( - handlerContext, - [this](HandlerContext & ctx, const auto & commandData) { HandleSetStreamPriorities(ctx, commandData); }); - return; + Commands::AudioStreamDeallocate::DecodableType commandData; + ReturnErrorOnFailure(commandData.Decode(aInputArgs)); + return HandleAudioStreamDeallocate(commandData); + } - case Commands::CaptureSnapshot::Id: - ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Capture Snapshot image", mEndpointId); + case Commands::SnapshotStreamAllocate::Id: { + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Allocating Snapshot Stream", mPath.mEndpointId); - if (!HasFeature(Feature::kSnapshot)) - { - handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); - } - else - { - HandleCommand( - handlerContext, - [this](HandlerContext & ctx, const auto & commandData) { HandleCaptureSnapshot(ctx, commandData); }); - } - return; + Commands::SnapshotStreamAllocate::DecodableType commandData; + ReturnErrorOnFailure(commandData.Decode(aInputArgs)); + return HandleSnapshotStreamAllocate(*aHandler, aRequest.path, commandData); } + + case Commands::SnapshotStreamModify::Id: { + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Modifying Snapshot Stream", mPath.mEndpointId); + + Commands::SnapshotStreamModify::DecodableType commandData; + ReturnErrorOnFailure(commandData.Decode(aInputArgs)); + return HandleSnapshotStreamModify(commandData); + } + + case Commands::SnapshotStreamDeallocate::Id: { + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Deallocating Snapshot Stream", mPath.mEndpointId); + + Commands::SnapshotStreamDeallocate::DecodableType commandData; + ReturnErrorOnFailure(commandData.Decode(aInputArgs)); + return HandleSnapshotStreamDeallocate(commandData); + } + + case Commands::SetStreamPriorities::Id: { + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Set Stream Priorities", mPath.mEndpointId); + + Commands::SetStreamPriorities::DecodableType commandData; + ReturnErrorOnFailure(commandData.Decode(aInputArgs)); + return HandleSetStreamPriorities(commandData); + } + + case Commands::CaptureSnapshot::Id: { + ChipLogDetail(Zcl, "CameraAVStreamMgmt[ep=%d]: Capture Snapshot image", mPath.mEndpointId); + + Commands::CaptureSnapshot::DecodableType commandData; + ReturnErrorOnFailure(commandData.Decode(aInputArgs)); + return HandleCaptureSnapshot(*aHandler, aRequest.path, commandData); + } + } + return Status::UnsupportedCommand; +} + +CHIP_ERROR CameraAVStreamManagementCluster::Attributes(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) +{ + AttributeListBuilder listBuilder(builder); + + // Counts only via feature bits; other optionals via optional attribute set. + AttributeListBuilder::OptionalAttributeEntry optionalAttributes[] = { + { HasFeature(Feature::kVideo) || HasFeature(Feature::kSnapshot), Attributes::MaxConcurrentEncoders::kMetadataEntry }, + { HasFeature(Feature::kVideo) || HasFeature(Feature::kSnapshot), Attributes::MaxEncodedPixelRate::kMetadataEntry }, + { HasFeature(Feature::kVideo), VideoSensorParams::kMetadataEntry }, + { HasFeature(Feature::kNightVision), NightVisionUsesInfrared::kMetadataEntry }, + { HasFeature(Feature::kVideo), MinViewportResolution::kMetadataEntry }, + { HasFeature(Feature::kVideo), RateDistortionTradeOffPoints::kMetadataEntry }, + { HasFeature(Feature::kAudio), MicrophoneCapabilities::kMetadataEntry }, + { HasFeature(Feature::kSpeaker), SpeakerCapabilities::kMetadataEntry }, + { HasFeature(Feature::kSpeaker), TwoWayTalkSupport::kMetadataEntry }, + { HasFeature(Feature::kSnapshot), SnapshotCapabilities::kMetadataEntry }, + { HasFeature(Feature::kVideo), CurrentFrameRate::kMetadataEntry }, + { HasFeature(Feature::kHighDynamicRange), HDRModeEnabled::kMetadataEntry }, + { HasFeature(Feature::kVideo), AllocatedVideoStreams::kMetadataEntry }, + { HasFeature(Feature::kAudio), AllocatedAudioStreams::kMetadataEntry }, + { HasFeature(Feature::kSnapshot), AllocatedSnapshotStreams::kMetadataEntry }, + { HasFeature(Feature::kPrivacy), SoftRecordingPrivacyModeEnabled::kMetadataEntry }, + { HasFeature(Feature::kPrivacy), SoftLivestreamPrivacyModeEnabled::kMetadataEntry }, + { SupportsOptAttr(OptionalAttribute::kHardPrivacyModeOn), HardPrivacyModeOn::kMetadataEntry }, + { HasFeature(Feature::kNightVision), NightVision::kMetadataEntry }, + { SupportsOptAttr(OptionalAttribute::kNightVisionIllum), NightVisionIllum::kMetadataEntry }, + { HasFeature(Feature::kVideo), Viewport::kMetadataEntry }, + { HasFeature(Feature::kSpeaker), SpeakerMuted::kMetadataEntry }, + { HasFeature(Feature::kSpeaker), SpeakerVolumeLevel::kMetadataEntry }, + { HasFeature(Feature::kSpeaker), SpeakerMaxLevel::kMetadataEntry }, + { HasFeature(Feature::kSpeaker), SpeakerMinLevel::kMetadataEntry }, + { HasFeature(Feature::kAudio), MicrophoneMuted::kMetadataEntry }, + { HasFeature(Feature::kAudio), MicrophoneVolumeLevel::kMetadataEntry }, + { HasFeature(Feature::kAudio), MicrophoneMaxLevel::kMetadataEntry }, + { HasFeature(Feature::kAudio), MicrophoneMinLevel::kMetadataEntry }, + { SupportsOptAttr(OptionalAttribute::kMicrophoneAGCEnabled), MicrophoneAGCEnabled::kMetadataEntry }, + { SupportsOptAttr(OptionalAttribute::kImageRotation), ImageRotation::kMetadataEntry }, + { SupportsOptAttr(OptionalAttribute::kImageFlipHorizontal), ImageFlipHorizontal::kMetadataEntry }, + { SupportsOptAttr(OptionalAttribute::kImageFlipVertical), ImageFlipVertical::kMetadataEntry }, + { HasFeature(Feature::kVideo) && HasFeature(Feature::kLocalStorage), LocalVideoRecordingEnabled::kMetadataEntry }, + { HasFeature(Feature::kSnapshot) && HasFeature(Feature::kLocalStorage), LocalSnapshotRecordingEnabled::kMetadataEntry }, + { SupportsOptAttr(OptionalAttribute::kStatusLightEnabled), StatusLightEnabled::kMetadataEntry }, + { SupportsOptAttr(OptionalAttribute::kStatusLightBrightness), StatusLightBrightness::kMetadataEntry }, + }; + + return listBuilder.Append(Span(Attributes::kMandatoryMetadata), Span(optionalAttributes)); } -bool CameraAVStreamMgmtServer::StreamPrioritiesHasDuplicates(const std::vector & aStreamUsagePriorities) +bool CameraAVStreamManagementCluster::StreamPrioritiesHasDuplicates( + const std::vector & aStreamUsagePriorities) { std::set seenStreamUsages; @@ -1949,61 +2024,58 @@ bool CameraAVStreamMgmtServer::StreamPrioritiesHasDuplicates(const std::vector +CameraAVStreamManagementCluster::HandleVideoStreamAllocate(CommandHandler & handler, const ConcreteCommandPath & commandPath, + const Commands::VideoStreamAllocate::DecodableType & commandData) { Status status = Status::Success; - Commands::VideoStreamAllocateResponse::Type response; uint16_t videoStreamID = 0; // If Watermark feature is supported, then command should have the // isWaterMarkEnabled param. Or, if it is not supported, then command should // not have the param. - VerifyOrReturn((HasFeature(Feature::kWatermark) == commandData.watermarkEnabled.HasValue()), - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand)); + VerifyOrReturnError((HasFeature(Feature::kWatermark) == commandData.watermarkEnabled.HasValue()), Status::InvalidCommand); // If OSD feature is supported, then command should have the // isOSDEnabled param. Or, if it is not supported, then command should // not have the param. - VerifyOrReturn((HasFeature(Feature::kOnScreenDisplay) == commandData.OSDEnabled.HasValue()), - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand)); - - VerifyOrReturn(commandData.streamUsage == Globals::StreamUsageEnum::kRecording || - commandData.streamUsage == Globals::StreamUsageEnum::kAnalysis || - commandData.streamUsage == Globals::StreamUsageEnum::kLiveView, - { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid stream usage", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - }); - - VerifyOrReturn(commandData.videoCodec != VideoCodecEnum::kUnknownEnumValue, { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid video codec", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - }); + VerifyOrReturnError((HasFeature(Feature::kOnScreenDisplay) == commandData.OSDEnabled.HasValue()), Status::InvalidCommand); + + if (!(commandData.streamUsage == Globals::StreamUsageEnum::kRecording || + commandData.streamUsage == Globals::StreamUsageEnum::kAnalysis || + commandData.streamUsage == Globals::StreamUsageEnum::kLiveView)) + { + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid stream usage", mPath.mEndpointId); + return Status::ConstraintError; + } + + if (commandData.videoCodec == VideoCodecEnum::kUnknownEnumValue) + { + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid video codec", mPath.mEndpointId); + return Status::ConstraintError; + } - VerifyOrReturn(commandData.minFrameRate >= 1 && commandData.minFrameRate <= commandData.maxFrameRate && - commandData.maxFrameRate >= 1, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); + VerifyOrReturnError(commandData.minFrameRate >= 1 && commandData.minFrameRate <= commandData.maxFrameRate && + commandData.maxFrameRate >= 1, + Status::ConstraintError); - VerifyOrReturn(commandData.minResolution.width >= 1 && commandData.minResolution.height >= 1, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); + VerifyOrReturnError(commandData.minResolution.width >= 1 && commandData.minResolution.height >= 1, Status::ConstraintError); - VerifyOrReturn(commandData.maxResolution.width >= 1 && commandData.maxResolution.height >= 1, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); + VerifyOrReturnError(commandData.maxResolution.width >= 1 && commandData.maxResolution.height >= 1, Status::ConstraintError); - VerifyOrReturn(commandData.minBitRate >= 1 && commandData.minBitRate <= commandData.maxBitRate && commandData.maxBitRate >= 1, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); + VerifyOrReturnError(commandData.minBitRate >= 1 && commandData.minBitRate <= commandData.maxBitRate && + commandData.maxBitRate >= 1, + Status::ConstraintError); - VerifyOrReturn(commandData.keyFrameInterval <= kMaxKeyFrameIntervalMaxValue, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); + VerifyOrReturnError(commandData.keyFrameInterval <= kMaxKeyFrameIntervalMaxValue, Status::ConstraintError); bool streamUsageSupported = std::find_if(mStreamUsagePriorities.begin(), mStreamUsagePriorities.end(), [&commandData](const Globals::StreamUsageEnum & entry) { return entry == commandData.streamUsage; }) != mStreamUsagePriorities.end(); - VerifyOrReturn(streamUsageSupported, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidInState)); + VerifyOrReturnError(streamUsageSupported, Status::InvalidInState); VideoStreamStruct videoStreamArgs; videoStreamArgs.videoStreamID = 0; @@ -2035,7 +2107,7 @@ void CameraAVStreamMgmtServer::HandleVideoStreamAllocate(HandlerContext & ctx, { // Add the allocated videostream object in the AllocatedVideoStreams list. videoStreamArgs.videoStreamID = videoStreamID; - AddVideoStream(videoStreamArgs); + TEMPORARY_RETURN_IGNORED AddVideoStream(videoStreamArgs); // Call delegate with the allocated stream parameters and new allocation action mDelegate.OnVideoStreamAllocated(videoStreamArgs, StreamAllocationAction::kNewAllocation); @@ -2046,24 +2118,26 @@ void CameraAVStreamMgmtServer::HandleVideoStreamAllocate(HandlerContext & ctx, VideoStreamStruct & videoStreamToUpdate = *it; // Reusing the existing stream. Update range parameters and check if they were modified - UpdateVideoStreamRangeParams(videoStreamToUpdate, videoStreamArgs, wasModified); + TEMPORARY_RETURN_IGNORED UpdateVideoStreamRangeParams(videoStreamToUpdate, videoStreamArgs, wasModified); // Call delegate with the final updated stream parameters and appropriate action mDelegate.OnVideoStreamAllocated(videoStreamToUpdate, wasModified ? StreamAllocationAction::kModification : StreamAllocationAction::kReuse); } + Commands::VideoStreamAllocateResponse::Type response; + response.videoStreamID = videoStreamID; - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); - } - else - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); + handler.AddResponse(commandPath, response); + + return std::nullopt; } + + return status; } -void CameraAVStreamMgmtServer::HandleVideoStreamModify(HandlerContext & ctx, - const Commands::VideoStreamModify::DecodableType & commandData) +std::optional +CameraAVStreamManagementCluster::HandleVideoStreamModify(const Commands::VideoStreamModify::DecodableType & commandData) { auto & isWaterMarkEnabled = commandData.watermarkEnabled; auto & isOSDEnabled = commandData.OSDEnabled; @@ -2072,111 +2146,113 @@ void CameraAVStreamMgmtServer::HandleVideoStreamModify(HandlerContext & ctx, // If WatermarkEnabled is provided then the Watermark feature has to be supported if (commandData.watermarkEnabled.HasValue()) { - VerifyOrReturn(HasFeature(Feature::kWatermark), { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: WatermarkEnabled provided but Watermark Feature not set", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - }); + if (!HasFeature(Feature::kWatermark)) + { + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: WatermarkEnabled provided but Watermark Feature not set", + mPath.mEndpointId); + return Status::InvalidCommand; + } } // If OSDEnabled is provided then the OSD feature has to be supported if (commandData.OSDEnabled.HasValue()) { - VerifyOrReturn(HasFeature(Feature::kOnScreenDisplay), { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: OSDEnabled provided but OSD Feature not set", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - }); + if (!HasFeature(Feature::kOnScreenDisplay)) + { + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: OSDEnabled provided but OSD Feature not set", mPath.mEndpointId); + return Status::InvalidCommand; + } } // One of WatermarkEnabled or OSDEnabled has to be present - VerifyOrReturn(commandData.watermarkEnabled.HasValue() || commandData.OSDEnabled.HasValue(), { + if (!(commandData.watermarkEnabled.HasValue() || commandData.OSDEnabled.HasValue())) + { ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: One of WatermarkEnabled or OSDEnabled must be provided in VideoStreamModify", - mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - }); + mPath.mEndpointId); + return Status::InvalidCommand; + } - if (!ValidateVideoStreamForModifyOrDeallocate(videoStreamID, ctx, /* isDeallocate = */ false)) + Status status = ValidateVideoStreamForModifyOrDeallocate(videoStreamID, /* isDeallocate = */ false); + if (status != Status::Success) { - return; + return status; } // Call the delegate - Status status = mDelegate.VideoStreamModify(videoStreamID, isWaterMarkEnabled, isOSDEnabled); + status = mDelegate.VideoStreamModify(videoStreamID, isWaterMarkEnabled, isOSDEnabled); if (status == Status::Success) { ModifyVideoStream(videoStreamID, isWaterMarkEnabled, isOSDEnabled); } - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); + return status; } -void CameraAVStreamMgmtServer::HandleVideoStreamDeallocate(HandlerContext & ctx, - const Commands::VideoStreamDeallocate::DecodableType & commandData) +std::optional +CameraAVStreamManagementCluster::HandleVideoStreamDeallocate(const Commands::VideoStreamDeallocate::DecodableType & commandData) { auto & videoStreamID = commandData.videoStreamID; - if (!ValidateVideoStreamForModifyOrDeallocate(videoStreamID, ctx, /* isDeallocate = */ true)) + Status status = ValidateVideoStreamForModifyOrDeallocate(videoStreamID, /* isDeallocate = */ true); + if (status != Status::Success) { - return; + return status; } // Call the delegate - Status status = mDelegate.VideoStreamDeallocate(videoStreamID); + status = mDelegate.VideoStreamDeallocate(videoStreamID); if (status == Status::Success) { - RemoveVideoStream(videoStreamID); + TEMPORARY_RETURN_IGNORED RemoveVideoStream(videoStreamID); } - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); + return status; } -void CameraAVStreamMgmtServer::HandleAudioStreamAllocate(HandlerContext & ctx, - const Commands::AudioStreamAllocate::DecodableType & commandData) +std::optional +CameraAVStreamManagementCluster::HandleAudioStreamAllocate(CommandHandler & handler, const ConcreteCommandPath & commandPath, + const Commands::AudioStreamAllocate::DecodableType & commandData) { - - Commands::AudioStreamAllocateResponse::Type response; uint16_t audioStreamID = 0; - VerifyOrReturn(commandData.streamUsage == Globals::StreamUsageEnum::kRecording || - commandData.streamUsage == Globals::StreamUsageEnum::kAnalysis || - commandData.streamUsage == Globals::StreamUsageEnum::kLiveView, - { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid stream usage", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - }); - - VerifyOrReturn(commandData.audioCodec != AudioCodecEnum::kUnknownEnumValue, { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid audio codec", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - }); + if (!(commandData.streamUsage == Globals::StreamUsageEnum::kRecording || + commandData.streamUsage == Globals::StreamUsageEnum::kAnalysis || + commandData.streamUsage == Globals::StreamUsageEnum::kLiveView)) + { + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid stream usage", mPath.mEndpointId); + return Status::ConstraintError; + } - VerifyOrReturn(commandData.channelCount >= 1 && commandData.channelCount <= kMaxChannelCount, { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid channel count", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - }); + if (commandData.audioCodec == AudioCodecEnum::kUnknownEnumValue) + { + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid audio codec", mPath.mEndpointId); + return Status::ConstraintError; + } - VerifyOrReturn(commandData.sampleRate > 0, { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid sampleRate", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - }); + if (!(commandData.channelCount >= 1 && commandData.channelCount <= kMaxChannelCount)) + { + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid channel count", mPath.mEndpointId); + return Status::ConstraintError; + } - VerifyOrReturn(commandData.bitRate > 0, { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid bitRate", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - }); + VerifyOrReturnError(commandData.sampleRate > 0, Status::ConstraintError); - VerifyOrReturn(IsBitDepthValid(commandData.bitDepth), { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid bitDepth", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - }); + VerifyOrReturnError(commandData.bitRate > 0, Status::ConstraintError); + + if (!IsBitDepthValid(commandData.bitDepth)) + { + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid bitDepth", mPath.mEndpointId); + return Status::ConstraintError; + } bool streamUsageSupported = std::find_if(mStreamUsagePriorities.begin(), mStreamUsagePriorities.end(), [&commandData](const Globals::StreamUsageEnum & entry) { return entry == commandData.streamUsage; }) != mStreamUsagePriorities.end(); - VerifyOrReturn(streamUsageSupported, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidInState)); + VerifyOrReturnError(streamUsageSupported, Status::InvalidInState); AudioStreamStruct audioStreamArgs; audioStreamArgs.audioStreamID = 0; @@ -2193,8 +2269,7 @@ void CameraAVStreamMgmtServer::HandleAudioStreamAllocate(HandlerContext & ctx, if (status != Status::Success) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); - return; + return status; } // Check if the streamID matches an existing one in the @@ -2207,75 +2282,80 @@ void CameraAVStreamMgmtServer::HandleAudioStreamAllocate(HandlerContext & ctx, { // Add the allocated audiostream object in the AllocatedAudioStreams list. audioStreamArgs.audioStreamID = audioStreamID; - AddAudioStream(audioStreamArgs); + TEMPORARY_RETURN_IGNORED AddAudioStream(audioStreamArgs); } + Commands::AudioStreamAllocateResponse::Type response; + response.audioStreamID = audioStreamID; - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + handler.AddResponse(commandPath, response); + + return std::nullopt; } -void CameraAVStreamMgmtServer::HandleAudioStreamDeallocate(HandlerContext & ctx, - const Commands::AudioStreamDeallocate::DecodableType & commandData) +std::optional +CameraAVStreamManagementCluster::HandleAudioStreamDeallocate(const Commands::AudioStreamDeallocate::DecodableType & commandData) { auto & audioStreamID = commandData.audioStreamID; - if (!ValidateAudioStreamForDeallocate(audioStreamID, ctx)) + Status status = ValidateAudioStreamForDeallocate(audioStreamID); + + if (status != Status::Success) { - return; + return status; } // Call the delegate - Status status = mDelegate.AudioStreamDeallocate(audioStreamID); + status = mDelegate.AudioStreamDeallocate(audioStreamID); if (status == Status::Success) { - RemoveAudioStream(audioStreamID); + TEMPORARY_RETURN_IGNORED RemoveAudioStream(audioStreamID); } - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); + return status; } -void CameraAVStreamMgmtServer::HandleSnapshotStreamAllocate(HandlerContext & ctx, - const Commands::SnapshotStreamAllocate::DecodableType & commandData) +std::optional +CameraAVStreamManagementCluster::HandleSnapshotStreamAllocate(CommandHandler & handler, const ConcreteCommandPath & commandPath, + const Commands::SnapshotStreamAllocate::DecodableType & commandData) { - Commands::SnapshotStreamAllocateResponse::Type response; uint16_t snapshotStreamID = 0; // If Watermark feature is supported, then command should have the // isWaterMarkEnabled param. Or, if it is not supported, then command should // not have the param. - VerifyOrReturn((HasFeature(Feature::kWatermark) == commandData.watermarkEnabled.HasValue()), - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand)); + VerifyOrReturnError((HasFeature(Feature::kWatermark) == commandData.watermarkEnabled.HasValue()), Status::InvalidCommand); // If OSD feature is supported, then command should have the // isOSDEnabled param. Or, if it is not supported, then command should // not have the param. - VerifyOrReturn((HasFeature(Feature::kOnScreenDisplay) == commandData.OSDEnabled.HasValue()), - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand)); + VerifyOrReturnError((HasFeature(Feature::kOnScreenDisplay) == commandData.OSDEnabled.HasValue()), Status::InvalidCommand); - VerifyOrReturn(commandData.imageCodec != ImageCodecEnum::kUnknownEnumValue, { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid image codec", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - }); + if (commandData.imageCodec == ImageCodecEnum::kUnknownEnumValue) + { + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid image codec", mPath.mEndpointId); + return Status::ConstraintError; + } - VerifyOrReturn(commandData.maxFrameRate > 0, { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid maxFrameRate", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - }); + if (commandData.maxFrameRate <= 0) + { + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid maxFrameRate", mPath.mEndpointId); + return Status::ConstraintError; + } - VerifyOrReturn(commandData.minResolution.width >= 1 && commandData.minResolution.height >= 1, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); + VerifyOrReturnError(commandData.minResolution.width >= 1 && commandData.minResolution.height >= 1, Status::ConstraintError); - VerifyOrReturn(commandData.maxResolution.width >= 1 && commandData.maxResolution.height >= 1, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); + VerifyOrReturnError(commandData.maxResolution.width >= 1 && commandData.maxResolution.height >= 1, Status::ConstraintError); - VerifyOrReturn(commandData.quality > 0 && commandData.quality <= kMaxImageQualityMetric, { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid image quality", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - }); + if (!(commandData.quality > 0 && commandData.quality <= kMaxImageQualityMetric)) + { + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Invalid image quality", mPath.mEndpointId); + return Status::ConstraintError; + } - CameraAVStreamMgmtDelegate::SnapshotStreamAllocateArgs snapshotStreamArgs; + CameraAVStreamManagementDelegate::SnapshotStreamAllocateArgs snapshotStreamArgs; snapshotStreamArgs.imageCodec = commandData.imageCodec; snapshotStreamArgs.maxFrameRate = commandData.maxFrameRate; snapshotStreamArgs.minResolution = commandData.minResolution; @@ -2309,8 +2389,7 @@ void CameraAVStreamMgmtServer::HandleSnapshotStreamAllocate(HandlerContext & ctx else { // Stream allocation request does not match any SnapshotCapabilities struct - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::DynamicConstraintError); - return; + return Status::DynamicConstraintError; } // Call the delegate @@ -2318,8 +2397,7 @@ void CameraAVStreamMgmtServer::HandleSnapshotStreamAllocate(HandlerContext & ctx if (status != Status::Success) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); - return; + return status; } // Check if the streamID matches an existing one in the @@ -2344,21 +2422,24 @@ void CameraAVStreamMgmtServer::HandleSnapshotStreamAllocate(HandlerContext & ctx allocatedSnapshotStream.watermarkEnabled = snapshotStreamArgs.watermarkEnabled; allocatedSnapshotStream.OSDEnabled = snapshotStreamArgs.OSDEnabled; - AddSnapshotStream(allocatedSnapshotStream); + TEMPORARY_RETURN_IGNORED AddSnapshotStream(allocatedSnapshotStream); } else { SnapshotStreamStruct & snapshotStreamToUpdate = *it; // Reusing the existing stream. Update range parameters - UpdateSnapshotStreamRangeParams(snapshotStreamToUpdate, snapshotStreamArgs); + TEMPORARY_RETURN_IGNORED UpdateSnapshotStreamRangeParams(snapshotStreamToUpdate, snapshotStreamArgs); } + Commands::SnapshotStreamAllocateResponse::Type response; response.snapshotStreamID = snapshotStreamID; - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + handler.AddResponse(commandPath, response); + + return std::nullopt; } -void CameraAVStreamMgmtServer::HandleSnapshotStreamModify(HandlerContext & ctx, - const Commands::SnapshotStreamModify::DecodableType & commandData) +std::optional +CameraAVStreamManagementCluster::HandleSnapshotStreamModify(const Commands::SnapshotStreamModify::DecodableType & commandData) { Status status = Status::Success; auto & isWaterMarkEnabled = commandData.watermarkEnabled; @@ -2368,32 +2449,37 @@ void CameraAVStreamMgmtServer::HandleSnapshotStreamModify(HandlerContext & ctx, // If WatermarkEnabled is provided then the Watermark feature has to be supported if (commandData.watermarkEnabled.HasValue()) { - VerifyOrReturn(HasFeature(Feature::kWatermark), { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: WatermarkEnabled provided but Watermark Feature not set", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - }); + if (!HasFeature(Feature::kWatermark)) + { + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: WatermarkEnabled provided but Watermark Feature not set", + mPath.mEndpointId); + return Status::InvalidCommand; + } } // If OSDEnabled is provided then the OSD feature has to be supported if (commandData.OSDEnabled.HasValue()) { - VerifyOrReturn(HasFeature(Feature::kOnScreenDisplay), { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: OSDEnabled provided but OSD Feature not set", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - }); + if (!HasFeature(Feature::kOnScreenDisplay)) + { + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: OSDEnabled provided but OSD Feature not set", mPath.mEndpointId); + return Status::InvalidCommand; + } } // One of WatermarkEnabled or OSDEnabled has to be present - VerifyOrReturn(commandData.watermarkEnabled.HasValue() || commandData.OSDEnabled.HasValue(), { + if (!(commandData.watermarkEnabled.HasValue() || commandData.OSDEnabled.HasValue())) + { ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: One of WatermarkEnabled or OSDEnabled must be provided in SnapshotStreamModify", - mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - }); + mPath.mEndpointId); + return Status::InvalidCommand; + } - if (!ValidateSnapshotStreamForModifyOrDeallocate(snapshotStreamID, ctx, /* isDeallocate = */ false)) + status = ValidateSnapshotStreamForModifyOrDeallocate(snapshotStreamID, /* isDeallocate = */ false); + if (status != Status::Success) { - return; + return status; } status = mDelegate.SnapshotStreamModify(snapshotStreamID, isWaterMarkEnabled, isOSDEnabled); @@ -2403,186 +2489,181 @@ void CameraAVStreamMgmtServer::HandleSnapshotStreamModify(HandlerContext & ctx, ModifySnapshotStream(snapshotStreamID, isWaterMarkEnabled, isOSDEnabled); } - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); + return status; } -void CameraAVStreamMgmtServer::HandleSnapshotStreamDeallocate(HandlerContext & ctx, - const Commands::SnapshotStreamDeallocate::DecodableType & commandData) +std::optional CameraAVStreamManagementCluster::HandleSnapshotStreamDeallocate( + const Commands::SnapshotStreamDeallocate::DecodableType & commandData) { auto & snapshotStreamID = commandData.snapshotStreamID; - if (!ValidateSnapshotStreamForModifyOrDeallocate(snapshotStreamID, ctx, /* isDeallocate = */ true)) + Status status = ValidateSnapshotStreamForModifyOrDeallocate(snapshotStreamID, /* isDeallocate = */ true); + if (status != Status::Success) { - return; + return status; } // Call the delegate - Status status = mDelegate.SnapshotStreamDeallocate(snapshotStreamID); + status = mDelegate.SnapshotStreamDeallocate(snapshotStreamID); if (status == Status::Success) { - RemoveSnapshotStream(snapshotStreamID); + TEMPORARY_RETURN_IGNORED RemoveSnapshotStream(snapshotStreamID); } - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); + return status; } -void CameraAVStreamMgmtServer::HandleSetStreamPriorities(HandlerContext & ctx, - const Commands::SetStreamPriorities::DecodableType & commandData) +std::optional +CameraAVStreamManagementCluster::HandleSetStreamPriorities(const Commands::SetStreamPriorities::DecodableType & commandData) { - auto & streamPriorities = commandData.streamPriorities; std::vector streamUsagePriorities; auto iter = streamPriorities.begin(); // If any video, audio or snapshot streams exist fail the command. - VerifyOrReturn(mAllocatedVideoStreams.empty() && mAllocatedAudioStreams.empty() && mAllocatedSnapshotStreams.empty(), - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidInState)); + VerifyOrReturnError(mAllocatedVideoStreams.empty() && mAllocatedAudioStreams.empty() && mAllocatedSnapshotStreams.empty(), + Status::InvalidInState); while (iter.Next()) { auto & streamUsage = iter.GetValue(); if (streamUsage == Globals::StreamUsageEnum::kUnknownEnumValue) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - return; + return Status::InvalidCommand; } // If any requested value is not found in SupportedStreamUsages, // return DynamicConstraintError. auto it = std::find(mSupportedStreamUsages.begin(), mSupportedStreamUsages.end(), streamUsage); - VerifyOrReturn(it != mSupportedStreamUsages.end(), - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::DynamicConstraintError)); + VerifyOrReturnError(it != mSupportedStreamUsages.end(), Status::DynamicConstraintError); streamUsagePriorities.push_back(streamUsage); } if (iter.GetStatus() != CHIP_NO_ERROR) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - return; + return Status::InvalidCommand; } // If there are duplicate stream usages in StreamPriorities, // return AlreadyExists - VerifyOrReturn(!StreamPrioritiesHasDuplicates(streamUsagePriorities), - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::AlreadyExists)); + VerifyOrReturnError(!StreamPrioritiesHasDuplicates(streamUsagePriorities), Status::AlreadyExists); CHIP_ERROR err = SetStreamUsagePriorities(streamUsagePriorities); if (err != CHIP_NO_ERROR) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); - return; + return Status::Failure; } mDelegate.OnStreamUsagePrioritiesChanged(); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Success); + return Status::Success; } -void CameraAVStreamMgmtServer::HandleCaptureSnapshot(HandlerContext & ctx, - const Commands::CaptureSnapshot::DecodableType & commandData) +std::optional +CameraAVStreamManagementCluster::HandleCaptureSnapshot(CommandHandler & handler, const ConcreteCommandPath & commandPath, + const Commands::CaptureSnapshot::DecodableType & commandData) { - - Commands::CaptureSnapshotResponse::Type response; auto & snapshotStreamID = commandData.snapshotStreamID; auto & requestedResolution = commandData.requestedResolution; ImageSnapshot image; - if (!CheckSnapshotStreamsAvailability(ctx)) + if (!CheckSnapshotStreamsAvailability()) { - return; + return Status::NotFound; } if (!snapshotStreamID.IsNull()) { - if (!ValidateSnapshotStreamId(snapshotStreamID, ctx)) + if (!ValidateSnapshotStreamId(snapshotStreamID)) { - return; + return Status::NotFound; } } - VerifyOrReturn(commandData.requestedResolution.width >= 1 && commandData.requestedResolution.height >= 1, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); + VerifyOrReturnError(commandData.requestedResolution.width >= 1 && commandData.requestedResolution.height >= 1, + Status::ConstraintError); // If SoftLivestreamPrivacyModeEnabled or HardPrivacyModeOn, return // InvalidInState. - VerifyOrReturn(!mSoftLivestreamPrivacyModeEnabled && !mHardPrivacyModeOn, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidInState)); + VerifyOrReturnError(!mSoftLivestreamPrivacyModeEnabled && !mHardPrivacyModeOn, Status::InvalidInState); // Call the delegate Status status = mDelegate.CaptureSnapshot(snapshotStreamID, requestedResolution, image); if (status != Status::Success) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); - return; + return status; } if (image.data.size() > kMaxSnapshotImageSize) { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Snapshot image file size(%lu) exceeded limit %lu", mEndpointId, + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: Snapshot image file size(%lu) exceeded limit %lu", mPath.mEndpointId, static_cast(image.data.size()), static_cast(kMaxSnapshotImageSize)); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ResourceExhausted); - return; + return Status::ResourceExhausted; } + // Build and send the response + Commands::CaptureSnapshotResponse::Type response; + // Populate the response response.data = ByteSpan(image.data.data(), image.data.size()); response.resolution = image.imageRes; response.imageCodec = image.imageCodec; - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + handler.AddResponse(commandPath, response); + + return std::nullopt; } -bool CameraAVStreamMgmtServer::CheckSnapshotStreamsAvailability(HandlerContext & ctx) +bool CameraAVStreamManagementCluster::CheckSnapshotStreamsAvailability() { if (mAllocatedSnapshotStreams.empty()) { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: No snapshot streams are allocated", mEndpointId); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: No snapshot streams are allocated", mPath.mEndpointId); return false; } return true; } -bool CameraAVStreamMgmtServer::ValidateSnapshotStreamId(const DataModel::Nullable & snapshotStreamID, - HandlerContext & ctx) +bool CameraAVStreamManagementCluster::ValidateSnapshotStreamId(const DataModel::Nullable & snapshotStreamID) { auto found = std::find_if(mAllocatedSnapshotStreams.begin(), mAllocatedSnapshotStreams.end(), [&](const SnapshotStreamStruct & s) { return s.snapshotStreamID == snapshotStreamID.Value(); }); if (found == mAllocatedSnapshotStreams.end()) { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: No snapshot stream exist by id %d", mEndpointId, snapshotStreamID.Value()); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: No snapshot stream exist by id %d", mPath.mEndpointId, + snapshotStreamID.Value()); return false; } return true; } -bool CameraAVStreamMgmtServer::ValidateVideoStreamForModifyOrDeallocate(const uint16_t videoStreamID, HandlerContext & ctx, - bool isDeallocate) +Protocols::InteractionModel::Status +CameraAVStreamManagementCluster::ValidateVideoStreamForModifyOrDeallocate(const uint16_t videoStreamID, bool isDeallocate) { return ValidateStreamForModifyOrDeallocateImpl( - mAllocatedVideoStreams, videoStreamID, ctx, StreamType::kVideo, [](const VideoStreamStruct & s) { return s.videoStreamID; }, + mAllocatedVideoStreams, videoStreamID, StreamType::kVideo, [](const VideoStreamStruct & s) { return s.videoStreamID; }, isDeallocate); } -bool CameraAVStreamMgmtServer::ValidateAudioStreamForDeallocate(const uint16_t audioStreamID, HandlerContext & ctx) +Protocols::InteractionModel::Status CameraAVStreamManagementCluster::ValidateAudioStreamForDeallocate(const uint16_t audioStreamID) { return ValidateStreamForModifyOrDeallocateImpl( - mAllocatedAudioStreams, audioStreamID, ctx, StreamType::kAudio, [](const AudioStreamStruct & s) { return s.audioStreamID; }, + mAllocatedAudioStreams, audioStreamID, StreamType::kAudio, [](const AudioStreamStruct & s) { return s.audioStreamID; }, /* isDeallocate = */ true); } -bool CameraAVStreamMgmtServer::ValidateSnapshotStreamForModifyOrDeallocate(const uint16_t snapshotStreamID, HandlerContext & ctx, - bool isDeallocate) +Protocols::InteractionModel::Status +CameraAVStreamManagementCluster::ValidateSnapshotStreamForModifyOrDeallocate(const uint16_t snapshotStreamID, bool isDeallocate) { return ValidateStreamForModifyOrDeallocateImpl( - mAllocatedSnapshotStreams, snapshotStreamID, ctx, StreamType::kSnapshot, + mAllocatedSnapshotStreams, snapshotStreamID, StreamType::kSnapshot, [](const SnapshotStreamStruct & s) { return s.snapshotStreamID; }, isDeallocate); } -bool CameraAVStreamMgmtServer::IsResourceAvailableForStreamAllocation(uint32_t candidateEncodedPixelRate, bool encoderRequired) +bool CameraAVStreamManagementCluster::IsResourceAvailableForStreamAllocation(uint32_t candidateEncodedPixelRate, + bool encoderRequired) { uint64_t totalEncodedPixelRate = candidateEncodedPixelRate; uint16_t totalEncodersRequired = encoderRequired ? 1 : 0; @@ -2626,11 +2707,3 @@ bool CameraAVStreamMgmtServer::IsResourceAvailableForStreamAllocation(uint32_t c } // namespace Clusters } // namespace app } // namespace chip - -/** @brief Camera AV Stream Management Cluster Server Init - * - * Server Init - * - */ -void MatterCameraAvStreamManagementPluginServerInitCallback() {} -void MatterCameraAvStreamManagementPluginServerShutdownCallback() {} diff --git a/src/app/clusters/camera-av-stream-management-server/camera-av-stream-management-server.h b/src/app/clusters/camera-av-stream-management-server/CameraAVStreamManagementCluster.h similarity index 82% rename from src/app/clusters/camera-av-stream-management-server/camera-av-stream-management-server.h rename to src/app/clusters/camera-av-stream-management-server/CameraAVStreamManagementCluster.h index 03c43aeb4d6..b1e36a4c138 100644 --- a/src/app/clusters/camera-av-stream-management-server/camera-av-stream-management-server.h +++ b/src/app/clusters/camera-av-stream-management-server/CameraAVStreamManagementCluster.h @@ -15,14 +15,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #pragma once -#include -#include -#include #include #include +#include +#include +#include #include #include @@ -144,7 +143,7 @@ enum class StreamType template struct StreamTraits; -class CameraAVStreamMgmtServer; +class CameraAVStreamManagementCluster; // ImageSnapshot response data for a CaptureSnapshot command. struct ImageSnapshot @@ -158,12 +157,12 @@ struct ImageSnapshot * Defines interfaces for implementing application-specific logic for various aspects of the CameraAvStreamManagement Cluster. * Specifically, it defines interfaces for the command handling and loading of the allocated streams. */ -class CameraAVStreamMgmtDelegate +class CameraAVStreamManagementDelegate { public: - CameraAVStreamMgmtDelegate() = default; + CameraAVStreamManagementDelegate() = default; - virtual ~CameraAVStreamMgmtDelegate() = default; + virtual ~CameraAVStreamManagementDelegate() = default; /** * @brief Handle Command Delegate for Video stream allocation with the provided parameter list. @@ -331,23 +330,11 @@ class CameraAVStreamMgmtDelegate */ virtual CHIP_ERROR PersistentAttributesLoadedCallback() = 0; - /** - * @brief Called by transports when they start using the corresponding audio and video streams. - * - */ - virtual CHIP_ERROR OnTransportAcquireAudioVideoStreams(uint16_t audioStreamID, uint16_t videoStreamID) = 0; - - /** - * @brief Called by transports when they release the corresponding audio and video streams. - * - */ - virtual CHIP_ERROR OnTransportReleaseAudioVideoStreams(uint16_t audioStreamID, uint16_t videoStreamID) = 0; - /** * @brief Provides read-only access to the list of currently allocated video streams. * This allows other components (like PushAVStreamTransportManager) to query * allocated stream parameters (e.g., for bandwidth calculation) without directly - * accessing the CameraAVStreamMgmtServer instance. + * accessing the CameraAVStreamManagementCluster instance. * * @return A const reference to the vector of allocated video stream structures. */ @@ -357,31 +344,32 @@ class CameraAVStreamMgmtDelegate * @brief Provides read-only access to the list of currently allocated audio streams. * This allows other components (like PushAVStreamTransportManager) to query * allocated stream parameters (e.g., for bandwidth calculation) without directly - * accessing the CameraAVStreamMgmtServer instance. + * accessing the CameraAVStreamManagementCluster instance. * * @return A const reference to the vector of allocated audio stream structures. */ virtual const std::vector & GetAllocatedAudioStreams() const = 0; private: - friend class CameraAVStreamMgmtServer; + friend class CameraAVStreamManagementCluster; - CameraAVStreamMgmtServer * mCameraAVStreamMgmtServer = nullptr; + CameraAVStreamManagementCluster * mCameraAVStreamManagementCluster = nullptr; /** * This method is used by the SDK to ensure the delegate points to the server instance it's associated with. * When a server instance is created or destroyed, this method will be called to set and clear, respectively, * the pointer to the server instance. * - * @param aCameraAVStreamMgmtServer A pointer to the CameraAVStreamMgmtServer object related to this delegate object. + * @param aCameraAVStreamManagementCluster A pointer to the CameraAVStreamManagementCluster object related to this delegate + * object. */ - void SetCameraAVStreamMgmtServer(CameraAVStreamMgmtServer * aCameraAVStreamMgmtServer) + void SetCameraAVStreamManagementCluster(CameraAVStreamManagementCluster * aCameraAVStreamManagementCluster) { - mCameraAVStreamMgmtServer = aCameraAVStreamMgmtServer; + mCameraAVStreamManagementCluster = aCameraAVStreamManagementCluster; } protected: - CameraAVStreamMgmtServer * GetCameraAVStreamMgmtServer() const { return mCameraAVStreamMgmtServer; } + CameraAVStreamManagementCluster * GetCameraAVStreamManagementCluster() const { return mCameraAVStreamManagementCluster; } }; enum class OptionalAttribute : uint32_t @@ -396,7 +384,7 @@ enum class OptionalAttribute : uint32_t kStatusLightBrightness = 0x0080, }; -class CameraAVStreamMgmtServer : public CommandHandlerInterface, public AttributeAccessInterface +class CameraAVStreamManagementCluster : public DefaultServerCluster { public: /** @@ -434,28 +422,47 @@ class CameraAVStreamMgmtServer : public CommandHandlerInterface, public Attribut * for the transmission of its media streams. * */ - CameraAVStreamMgmtServer(CameraAVStreamMgmtDelegate & aDelegate, EndpointId aEndpointId, const BitFlags aFeatures, - const BitFlags aOptionalAttrs, uint8_t aMaxConcurrentEncoders, - uint32_t aMaxEncodedPixelRate, const VideoSensorParamsStruct & aVideoSensorParams, - bool aNightVisionUsesInfrared, const VideoResolutionStruct & aMinViewPort, - const std::vector & aRateDistortionTradeOffPoints, - uint32_t aMaxContentBufferSize, const AudioCapabilitiesStruct & aMicrophoneCapabilities, - const AudioCapabilitiesStruct & aSpkrCapabilities, TwoWayTalkSupportTypeEnum aTwoWayTalkSupport, - const std::vector & aSnapshotCapabilities, uint32_t aMaxNetworkBandwidth, - const std::vector & aSupportedStreamUsages, - const std::vector & aStreamUsagePriorities); - - ~CameraAVStreamMgmtServer() override; + CameraAVStreamManagementCluster(CameraAVStreamManagementDelegate & aDelegate, EndpointId aEndpointId, + const BitFlags aFeatures, const BitFlags aOptionalAttrs, + uint8_t aMaxConcurrentEncoders, uint32_t aMaxEncodedPixelRate, + const VideoSensorParamsStruct & aVideoSensorParams, bool aNightVisionUsesInfrared, + const VideoResolutionStruct & aMinViewPort, + const std::vector & aRateDistortionTradeOffPoints, + uint32_t aMaxContentBufferSize, const AudioCapabilitiesStruct & aMicrophoneCapabilities, + const AudioCapabilitiesStruct & aSpkrCapabilities, TwoWayTalkSupportTypeEnum aTwoWayTalkSupport, + const std::vector & aSnapshotCapabilities, + uint32_t aMaxNetworkBandwidth, + const std::vector & aSupportedStreamUsages, + const std::vector & aStreamUsagePriorities); + + ~CameraAVStreamManagementCluster() override; /** * @brief Initialise the Camera AV Stream Management server instance. - * This function must be called after defining an CameraAVStreamMgmtServer class object. + * This function must be called after defining an CameraAVStreamManagementCluster class object. * @return Returns an error if the given endpoint and cluster ID have not been enabled in zap or if the * CommandHandler or AttributeHandler registration fails, else returns CHIP_NO_ERROR. * This method also checks if the feature setting is valid, if invalid it will return CHIP_ERROR_INVALID_ARGUMENT. */ CHIP_ERROR Init(); + // Server cluster implementation + DataModel::ActionReturnStatus ReadAttribute(const DataModel::ReadAttributeRequest & request, + AttributeValueEncoder & encoder) override; + + DataModel::ActionReturnStatus WriteAttribute(const DataModel::WriteAttributeRequest & request, + AttributeValueDecoder & decoder) override; + + std::optional InvokeCommand(const DataModel::InvokeRequest & request, + TLV::TLVReader & input_arguments, CommandHandler * handler) override; + + CHIP_ERROR Attributes(const ConcreteClusterPath & path, ReadOnlyBufferBuilder & builder) override; + + CHIP_ERROR AcceptedCommands(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) override; + + CHIP_ERROR GeneratedCommands(const ConcreteClusterPath & path, ReadOnlyBufferBuilder & builder) override; + bool HasFeature(Feature feature) const; bool SupportsOptAttr(OptionalAttribute aOptionalAttr) const; @@ -599,22 +606,23 @@ class CameraAVStreamMgmtServer : public CommandHandlerInterface, public Attribut Globals::ThreeLevelAutoEnum GetStatusLightBrightness() const { return mStatusLightBrightness; } - EndpointId GetEndpointId() { return AttributeAccessInterface::GetEndpointId().Value(); } - // Add/Remove Management functions for streams CHIP_ERROR SetStreamUsagePriorities(const std::vector & newPriorities); /** - * Called during the processing of an AllocateVideoStream request. The - * handler of the request iterates through the currently allocated video + * Called during the processing of an AllocateVideoStream request to find + * an existing stream that can be reused given the requested stream args. + * + * @param requestedArgs parameters in the allocation request + * + * Returns std::nullopt if there is no such stream, else the id of the stream + * that can be reused. + * The handler of the request iterates through the currently allocated video * streams to check if the allocation request parameters fall within the * ranges of an allocated stream so that the latter can be reused. * If a match is found, the function returns the StreamID of the reusable * stream. - * - * @param requestedArgs parameters in the allocation request - * */ std::optional GetReusableVideoStreamId(const VideoStreamStruct & requestedArgs) const; @@ -630,23 +638,26 @@ class CameraAVStreamMgmtServer : public CommandHandlerInterface, public Attribut CHIP_ERROR RemoveAudioStream(uint16_t audioStreamId); /** - * Called during the processing of an AllocateSnapshotStream request. The - * handler of the request iterates through the currently allocated snapshot + * Called during the processing of an AllocateSnapshotStream request to find + * an existing stream that can be reused given the requested stream args. + * + * @param requestedArgs parameters in the allocation request + * + * Returns std::nullopt if there is no such stream, else the id of the stream + * that can be reused. + * The handler of the request iterates through the currently allocated snapshot * streams to check if the allocation request parameters fall within the * ranges of an allocated stream so that the latter can be reused. * If a match is found, the function returns the StreamID of the reusable * stream. - * - * @param requestedArgs parameters in the allocation request - * */ std::optional - GetReusableSnapshotStreamId(const CameraAVStreamMgmtDelegate::SnapshotStreamAllocateArgs & requestedArgs) const; + GetReusableSnapshotStreamId(const CameraAVStreamManagementDelegate::SnapshotStreamAllocateArgs & requestedArgs) const; CHIP_ERROR AddSnapshotStream(const SnapshotStreamStruct & snapshotStream); CHIP_ERROR UpdateSnapshotStreamRangeParams(SnapshotStreamStruct & snapshotStreamToUpdate, - const CameraAVStreamMgmtDelegate::SnapshotStreamAllocateArgs & snapshotStream); + const CameraAVStreamManagementDelegate::SnapshotStreamAllocateArgs & snapshotStream); CHIP_ERROR RemoveSnapshotStream(uint16_t snapshotStreamId); @@ -678,13 +689,12 @@ class CameraAVStreamMgmtServer : public CommandHandlerInterface, public Attribut CHIP_ERROR PersistAndNotify(); // Declared friend so that it can access the private stream vector members - // from CameraAVStreamMgmtServer. + // from CameraAVStreamManagementCluster. template friend struct StreamTraits; - CameraAVStreamMgmtDelegate & mDelegate; - EndpointId mEndpointId; - const BitFlags mFeatures; + CameraAVStreamManagementDelegate & mDelegate; + const BitFlags mEnabledFeatures; const BitFlags mOptionalAttrs; // Attributes @@ -742,37 +752,36 @@ class CameraAVStreamMgmtServer : public CommandHandlerInterface, public Attribut if (currentValue != newValue) { currentValue = newValue; - auto path = ConcreteAttributePath(mEndpointId, CameraAvStreamManagement::Id, attributeId); + auto path = ConcreteAttributePath(mPath.mEndpointId, CameraAvStreamManagement::Id, attributeId); if (shouldPersist) { ReturnErrorOnFailure(GetSafeAttributePersistenceProvider()->WriteScalarValue(path, currentValue)); } mDelegate.OnAttributeChanged(attributeId); - MatterReportingAttributeChangeCallback(path); + NotifyAttributeChanged(attributeId); } return CHIP_NO_ERROR; } template - bool ValidateStreamForModifyOrDeallocateImpl(StreamContainer & streams, uint16_t streamID, HandlerContext & ctx, - StreamType streamType, IdGetter id_getter, bool isDeallocate) + Protocols::InteractionModel::Status ValidateStreamForModifyOrDeallocateImpl(StreamContainer & streams, uint16_t streamID, + StreamType streamType, IdGetter id_getter, + bool isDeallocate) { auto it = std::find_if(streams.begin(), streams.end(), [&](const auto & stream) { return id_getter(stream) == streamID; }); if (it == streams.end()) { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: %s stream with ID: %u not found", mEndpointId, + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: %s stream with ID: %u not found", mPath.mEndpointId, StreamTypeToString(streamType), streamID); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::NotFound); - return false; + return Protocols::InteractionModel::Status::NotFound; } if (isDeallocate && it->referenceCount > 0) { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: %s stream with ID: %u still in use", mEndpointId, + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: %s stream with ID: %u still in use", mPath.mEndpointId, StreamTypeToString(streamType), streamID); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::InvalidInState); - return false; + return Protocols::InteractionModel::Status::InvalidInState; } using StreamValueType = typename StreamContainer::value_type; @@ -780,10 +789,9 @@ class CameraAVStreamMgmtServer : public CommandHandlerInterface, public Attribut { if (it->streamUsage == Globals::StreamUsageEnum::kInternal) { - ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: %s stream with ID: %u is Internal", mEndpointId, + ChipLogError(Zcl, "CameraAVStreamMgmt[ep=%d]: %s stream with ID: %u is Internal", mPath.mEndpointId, StreamTypeToString(streamType), streamID); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::DynamicConstraintError); - return false; + return Protocols::InteractionModel::Status::DynamicConstraintError; } } @@ -809,36 +817,22 @@ class CameraAVStreamMgmtServer : public CommandHandlerInterface, public Attribut Zcl, "CameraAVStreamMgmt[ep=%d]: Snapshot stream with ID: %u based off an underlying video stream and " "not modifiable", - mEndpointId, streamID); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::InvalidInState); - return false; + mPath.mEndpointId, streamID); + return Protocols::InteractionModel::Status::InvalidInState; } } else { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::InvalidInState); - return false; + return Protocols::InteractionModel::Status::InvalidInState; } } } - return true; + return Protocols::InteractionModel::Status::Success; } bool IsBitDepthValid(uint8_t bitDepth) { return (bitDepth == 8 || bitDepth == 16 || bitDepth == 24 || bitDepth == 32); } - /** - * IM-level implementation of read - * @return appropriately mapped CHIP_ERROR if applicable - */ - CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; - - /** - * IM-level implementation of write - * @return appropriately mapped CHIP_ERROR if applicable - */ - CHIP_ERROR Write(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder) override; - /** * Helper function that loads all the persistent attributes from the KVS. */ @@ -881,40 +875,49 @@ class CameraAVStreamMgmtServer : public CommandHandlerInterface, public Attribut bool StreamPrioritiesHasDuplicates(const std::vector & aStreamUsagePriorities); - /** - * @brief Inherited from CommandHandlerInterface - */ - void InvokeCommand(HandlerContext & ctx) override; - - void HandleVideoStreamAllocate(HandlerContext & ctx, const Commands::VideoStreamAllocate::DecodableType & req); + std::optional + HandleVideoStreamAllocate(CommandHandler & handler, const ConcreteCommandPath & commandPath, + const Commands::VideoStreamAllocate::DecodableType & req); - void HandleVideoStreamModify(HandlerContext & ctx, const Commands::VideoStreamModify::DecodableType & req); + std::optional HandleVideoStreamModify(const Commands::VideoStreamModify::DecodableType & req); - void HandleVideoStreamDeallocate(HandlerContext & ctx, const Commands::VideoStreamDeallocate::DecodableType & req); + std::optional + HandleVideoStreamDeallocate(const Commands::VideoStreamDeallocate::DecodableType & req); - void HandleAudioStreamAllocate(HandlerContext & ctx, const Commands::AudioStreamAllocate::DecodableType & req); + std::optional + HandleAudioStreamAllocate(CommandHandler & handler, const ConcreteCommandPath & commandPath, + const Commands::AudioStreamAllocate::DecodableType & req); - void HandleAudioStreamDeallocate(HandlerContext & ctx, const Commands::AudioStreamDeallocate::DecodableType & req); + std::optional + HandleAudioStreamDeallocate(const Commands::AudioStreamDeallocate::DecodableType & req); - void HandleSnapshotStreamAllocate(HandlerContext & ctx, const Commands::SnapshotStreamAllocate::DecodableType & req); + std::optional + HandleSnapshotStreamAllocate(CommandHandler & handler, const ConcreteCommandPath & commandPath, + const Commands::SnapshotStreamAllocate::DecodableType & req); - void HandleSnapshotStreamModify(HandlerContext & ctx, const Commands::SnapshotStreamModify::DecodableType & req); + std::optional + HandleSnapshotStreamModify(const Commands::SnapshotStreamModify::DecodableType & req); - void HandleSnapshotStreamDeallocate(HandlerContext & ctx, const Commands::SnapshotStreamDeallocate::DecodableType & req); + std::optional + HandleSnapshotStreamDeallocate(const Commands::SnapshotStreamDeallocate::DecodableType & req); - void HandleSetStreamPriorities(HandlerContext & ctx, const Commands::SetStreamPriorities::DecodableType & req); + std::optional + HandleSetStreamPriorities(const Commands::SetStreamPriorities::DecodableType & req); - void HandleCaptureSnapshot(HandlerContext & ctx, const Commands::CaptureSnapshot::DecodableType & req); + std::optional HandleCaptureSnapshot(CommandHandler & handler, + const ConcreteCommandPath & commandPath, + const Commands::CaptureSnapshot::DecodableType & req); - bool CheckSnapshotStreamsAvailability(HandlerContext & ctx); + bool CheckSnapshotStreamsAvailability(); - bool ValidateSnapshotStreamId(const DataModel::Nullable & snapshotStreamID, HandlerContext & ctx); + bool ValidateSnapshotStreamId(const DataModel::Nullable & snapshotStreamID); - bool ValidateVideoStreamForModifyOrDeallocate(const uint16_t videoStreamID, HandlerContext & ctx, bool isDeallocate); + Protocols::InteractionModel::Status ValidateVideoStreamForModifyOrDeallocate(const uint16_t videoStreamID, bool isDeallocate); - bool ValidateAudioStreamForDeallocate(const uint16_t audioStreamID, HandlerContext & ctx); + Protocols::InteractionModel::Status ValidateAudioStreamForDeallocate(const uint16_t audioStreamID); - bool ValidateSnapshotStreamForModifyOrDeallocate(const uint16_t snapshotStreamID, HandlerContext & ctx, bool isDeallocate); + Protocols::InteractionModel::Status ValidateSnapshotStreamForModifyOrDeallocate(const uint16_t snapshotStreamID, + bool isDeallocate); }; } // namespace CameraAvStreamManagement diff --git a/src/app/clusters/camera-av-stream-management-server/README.md b/src/app/clusters/camera-av-stream-management-server/README.md new file mode 100644 index 00000000000..b1f9ad2276f --- /dev/null +++ b/src/app/clusters/camera-av-stream-management-server/README.md @@ -0,0 +1,65 @@ +# Camera AV Stream Management Cluster Server Implementation + +This directory contains the server-side implementation of the Camera AV Stream +Management Cluster. This implementation is code-driven, and it does not rely on +ZAP tool code generation for its core logic, and applications should not use the +ZAP tool for configuring its attributes and commands. + +## Purpose + +The Camera AV Stream Management Cluster manages the allocation, configuration, +and lifecycle of audio and video streams from a camera device. It allows +commissioners to request streams for various purposes like live viewing, +recording, and analysis, while enabling the device to manage its encoding and +streaming resources. + +## Key Components + +1. **`CameraAVStreamManagementCluster`:** The main class implementing the + cluster logic, attribute storage, and command handling. +2. **`CameraAVStreamManagementDelegate`:** A pure virtual interface that the + application MUST implement. This delegate is responsible for interacting + with the device's underlying camera, audio, and encoder hardware/software + stack to fulfill stream requests and report status. + +## Integration Guide + +To use this cluster implementation in your application, follow the pattern in +`examples/camera-app/camera-common/src/camera-app.cpp`: + +### 1. Implement the Delegate + +Create a concrete class inheriting from `CameraAVStreamManagementDelegate` and +implement all its pure virtual methods. This class will bridge the cluster logic +with your device's specific media pipelines. + +### 2. Instantiate and Initialize the Cluster + +Within your application setup (e.g., in a function like +`CreateAndInitializeCameraAVStreamMgmt`): + + a. **Determine Features and Optional Attributes:** Based on your device capabilities, populate `BitFlags` and `BitFlags`. Use helper functions or interfaces (like `CameraHALInterface` in the example) to query device capabilities. + + b. **Gather Configuration Parameters:** Collect all necessary parameters for the `CameraAVStreamManagementCluster` constructor. This includes: + * Max concurrent encoders + * Max encoded pixel rate + * Video sensor parameters + * Audio/Speaker capabilities + * Snapshot capabilities + * Supported stream usages, etc. + Again, source these values from your device's hardware abstraction layer. + + c. **Create Cluster Instance:** Instantiate `CameraAVStreamManagementCluster` on the heap or as a member variable, passing the delegate instance, endpoint ID, features, optional attributes, and all configuration parameters gathered above. + +The example uses a `ServerCluster` member and a +`Create` method. + + d. **Register Cluster:** Register the created cluster instance with the Matter data model registry for the desired endpoint. + + e. **Set Initial Attribute Values:** After creation, set the initial values for writable attributes based on the device's current state. This is typically done by calling the cluster's setter methods (e.g., `SetHDRModeEnabled`, `SetViewport`, etc.). + + f. **Call `Init()`:** Finally, call the `Init()` method on the cluster instance. This performs essential validation of the configuration. + +Refer to the Matter specification, the header files +(`CameraAVStreamManagementCluster.h`, `CameraAVStreamManagementDelegate.h`), and +the `camera-app.cpp` example for full details. diff --git a/src/app/clusters/camera-av-stream-management-server/app_config_dependent_sources.cmake b/src/app/clusters/camera-av-stream-management-server/app_config_dependent_sources.cmake index 4190b619196..74fc98ead9d 100644 --- a/src/app/clusters/camera-av-stream-management-server/app_config_dependent_sources.cmake +++ b/src/app/clusters/camera-av-stream-management-server/app_config_dependent_sources.cmake @@ -16,6 +16,6 @@ TARGET_SOURCES( ${APP_TARGET} PRIVATE - "${CLUSTER_DIR}/camera-av-stream-management-server.cpp" - "${CLUSTER_DIR}/camera-av-stream-management-server.h" + "${CLUSTER_DIR}/CameraAVStreamManagementCluster.cpp" + "${CLUSTER_DIR}/CameraAVStreamManagementCluster.h" ) \ No newline at end of file diff --git a/src/app/clusters/camera-av-stream-management-server/app_config_dependent_sources.gni b/src/app/clusters/camera-av-stream-management-server/app_config_dependent_sources.gni index e1ae79a4a5f..ef59f84b0b2 100644 --- a/src/app/clusters/camera-av-stream-management-server/app_config_dependent_sources.gni +++ b/src/app/clusters/camera-av-stream-management-server/app_config_dependent_sources.gni @@ -11,7 +11,4 @@ # 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. -app_config_dependent_sources = [ - "camera-av-stream-management-server.cpp", - "camera-av-stream-management-server.h", -] +app_config_dependent_sources = [] diff --git a/src/app/clusters/camera-av-stream-management-server/tests/BUILD.gn b/src/app/clusters/camera-av-stream-management-server/tests/BUILD.gn new file mode 100644 index 00000000000..8038ec57f46 --- /dev/null +++ b/src/app/clusters/camera-av-stream-management-server/tests/BUILD.gn @@ -0,0 +1,35 @@ +# Copyright (c) 2025 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +import("${chip_root}/build/chip/chip_test_suite.gni") + +chip_test_suite("tests") { + output_name = "libTestCameraAVStreamManagementCluster" + + # Comment out unit test file because of dependency on ClusterTest.h which + # had locations moved and other associated dependency changes in master. + #test_sources = [ "TestCameraAVStreamManagementCluster.cpp" ] + + cflags = [ "-Wconversion" ] + + public_deps = [ + "${chip_root}/src/app/clusters/camera-av-stream-management-server", + "${chip_root}/src/app/server-cluster/testing", + "${chip_root}/src/lib/core:string-builder-adapters", + "${chip_root}/src/lib/support", + ] +} diff --git a/src/app/clusters/camera-av-stream-management-server/tests/TestCameraAVStreamManagementCluster.cpp b/src/app/clusters/camera-av-stream-management-server/tests/TestCameraAVStreamManagementCluster.cpp new file mode 100644 index 00000000000..50d4d0cc916 --- /dev/null +++ b/src/app/clusters/camera-av-stream-management-server/tests/TestCameraAVStreamManagementCluster.cpp @@ -0,0 +1,656 @@ +/* + * Copyright (c) 2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::CameraAvStreamManagement; +using namespace chip::Testing; + +static constexpr chip::EndpointId kTestEndpointId = 1; + +// Mock delegate for testing CameraAVStreamManagement +class MockCameraAVStreamManagementDelegate : public CameraAVStreamManagementDelegate +{ +public: + MockCameraAVStreamManagementDelegate(std::vector * videoStreams, + std::vector * audioStreams, + std::vector * snapshotStreams) : + mAllocatedVideoStreams(videoStreams), + mAllocatedAudioStreams(audioStreams), mAllocatedSnapshotStreams(snapshotStreams) + {} + + Protocols::InteractionModel::Status VideoStreamAllocate(const VideoStreamStruct & allocateArgs, uint16_t & outStreamID) override + { + outStreamID = 1; + return Protocols::InteractionModel::Status::Success; + } + + void OnVideoStreamAllocated(const VideoStreamStruct & allocatedStream, StreamAllocationAction action) override {} + + Protocols::InteractionModel::Status VideoStreamModify(const uint16_t streamID, const Optional waterMarkEnabled, + const Optional osdEnabled) override + { + return Protocols::InteractionModel::Status::Success; + } + + Protocols::InteractionModel::Status VideoStreamDeallocate(const uint16_t streamID) override + { + return Protocols::InteractionModel::Status::Success; + } + + Protocols::InteractionModel::Status AudioStreamAllocate(const AudioStreamStruct & allocateArgs, uint16_t & outStreamID) override + { + outStreamID = 1; + return Protocols::InteractionModel::Status::Success; + } + + Protocols::InteractionModel::Status AudioStreamDeallocate(const uint16_t streamID) override + { + return Protocols::InteractionModel::Status::Success; + } + + Protocols::InteractionModel::Status SnapshotStreamAllocate(const SnapshotStreamAllocateArgs & allocateArgs, + uint16_t & outStreamID) override + { + outStreamID = 1; + return Protocols::InteractionModel::Status::Success; + } + + Protocols::InteractionModel::Status SnapshotStreamModify(const uint16_t streamID, const Optional waterMarkEnabled, + const Optional osdEnabled) override + { + return Protocols::InteractionModel::Status::Success; + } + + Protocols::InteractionModel::Status SnapshotStreamDeallocate(const uint16_t streamID) override + { + return Protocols::InteractionModel::Status::Success; + } + + void OnStreamUsagePrioritiesChanged() override {} + + void OnAttributeChanged(AttributeId attributeId) override {} + + Protocols::InteractionModel::Status CaptureSnapshot(const DataModel::Nullable streamID, + const VideoResolutionStruct & resolution, + ImageSnapshot & outImageSnapshot) override + { + return Protocols::InteractionModel::Status::Success; + } + + CHIP_ERROR PersistentAttributesLoadedCallback() override { return CHIP_NO_ERROR; } + + const std::vector & GetAllocatedVideoStreams() const override { return *mAllocatedVideoStreams; } + + const std::vector & GetAllocatedAudioStreams() const override { return *mAllocatedAudioStreams; } + + const std::vector & GetAllocatedSnapshotStreams() const { return *mAllocatedSnapshotStreams; } + +private: + std::vector * mAllocatedVideoStreams; + std::vector * mAllocatedAudioStreams; + std::vector * mAllocatedSnapshotStreams; +}; + +// initialize memory as ReadOnlyBufferBuilder may allocate +struct TestCameraAVStreamManagementCluster : public ::testing::Test +{ + static void SetUpTestSuite() { ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR); } + static void TearDownTestSuite() { chip::Platform::MemoryShutdown(); } + + static VideoSensorParamsStruct & GetVideoSensorParams() + { + static VideoSensorParamsStruct videoSensorParams = { 1920, 1080, 120, + chip::Optional(30) }; // Typical numbers for Pi camera. + return videoSensorParams; + } + + static std::vector & GetRateDistortionTradeOffPoints() + { + static std::vector rateDistTradeOffs = { + { VideoCodecEnum::kH264, { 640, 480 }, 10000 /* bitrate */ } + }; + return rateDistTradeOffs; + } + + static AudioCapabilitiesStruct & GetAudioCapabilities() + { + static std::array audioCodecs = { AudioCodecEnum::kOpus, AudioCodecEnum::kAacLc }; + static std::array sampleRates = { 48000, 32000 }; // Sample rates in Hz + static std::array bitDepths = { 24, 32 }; + static AudioCapabilitiesStruct audioCapabilities = { 2, chip::Span(audioCodecs), + chip::Span(sampleRates), chip::Span(bitDepths) }; + return audioCapabilities; + } + + static std::vector & GetSnapshotCapabilities() + { + static std::vector snapshotCapabilities = { + { { 640, 480 }, 30, ImageCodecEnum::kJpeg, false, chip::MakeOptional(static_cast(false)) }, + { { 1280, 720 }, 30, ImageCodecEnum::kJpeg, true, chip::MakeOptional(static_cast(true)) }, + }; + return snapshotCapabilities; + } + + static std::vector & GetSupportedStreamUsages() + { + static std::vector supportedStreamUsage = { StreamUsageEnum::kLiveView, StreamUsageEnum::kRecording }; + return supportedStreamUsage; + } + + static CHIP_ERROR InitializeCameraAVSMDefaults(CameraAvStreamManagement::CameraAVStreamManagementCluster & mServer) + { + ReturnErrorOnFailure(mServer.SetSoftRecordingPrivacyModeEnabled(true)); + ReturnErrorOnFailure(mServer.SetSoftLivestreamPrivacyModeEnabled(true)); + ReturnErrorOnFailure(mServer.SetHardPrivacyModeOn(true)); + ReturnErrorOnFailure(mServer.SetViewport({ 0, 0, 1920, 1080 })); + ReturnErrorOnFailure(mServer.SetSpeakerMuted(true)); + ReturnErrorOnFailure(mServer.SetSpeakerVolumeLevel(1)); + ReturnErrorOnFailure(mServer.SetSpeakerMinLevel(1)); + ReturnErrorOnFailure(mServer.SetSpeakerMaxLevel(254)); + ReturnErrorOnFailure(mServer.SetMicrophoneMuted(true)); + ReturnErrorOnFailure(mServer.SetMicrophoneVolumeLevel(1)); + ReturnErrorOnFailure(mServer.SetMicrophoneMinLevel(1)); + ReturnErrorOnFailure(mServer.SetMicrophoneMaxLevel(254)); + ReturnErrorOnFailure(mServer.SetMicrophoneAGCEnabled(true)); + ReturnErrorOnFailure(mServer.SetImageRotation(0)); + ReturnErrorOnFailure(mServer.SetImageFlipHorizontal(false)); + ReturnErrorOnFailure(mServer.SetImageFlipVertical(false)); + ReturnErrorOnFailure(mServer.SetStatusLightEnabled(true)); + ReturnErrorOnFailure(mServer.SetStatusLightBrightness(Globals::ThreeLevelAutoEnum::kMedium)); + + return CHIP_NO_ERROR; + } + + TestCameraAVStreamManagementCluster() : + mMockDelegate(&mVideoStreams, &mAudioStreams, &mSnapshotStreams), + mServer(mMockDelegate, kTestEndpointId, + chip::BitFlags( + CameraAvStreamManagement::Feature::kVideo, CameraAvStreamManagement::Feature::kAudio, + CameraAvStreamManagement::Feature::kSnapshot, CameraAvStreamManagement::Feature::kSpeaker, + CameraAvStreamManagement::Feature::kImageControl, CameraAvStreamManagement::Feature::kPrivacy, + CameraAvStreamManagement::Feature::kWatermark), + chip::BitFlags( + CameraAvStreamManagement::OptionalAttribute::kHardPrivacyModeOn, + CameraAvStreamManagement::OptionalAttribute::kMicrophoneAGCEnabled, + CameraAvStreamManagement::OptionalAttribute::kImageRotation, + CameraAvStreamManagement::OptionalAttribute::kImageFlipHorizontal, + CameraAvStreamManagement::OptionalAttribute::kImageFlipVertical, + CameraAvStreamManagement::OptionalAttribute::kStatusLightEnabled, + CameraAvStreamManagement::OptionalAttribute::kStatusLightBrightness), + 1, 248832000 /*1920*1080*120 */, GetVideoSensorParams(), false, { 640, 480 }, GetRateDistortionTradeOffPoints(), + 4096, GetAudioCapabilities(), GetAudioCapabilities(), TwoWayTalkSupportTypeEnum::kFullDuplex, + GetSnapshotCapabilities(), 128000000, GetSupportedStreamUsages(), GetSupportedStreamUsages()), + mClusterTester(mServer) + {} + + void SetUp() override + { + VerifyOrDie(mPersistenceProvider.Init(&mClusterTester.GetServerClusterContext().storage) == CHIP_NO_ERROR); + app::SetSafeAttributePersistenceProvider(&mPersistenceProvider); + EXPECT_EQ(mServer.Startup(mClusterTester.GetServerClusterContext()), CHIP_NO_ERROR); + EXPECT_EQ(InitializeCameraAVSMDefaults(mServer), CHIP_NO_ERROR); + } + + void TearDown() override { app::SetSafeAttributePersistenceProvider(nullptr); } + + std::vector mVideoStreams; + std::vector mAudioStreams; + std::vector mSnapshotStreams; + MockCameraAVStreamManagementDelegate mMockDelegate; + CameraAvStreamManagement::CameraAVStreamManagementCluster mServer; + ClusterTester mClusterTester; + app::DefaultSafeAttributePersistenceProvider mPersistenceProvider; +}; + +TEST_F(TestCameraAVStreamManagementCluster, TestAttributes) +{ + ASSERT_TRUE( + Testing::IsAttributesListEqualTo(mServer, + { + CameraAvStreamManagement::Attributes::MaxConcurrentEncoders::kMetadataEntry, + CameraAvStreamManagement::Attributes::MaxEncodedPixelRate::kMetadataEntry, + CameraAvStreamManagement::Attributes::VideoSensorParams::kMetadataEntry, + CameraAvStreamManagement::Attributes::MinViewportResolution::kMetadataEntry, + CameraAvStreamManagement::Attributes::RateDistortionTradeOffPoints::kMetadataEntry, + CameraAvStreamManagement::Attributes::MaxContentBufferSize::kMetadataEntry, + CameraAvStreamManagement::Attributes::MicrophoneCapabilities::kMetadataEntry, + CameraAvStreamManagement::Attributes::SpeakerCapabilities::kMetadataEntry, + CameraAvStreamManagement::Attributes::TwoWayTalkSupport::kMetadataEntry, + CameraAvStreamManagement::Attributes::SnapshotCapabilities::kMetadataEntry, + CameraAvStreamManagement::Attributes::MaxNetworkBandwidth::kMetadataEntry, + CameraAvStreamManagement::Attributes::CurrentFrameRate::kMetadataEntry, + CameraAvStreamManagement::Attributes::SupportedStreamUsages::kMetadataEntry, + CameraAvStreamManagement::Attributes::AllocatedVideoStreams::kMetadataEntry, + CameraAvStreamManagement::Attributes::AllocatedAudioStreams::kMetadataEntry, + CameraAvStreamManagement::Attributes::AllocatedSnapshotStreams::kMetadataEntry, + CameraAvStreamManagement::Attributes::StreamUsagePriorities::kMetadataEntry, + CameraAvStreamManagement::Attributes::SoftRecordingPrivacyModeEnabled::kMetadataEntry, + CameraAvStreamManagement::Attributes::SoftLivestreamPrivacyModeEnabled::kMetadataEntry, + CameraAvStreamManagement::Attributes::HardPrivacyModeOn::kMetadataEntry, + CameraAvStreamManagement::Attributes::Viewport::kMetadataEntry, + CameraAvStreamManagement::Attributes::SpeakerMuted::kMetadataEntry, + CameraAvStreamManagement::Attributes::SpeakerVolumeLevel::kMetadataEntry, + CameraAvStreamManagement::Attributes::SpeakerMaxLevel::kMetadataEntry, + CameraAvStreamManagement::Attributes::SpeakerMinLevel::kMetadataEntry, + CameraAvStreamManagement::Attributes::MicrophoneMuted::kMetadataEntry, + CameraAvStreamManagement::Attributes::MicrophoneVolumeLevel::kMetadataEntry, + CameraAvStreamManagement::Attributes::MicrophoneMaxLevel::kMetadataEntry, + CameraAvStreamManagement::Attributes::MicrophoneMinLevel::kMetadataEntry, + CameraAvStreamManagement::Attributes::MicrophoneAGCEnabled::kMetadataEntry, + CameraAvStreamManagement::Attributes::ImageRotation::kMetadataEntry, + CameraAvStreamManagement::Attributes::ImageFlipHorizontal::kMetadataEntry, + CameraAvStreamManagement::Attributes::ImageFlipVertical::kMetadataEntry, + CameraAvStreamManagement::Attributes::StatusLightEnabled::kMetadataEntry, + CameraAvStreamManagement::Attributes::StatusLightBrightness::kMetadataEntry, + })); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestAcceptedCommands) +{ + ASSERT_TRUE( + Testing::IsAcceptedCommandsListEqualTo(mServer, + { + CameraAvStreamManagement::Commands::VideoStreamAllocate::kMetadataEntry, + CameraAvStreamManagement::Commands::VideoStreamDeallocate::kMetadataEntry, + CameraAvStreamManagement::Commands::VideoStreamModify::kMetadataEntry, + CameraAvStreamManagement::Commands::AudioStreamAllocate::kMetadataEntry, + CameraAvStreamManagement::Commands::AudioStreamDeallocate::kMetadataEntry, + CameraAvStreamManagement::Commands::SnapshotStreamAllocate::kMetadataEntry, + CameraAvStreamManagement::Commands::SnapshotStreamDeallocate::kMetadataEntry, + CameraAvStreamManagement::Commands::SnapshotStreamModify::kMetadataEntry, + CameraAvStreamManagement::Commands::SetStreamPriorities::kMetadataEntry, + CameraAvStreamManagement::Commands::CaptureSnapshot::kMetadataEntry, + + })); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadClusterRevisionAttribute) +{ + // Create a mock attribute request for ClusterRevision + chip::app::DataModel::ReadAttributeRequest request; + request.path.mEndpointId = kTestEndpointId; + request.path.mClusterId = CameraAvStreamManagement::Id; + request.path.mAttributeId = chip::app::Clusters::Globals::Attributes::ClusterRevision::Id; + + // Create a buffer for encoding + chip::Platform::ScopedMemoryBufferWithSize buffer; + ASSERT_TRUE(buffer.Alloc(1024)); + + // Create AttributeReportIBs::Builder for the encoder + chip::app::AttributeReportIBs::Builder attributeReportIBsBuilder; + chip::TLV::TLVWriter reportWriter; + reportWriter.Init(buffer.Get(), buffer.AllocatedSize()); + CHIP_ERROR err = attributeReportIBsBuilder.Init(&reportWriter); + ASSERT_EQ(err, CHIP_NO_ERROR); + + chip::app::AttributeValueEncoder encoder(attributeReportIBsBuilder, chip::Access::SubjectDescriptor{}, request.path, + 0 /* dataVersion */); + + // Test reading cluster revision + auto status = mServer.ReadAttribute(request, encoder); + EXPECT_TRUE(status.IsSuccess()); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadMaxConcurrentEncoders) +{ + uint8_t maxConcurrentEncoders = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::MaxConcurrentEncoders::Id, maxConcurrentEncoders), CHIP_NO_ERROR); + EXPECT_EQ(maxConcurrentEncoders, 1); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadMaxEncodedPixelRate) +{ + uint32_t maxEncodedPixelRate = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::MaxEncodedPixelRate::Id, maxEncodedPixelRate), CHIP_NO_ERROR); + EXPECT_EQ(maxEncodedPixelRate, static_cast(248832000)); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadVideoSensorParams) +{ + Attributes::VideoSensorParams::TypeInfo::DecodableType videoSensorParams; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::VideoSensorParams::Id, videoSensorParams), CHIP_NO_ERROR); + EXPECT_EQ(videoSensorParams.sensorWidth, 1920); + EXPECT_EQ(videoSensorParams.sensorHeight, 1080); + EXPECT_EQ(videoSensorParams.maxFPS, 120); + EXPECT_TRUE(videoSensorParams.maxHDRFPS.HasValue()); + EXPECT_EQ(videoSensorParams.maxHDRFPS.Value(), 30); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadMinViewportResolution) +{ + Attributes::MinViewportResolution::TypeInfo::Type minViewportResolution; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::MinViewportResolution::Id, minViewportResolution), CHIP_NO_ERROR); + EXPECT_EQ(minViewportResolution.width, 640); + EXPECT_EQ(minViewportResolution.height, 480); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadRateDistortionTradeOffPoints) +{ + Attributes::RateDistortionTradeOffPoints::TypeInfo::DecodableType rateDistortionTradeOffPoints; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::RateDistortionTradeOffPoints::Id, rateDistortionTradeOffPoints), + CHIP_NO_ERROR); + auto it = rateDistortionTradeOffPoints.begin(); + uint8_t count = 0; + while (it.Next()) + { + ++count; + } + EXPECT_EQ(it.GetStatus(), CHIP_NO_ERROR); + EXPECT_EQ(count, 1u); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadMaxContentBufferSize) +{ + uint32_t maxContentBufferSize = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::MaxContentBufferSize::Id, maxContentBufferSize), CHIP_NO_ERROR); + EXPECT_EQ(maxContentBufferSize, 4096u); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadMicrophoneCapabilities) +{ + Attributes::MicrophoneCapabilities::TypeInfo::DecodableType microphoneCapabilities; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::MicrophoneCapabilities::Id, microphoneCapabilities), CHIP_NO_ERROR); + + EXPECT_EQ(microphoneCapabilities.maxNumberOfChannels, 2); + + auto it = microphoneCapabilities.supportedCodecs.begin(); + uint8_t count = 0; + while (it.Next()) + { + ++count; + } + EXPECT_EQ(it.GetStatus(), CHIP_NO_ERROR); + EXPECT_EQ(count, 2u); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadSpeakerCapabilities) +{ + Attributes::SpeakerCapabilities::TypeInfo::DecodableType speakerCapabilities; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::SpeakerCapabilities::Id, speakerCapabilities), CHIP_NO_ERROR); + + EXPECT_EQ(speakerCapabilities.maxNumberOfChannels, 2); + + auto it = speakerCapabilities.supportedCodecs.begin(); + uint8_t count = 0; + while (it.Next()) + { + ++count; + } + EXPECT_EQ(it.GetStatus(), CHIP_NO_ERROR); + EXPECT_EQ(count, 2u); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadTwoWayTalkSupport) +{ + Attributes::TwoWayTalkSupport::TypeInfo::Type twoWayTalkSupport = TwoWayTalkSupportTypeEnum::kNotSupported; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::TwoWayTalkSupport::Id, twoWayTalkSupport), CHIP_NO_ERROR); + EXPECT_EQ(twoWayTalkSupport, TwoWayTalkSupportTypeEnum::kFullDuplex); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadSnapshotCapabilities) +{ + Attributes::SnapshotCapabilities::TypeInfo::DecodableType snapshotCapabilities; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::SnapshotCapabilities::Id, snapshotCapabilities), CHIP_NO_ERROR); + auto it = snapshotCapabilities.begin(); + uint8_t count = 0; + while (it.Next()) + { + ++count; + } + EXPECT_EQ(it.GetStatus(), CHIP_NO_ERROR); + EXPECT_EQ(count, 2u); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadMaxNetworkBandwidth) +{ + uint32_t maxNetworkBandwidth = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::MaxNetworkBandwidth::Id, maxNetworkBandwidth), CHIP_NO_ERROR); + EXPECT_EQ(maxNetworkBandwidth, 128000000u); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadCurrentFrameRate) +{ + Attributes::CurrentFrameRate::TypeInfo::Type currentFrameRate = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::CurrentFrameRate::Id, currentFrameRate), CHIP_NO_ERROR); + EXPECT_EQ(currentFrameRate, 0); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadSupportedStreamUsages) +{ + Attributes::SupportedStreamUsages::TypeInfo::DecodableType supportedStreamUsages; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::SupportedStreamUsages::Id, supportedStreamUsages), CHIP_NO_ERROR); + auto it = supportedStreamUsages.begin(); + uint8_t count = 0; + while (it.Next()) + { + ++count; + } + EXPECT_EQ(it.GetStatus(), CHIP_NO_ERROR); + EXPECT_EQ(count, 2u); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadAllocatedVideoStreams) +{ + Attributes::AllocatedVideoStreams::TypeInfo::DecodableType allocatedVideoStreams; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::AllocatedVideoStreams::Id, allocatedVideoStreams), CHIP_NO_ERROR); + auto it = allocatedVideoStreams.begin(); + uint8_t count = 0; + while (it.Next()) + { + ++count; + } + EXPECT_EQ(it.GetStatus(), CHIP_NO_ERROR); + EXPECT_EQ(count, 0u); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadAllocatedAudioStreams) +{ + Attributes::AllocatedAudioStreams::TypeInfo::DecodableType allocatedAudioStreams; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::AllocatedAudioStreams::Id, allocatedAudioStreams), CHIP_NO_ERROR); + auto it = allocatedAudioStreams.begin(); + uint8_t count = 0; + while (it.Next()) + { + ++count; + } + EXPECT_EQ(it.GetStatus(), CHIP_NO_ERROR); + EXPECT_EQ(count, 0u); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadAllocatedSnapshotStreams) +{ + Attributes::AllocatedSnapshotStreams::TypeInfo::DecodableType allocatedSnapshotStreams; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::AllocatedSnapshotStreams::Id, allocatedSnapshotStreams), CHIP_NO_ERROR); + auto it = allocatedSnapshotStreams.begin(); + uint8_t count = 0; + while (it.Next()) + { + ++count; + } + EXPECT_EQ(it.GetStatus(), CHIP_NO_ERROR); + EXPECT_EQ(count, 0u); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadStreamUsagePriorities) +{ + Attributes::StreamUsagePriorities::TypeInfo::DecodableType streamUsagePriorities; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::StreamUsagePriorities::Id, streamUsagePriorities), CHIP_NO_ERROR); + auto it = streamUsagePriorities.begin(); + uint8_t count = 0; + while (it.Next()) + { + ++count; + } + EXPECT_EQ(it.GetStatus(), CHIP_NO_ERROR); + EXPECT_EQ(count, 2u); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadSoftRecordingPrivacyModeEnabled) +{ + bool softRecordingPrivacyModeEnabled = false; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::SoftRecordingPrivacyModeEnabled::Id, softRecordingPrivacyModeEnabled), + CHIP_NO_ERROR); + EXPECT_TRUE(softRecordingPrivacyModeEnabled); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadSoftLivestreamPrivacyModeEnabled) +{ + bool softLivestreamPrivacyModeEnabled = false; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::SoftLivestreamPrivacyModeEnabled::Id, softLivestreamPrivacyModeEnabled), + CHIP_NO_ERROR); + EXPECT_TRUE(softLivestreamPrivacyModeEnabled); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadHardPrivacyModeOn) +{ + bool hardPrivacyModeOn = false; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::HardPrivacyModeOn::Id, hardPrivacyModeOn), CHIP_NO_ERROR); + EXPECT_TRUE(hardPrivacyModeOn); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadViewport) +{ + Attributes::Viewport::TypeInfo::Type viewport = { 0, 0, 0, 0 }; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::Viewport::Id, viewport), CHIP_NO_ERROR); + EXPECT_EQ(viewport.x1, 0); + EXPECT_EQ(viewport.y1, 0); + EXPECT_EQ(viewport.x2, 1920); + EXPECT_EQ(viewport.y2, 1080); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadSpeakerMuted) +{ + bool speakerMuted = false; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::SpeakerMuted::Id, speakerMuted), CHIP_NO_ERROR); + EXPECT_TRUE(speakerMuted); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadSpeakerVolumeLevel) +{ + uint8_t speakerVolumeLevel = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::SpeakerVolumeLevel::Id, speakerVolumeLevel), CHIP_NO_ERROR); + EXPECT_EQ(speakerVolumeLevel, 1); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadSpeakerMaxLevel) +{ + uint8_t speakerMaxLevel = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::SpeakerMaxLevel::Id, speakerMaxLevel), CHIP_NO_ERROR); + EXPECT_EQ(speakerMaxLevel, 254); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadSpeakerMinLevel) +{ + uint8_t speakerMinLevel = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::SpeakerMinLevel::Id, speakerMinLevel), CHIP_NO_ERROR); + EXPECT_EQ(speakerMinLevel, 1); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadMicrophoneMuted) +{ + bool microphoneMuted = false; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::MicrophoneMuted::Id, microphoneMuted), CHIP_NO_ERROR); + EXPECT_TRUE(microphoneMuted); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadMicrophoneVolumeLevel) +{ + uint8_t microphoneVolumeLevel = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::MicrophoneVolumeLevel::Id, microphoneVolumeLevel), CHIP_NO_ERROR); + EXPECT_EQ(microphoneVolumeLevel, 1); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadMicrophoneMaxLevel) +{ + uint8_t microphoneMaxLevel = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::MicrophoneMaxLevel::Id, microphoneMaxLevel), CHIP_NO_ERROR); + EXPECT_EQ(microphoneMaxLevel, 254); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadMicrophoneMinLevel) +{ + uint8_t microphoneMinLevel = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::MicrophoneMinLevel::Id, microphoneMinLevel), CHIP_NO_ERROR); + EXPECT_EQ(microphoneMinLevel, 1); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadMicrophoneAGCEnabled) +{ + bool microphoneAGCEnabled = false; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::MicrophoneAGCEnabled::Id, microphoneAGCEnabled), CHIP_NO_ERROR); + EXPECT_TRUE(microphoneAGCEnabled); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadImageRotation) +{ + uint16_t imageRotation = 1; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::ImageRotation::Id, imageRotation), CHIP_NO_ERROR); + EXPECT_EQ(imageRotation, 0); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadImageFlipHorizontal) +{ + bool imageFlipHorizontal = true; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::ImageFlipHorizontal::Id, imageFlipHorizontal), CHIP_NO_ERROR); + EXPECT_FALSE(imageFlipHorizontal); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadImageFlipVertical) +{ + bool imageFlipVertical = true; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::ImageFlipVertical::Id, imageFlipVertical), CHIP_NO_ERROR); + EXPECT_FALSE(imageFlipVertical); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadStatusLightEnabled) +{ + bool statusLightEnabled = false; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::StatusLightEnabled::Id, statusLightEnabled), CHIP_NO_ERROR); + EXPECT_TRUE(statusLightEnabled); +} + +TEST_F(TestCameraAVStreamManagementCluster, TestReadStatusLightBrightness) +{ + Attributes::StatusLightBrightness::TypeInfo::Type statusLightBrightness = Globals::ThreeLevelAutoEnum::kAuto; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::StatusLightBrightness::Id, statusLightBrightness), CHIP_NO_ERROR); + EXPECT_EQ(statusLightBrightness, Globals::ThreeLevelAutoEnum::kMedium); +} + +} // namespace diff --git a/src/app/clusters/chime-server/BUILD.gn b/src/app/clusters/chime-server/BUILD.gn index 15ef362f808..00a427e00af 100644 --- a/src/app/clusters/chime-server/BUILD.gn +++ b/src/app/clusters/chime-server/BUILD.gn @@ -11,5 +11,21 @@ # 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. -group("chime-server") { + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +source_set("chime-server") { + sources = [ + "ChimeCluster.cpp", + "ChimeCluster.h", + ] + + public_deps = [ + "${chip_root}/src/app/data-model-provider", + "${chip_root}/src/app/server", + "${chip_root}/src/app/server-cluster", + "${chip_root}/src/lib/support", + "${chip_root}/zzz_generated/app-common/clusters/Chime", + ] } diff --git a/src/app/clusters/chime-server/ChimeCluster.cpp b/src/app/clusters/chime-server/ChimeCluster.cpp new file mode 100644 index 00000000000..48725e851a5 --- /dev/null +++ b/src/app/clusters/chime-server/ChimeCluster.cpp @@ -0,0 +1,322 @@ +/* + * + * Copyright (c) 2024-2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/****************************************************************************' + * @file + * @brief Implementation for the Chime Server Cluster + ***************************************************************************/ + +#include "ChimeCluster.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::Chime; +using namespace chip::app::Clusters::Chime::Attributes; +using chip::Protocols::InteractionModel::Status; +using ChimeSoundStructType = Structs::ChimeSoundStruct::Type; + +namespace chip { +namespace app { +namespace Clusters { + +ChimeCluster::ChimeCluster(EndpointId endpointId, ChimeDelegate & delegate) : + DefaultServerCluster({ endpointId, Chime::Id }), mDelegate(delegate) +{ + mDelegate.SetChimeCluster(this); +} + +ChimeCluster::~ChimeCluster() +{ + mDelegate.SetChimeCluster(nullptr); +} + +CHIP_ERROR ChimeCluster::Startup(ServerClusterContext & context) +{ + ReturnErrorOnFailure(DefaultServerCluster::Startup(context)); + + LoadPersistentAttributes(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ChimeCluster::AcceptedCommands(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) +{ + static constexpr DataModel::AcceptedCommandEntry kAcceptedCommands[] = { + Chime::Commands::PlayChimeSound::kMetadataEntry, + }; + return builder.ReferenceExisting(kAcceptedCommands); +} + +CHIP_ERROR ChimeCluster::Attributes(const ConcreteClusterPath & path, ReadOnlyBufferBuilder & builder) +{ + AttributeListBuilder listBuilder(builder); + // Chime does not have optional attributes implemented yet (or exposed via options), + // so we just return mandatory ones. + return listBuilder.Append(Span(Chime::Attributes::kMandatoryMetadata), {}); +} + +void ChimeCluster::LoadPersistentAttributes() +{ + // Load Active Chime ID + uint8_t storedSelectedChime = 0; + CHIP_ERROR err = GetSafeAttributePersistenceProvider()->ReadScalarValue( + ConcreteAttributePath(mPath.mEndpointId, Chime::Id, SelectedChime::Id), storedSelectedChime); + if (err == CHIP_NO_ERROR) + { + mSelectedChime = storedSelectedChime; + } + else + { + // otherwise defaults + ChipLogDetail(Zcl, "Chime: Unable to load the SelectedChime attribute from the KVS. Defaulting to %u", mSelectedChime); + } + + // Load Enabled + bool storedEnabled = false; + err = GetSafeAttributePersistenceProvider()->ReadScalarValue(ConcreteAttributePath(mPath.mEndpointId, Chime::Id, Enabled::Id), + storedEnabled); + if (err == CHIP_NO_ERROR) + { + mEnabled = storedEnabled; + } + else + { + // otherwise take the default + ChipLogDetail(Zcl, "Chime: Unable to load the Enabled attribute from the KVS. Defaulting to %u", mEnabled); + } +} + +DataModel::ActionReturnStatus ChimeCluster::ReadAttribute(const DataModel::ReadAttributeRequest & request, + AttributeValueEncoder & encoder) +{ + switch (request.path.mAttributeId) + { + case ClusterRevision::Id: + return encoder.Encode(Chime::kRevision); + case FeatureMap::Id: + return encoder.Encode(static_cast(0)); + case SelectedChime::Id: + return encoder.Encode(mSelectedChime); + case Enabled::Id: + return encoder.Encode(mEnabled); + case InstalledChimeSounds::Id: + return encoder.EncodeList( + [this](const auto & subEncoder) -> CHIP_ERROR { return this->EncodeSupportedChimeSounds(subEncoder); }); + default: + return Protocols::InteractionModel::Status::UnsupportedAttribute; + } +} + +uint8_t ChimeCluster::GetSelectedChime() const +{ + return mSelectedChime; +} + +bool ChimeCluster::GetEnabled() const +{ + return mEnabled; +} + +// helper method to get the Chime Sounds one by one and encode into a list +CHIP_ERROR ChimeCluster::EncodeSupportedChimeSounds(const AttributeValueEncoder::ListEncodeHelper & encoder) +{ + + for (uint8_t i = 0; true; i++) + { + ChimeSoundStructType chimeSound; + + // Get the chime sound + // We pass in a MutableCharSpan to avoid any ownership issues - Delegate needs to use + // CopyCharSpanToMutableCharSpan to copy data in + char buffer[kMaxChimeSoundNameSize]; + MutableCharSpan name(buffer); + auto err = mDelegate.GetChimeSoundByIndex(i, chimeSound.chimeID, name); + + // return if we've run off the end of the Chime Sound List on the delegate + if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED) + { + return CHIP_NO_ERROR; + } + + ReturnErrorOnFailure(err); + + // set the name on the struct + chimeSound.name = name; + + // and now encode the struct + ReturnErrorOnFailure(encoder.Encode(chimeSound)); + + if (i == UINT8_MAX) // prevent overflow / infinite loop + { + // This should never happen if the delegate is well-behaved + return CHIP_ERROR_INTERNAL; + } + } + return CHIP_NO_ERROR; +} + +// helper method to check if the chimeID param is supported by the delegate +bool ChimeCluster::IsSupportedChimeID(uint8_t chimeID) +{ + uint8_t supportedChimeID; + for (uint8_t i = 0; mDelegate.GetChimeIDByIndex(i, supportedChimeID) != CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; i++) + { + if (supportedChimeID == chimeID) + { + return true; + } + + if (i == UINT8_MAX) // prevent overflow / infinite loop + { + // This should never happen if the delegate is well-behaved + return false; + } + } + return false; +} + +DataModel::ActionReturnStatus ChimeCluster::WriteAttribute(const DataModel::WriteAttributeRequest & request, + AttributeValueDecoder & decoder) +{ + switch (request.path.mAttributeId) + { + case SelectedChime::Id: { + uint8_t newValue; + ReturnErrorOnFailure(decoder.Decode(newValue)); + return DataModel::ActionReturnStatus(SetSelectedChime(newValue)); + } + case Enabled::Id: { + bool newValue; + ReturnErrorOnFailure(decoder.Decode(newValue)); + return DataModel::ActionReturnStatus(SetEnabled(newValue)); + } + default: + return Protocols::InteractionModel::Status::UnsupportedAttribute; + } +} + +Status ChimeCluster::SetSelectedChime(uint8_t chimeID) +{ + if (!IsSupportedChimeID(chimeID)) + { + return Protocols::InteractionModel::Status::NotFound; + } + if (mSelectedChime != chimeID) + { + mSelectedChime = chimeID; + NotifyAttributeChanged(Attributes::SelectedChime::Id); + + // TODO: Migrate to use context.attributeStorage + TEMPORARY_RETURN_IGNORED GetSafeAttributePersistenceProvider()->WriteScalarValue( + { mPath.mEndpointId, Chime::Id, Attributes::SelectedChime::Id }, mSelectedChime); + } + return Protocols::InteractionModel::Status::Success; +} + +Status ChimeCluster::SetEnabled(bool enabled) +{ + if (mEnabled != enabled) + { + mEnabled = enabled; + NotifyAttributeChanged(Attributes::Enabled::Id); + + // TODO: Migrate to use context.attributeStorage + TEMPORARY_RETURN_IGNORED GetSafeAttributePersistenceProvider()->WriteScalarValue( + { mPath.mEndpointId, Chime::Id, Attributes::Enabled::Id }, mEnabled); + } + return Protocols::InteractionModel::Status::Success; +} + +std::optional ChimeCluster::InvokeCommand(const DataModel::InvokeRequest & request, + chip::TLV::TLVReader & input_arguments, + CommandHandler * handler) +{ + switch (request.path.mCommandId) + { + case Commands::PlayChimeSound::Id: { + ChipLogDetail(Zcl, "Chime: PlayChimeSound"); + + Commands::PlayChimeSound::DecodableType commandData; + ReturnErrorOnFailure(commandData.Decode(input_arguments)); + return HandlePlayChimeSound(*handler, request.path, commandData); + } + default: + return Status::UnsupportedCommand; + } +} + +DataModel::ActionReturnStatus ChimeCluster::HandlePlayChimeSound(CommandHandler & aHandler, const ConcreteCommandPath & aPath, + const Commands::PlayChimeSound::DecodableType & commandData) +{ + // Immediately return if we're not enabled + // + if (!mEnabled) + { + return Status::Success; + } + + // If we have a provided Chime ID, ensure it is valid + // + uint8_t chimeIDToUse = mSelectedChime; + if (commandData.chimeID.HasValue()) + { + if (!IsSupportedChimeID(commandData.chimeID.Value())) + { + ChipLogError(Zcl, "Chime: Unknown Chime ID provided to PlayChimeSound"); + return Status::NotFound; + } + + chimeIDToUse = commandData.chimeID.Value(); + } + + Status status = mDelegate.PlayChimeSound(chimeIDToUse); + if (status == Status::Success) + { + // Generate the event + GenerateChimeStartedPlayingEvent(chimeIDToUse); + } + return status; +} + +void ChimeCluster::GenerateChimeStartedPlayingEvent(const uint8_t chimeID) +{ + Events::ChimeStartedPlaying::Type event; + EventNumber eventNumber; + + event.chimeID = chimeID; + + CHIP_ERROR err = LogEvent(event, GetPaths().data()->mEndpointId, eventNumber); + if (CHIP_NO_ERROR != err) + { + ChipLogError(Zcl, "Unable to generate ChimeStartedPlaying event"); + } +} + +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/chime-server/ChimeCluster.h b/src/app/clusters/chime-server/ChimeCluster.h new file mode 100644 index 00000000000..ba418cb9210 --- /dev/null +++ b/src/app/clusters/chime-server/ChimeCluster.h @@ -0,0 +1,172 @@ +/* + * + * Copyright (c) 2024-2025 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 + +namespace chip { +namespace app { +namespace Clusters { + +class ChimeDelegate; + +class ChimeCluster : public DefaultServerCluster +{ +public: + /** + * Creates a Chime Cluster instance. + * @param aEndpointId The endpoint on which this cluster exists. + * @param aDelegate A reference to the delegate to be used by this server. + * Note: the caller must ensure that the delegate lives throughout the instance's lifetime. + */ + ChimeCluster(EndpointId endpointId, ChimeDelegate & delegate); + ~ChimeCluster(); + + // Attribute Setters + /** + * Sets the SelectedChime attribute. Note, this also handles writing the new value into non-volatile storage. + * @param chimeSoundID The value to which the SelectedChime is to be set. + * @return Returns a ConstraintError if the chimeSoundID value is not valid. Returns Success otherwise. + */ + Protocols::InteractionModel::Status SetSelectedChime(uint8_t chimeSoundID); + + /** + * Sets the Enabled attribute. Note, this also handles writing the new value into non-volatile storage. + * @param Enabled The value to which the Enabled is to be set. + */ + Protocols::InteractionModel::Status SetEnabled(bool enabled); + + // Attribute Getters + /** + * @return The Current SelectedChime. + */ + uint8_t GetSelectedChime() const; + + /** + * @return The Enabled attribute. + */ + bool GetEnabled() const; + + // Cluster constants from the spec + static constexpr uint8_t kMaxChimeSoundNameSize = 48; + + /** + * @brief ServerClusterInterface methods. + */ + CHIP_ERROR Startup(ServerClusterContext & context) override; + + CHIP_ERROR Attributes(const ConcreteClusterPath & path, ReadOnlyBufferBuilder & builder) override; + + CHIP_ERROR AcceptedCommands(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) override; + + DataModel::ActionReturnStatus ReadAttribute(const DataModel::ReadAttributeRequest & request, + AttributeValueEncoder & encoder) override; + DataModel::ActionReturnStatus WriteAttribute(const DataModel::WriteAttributeRequest & request, + AttributeValueDecoder & decoder) override; + + std::optional InvokeCommand(const DataModel::InvokeRequest & request, + chip::TLV::TLVReader & input_arguments, + CommandHandler * handler) override; + +private: + ChimeDelegate & mDelegate; + + // Attribute local storage + uint8_t mSelectedChime = 0; + bool mEnabled = true; + // Helpers + // Loads all the persistent attributes from the KVS. + void LoadPersistentAttributes(); + + // Checks if the chimeID is supported by the delegate + bool IsSupportedChimeID(uint8_t chimeID); + + // Encodes all Installed Chime Sounds + CHIP_ERROR EncodeSupportedChimeSounds(const AttributeValueEncoder::ListEncodeHelper & encoder); + + DataModel::ActionReturnStatus HandlePlayChimeSound(CommandHandler & aHandler, const ConcreteCommandPath & aPath, + const Chime::Commands::PlayChimeSound::DecodableType & commandData); + + void GenerateChimeStartedPlayingEvent(const uint8_t chimeID); +}; + +/** @brief + * Defines methods for implementing application-specific logic for the Chime Cluster. + */ +class ChimeDelegate +{ +public: + ChimeDelegate() = default; + + virtual ~ChimeDelegate() = default; + + /** + * Get the installed chime sounds. + * @param index The index of the chime sound to be returned. It is assumed that chime sounds are indexable from 0 and with no + * gaps. + * @param chimeID a reference to the uint8_t variable that is to contain the ChimeID value. + * @param name A reference to the mutable char span which will be mutated to receive the chime sound name on success. Use + * CopyCharSpanToMutableCharSpan to copy into the MutableCharSpan. + * @return Returns a CHIP_NO_ERROR if there was no error and the chime sound details were returned successfully, + * CHIP_ERROR_PROVIDER_LIST_EXHAUSTED. if the index is beyond the list of available chime sounds. + * + * Note: This is used by the SDK to populate the InstalledChimeSounds attribute. If the contents of this list change, + * the device SHALL call the Instance's ReportInstalledChimeSoundsChange method to report that this attribute has changed. + */ + virtual CHIP_ERROR GetChimeSoundByIndex(uint8_t chimeIndex, uint8_t & chimeID, MutableCharSpan & name) = 0; + + /** + * Get the installed chime sound IDs + * @param index The index of the chime ID to be returned. It is assumed that chime sounds are indexable from 0 and with no + * gaps. + * @param chimeID a reference to the uint8_t variable that is to contain the ChimeID value. + * @return Returns a CHIP_NO_ERROR if there was no error and the ChimeID was returned successfully, + * CHIP_ERROR_PROVIDER_LIST_EXHAUSTED if the index is beyond the list of available chime sounds. + * + * Note: This is used by the SDK to help populate the InstalledChimeSounds attribute. If the contents of this list change, + * the device SHALL call the Instance's ReportInstalledChimeSoundsChange method to report that this attribute has changed. + */ + virtual CHIP_ERROR GetChimeIDByIndex(uint8_t chimeIndex, uint8_t & chimeID) = 0; + + // Commands + /** + * @brief Delegate should implement a handler to play the currently active chime sound. + * It should report Status::Success if successful and may + * return other Status codes if it fails + * @param chimeID the identifier for the chime to be played + */ + virtual Protocols::InteractionModel::Status PlayChimeSound(uint8_t chimeID) = 0; + +protected: + friend class ChimeCluster; + + // This is named mChimeServer instead of mChimeCluster to preserve backwards compatibility with legacy usage. + ChimeCluster * mChimeServer = nullptr; + + void SetChimeCluster(ChimeCluster * chimeCluster) { mChimeServer = chimeCluster; } + ChimeCluster * GetChimeCluster() const { return mChimeServer; } +}; + +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/chime-server/CodegenIntegration.cpp b/src/app/clusters/chime-server/CodegenIntegration.cpp new file mode 100644 index 00000000000..d8aa4fdec94 --- /dev/null +++ b/src/app/clusters/chime-server/CodegenIntegration.cpp @@ -0,0 +1,64 @@ +/* + * + * Copyright (c) 2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CodegenIntegration.h" +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using chip::app::Clusters::ChimeServer; + +ChimeServer::ChimeServer(EndpointId endpointId, ChimeDelegate & delegate) : mCluster(endpointId, delegate) {} + +ChimeServer::~ChimeServer() +{ + RETURN_SAFELY_IGNORED CodegenDataModelProvider::Instance().Registry().Unregister(&(mCluster.Cluster())); +} + +CHIP_ERROR ChimeServer::Init() +{ + return CodegenDataModelProvider::Instance().Registry().Register(mCluster.Registration()); +} + +Protocols::InteractionModel::Status ChimeServer::SetSelectedChime(uint8_t chimeSoundID) +{ + return mCluster.Cluster().SetSelectedChime(chimeSoundID); +} + +Protocols::InteractionModel::Status ChimeServer::SetEnabled(bool Enabled) +{ + return mCluster.Cluster().SetEnabled(Enabled); +} + +uint8_t ChimeServer::GetSelectedChime() +{ + return mCluster.Cluster().GetSelectedChime(); +} + +bool ChimeServer::GetEnabled() +{ + return mCluster.Cluster().GetEnabled(); +} + +void MatterChimeClusterInitCallback(EndpointId endpointId) {} +void MatterChimeClusterShutdownCallback(EndpointId endpointId) {} + +// Stub callbacks for ZAP generated code +void MatterChimePluginServerInitCallback() {} +void MatterChimePluginServerShutdownCallback() {} diff --git a/src/app/clusters/chime-server/CodegenIntegration.h b/src/app/clusters/chime-server/CodegenIntegration.h new file mode 100644 index 00000000000..c16cb67d306 --- /dev/null +++ b/src/app/clusters/chime-server/CodegenIntegration.h @@ -0,0 +1,84 @@ +/* + * + * Copyright (c) 2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace chip { +namespace app { +namespace Clusters { + +class ChimeServer +{ +public: + /** + * Creates a chime server instance. This is just a backwards compatibility wrapper around the ChimeCluster. + * @param aEndpointId The endpoint on which this cluster exists. This must match the zap configuration. + * @param aDelegate A reference to the delegate to be used by this server. + * Note: the caller must ensure that the delegate lives throughout the instance's lifetime. + */ + ChimeServer(EndpointId endpointId, ChimeDelegate & delegate); + ~ChimeServer(); + + /** + * Register the chime cluster instance with the codegen data model provider. + * @return Returns an error if registration fails. + */ + CHIP_ERROR Init(); + + // Attribute Setters + /** + * Sets the SelectedChime attribute. Note, this also handles writing the new value into non-volatile storage. + * @param chimeSoundID The value to which the SelectedChime is to be set. + * @return Returns a ConstraintError if the chimeSoundID value is not valid. Returns Success otherwise. + */ + Protocols::InteractionModel::Status SetSelectedChime(uint8_t chimeSoundID); + + /** + * Sets the Enabled attribute. Note, this also handles writing the new value into non-volatile storage. + * @param Enabled The value to which the Enabled is to be set. + */ + Protocols::InteractionModel::Status SetEnabled(bool Enabled); + + // Attribute Getters + /** + * @return The Current SelectedChime. + */ + uint8_t GetSelectedChime(); + + /** + * @return The Enabled attribute.. + */ + bool GetEnabled(); + + /** + * @return The endpoint ID. + */ + EndpointId GetEndpointId() { return mCluster.Cluster().GetPaths()[0].mEndpointId; } + + // Cluster constants from the spec + static constexpr uint8_t kMaxChimeSoundNameSize = ChimeCluster::kMaxChimeSoundNameSize; + + // The Code Driven ChimeCluster instance + chip::app::RegisteredServerCluster mCluster; +}; + +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/chime-server/README.md b/src/app/clusters/chime-server/README.md new file mode 100644 index 00000000000..64443441545 --- /dev/null +++ b/src/app/clusters/chime-server/README.md @@ -0,0 +1,131 @@ +# Chime Cluster + +The Chime cluster provides an interface for controlling a chime device, such as +a doorbell or other audible notification device. It allows clients to discover +available sounds and trigger them. + +## Overview + +This directory contains a code-driven C++ implementation of the Matter Chime +cluster server. This implementation (`ChimeCluster.h`) is designed for +flexibility, avoiding the tight coupling present in older codegen-based +implementations. + +It uses a delegate pattern (`chip::app::Clusters::ChimeDelegate`) to interact +with the application's sound resources and playback logic. + +## Usage + +To integrate the `ChimeCluster` into your application, follow these steps: + +### 1. Implement the Delegate + +Create a class that inherits from `chip::app::Clusters::ChimeDelegate` and +implement its virtual methods to provide the list of available sounds and handle +playback commands. + +```cpp +#include "app/clusters/chime-server/ChimeCluster.h" + +class MyChimeDelegate : public chip::app::Clusters::ChimeDelegate +{ +public: + CHIP_ERROR GetChimeSoundByIndex(uint8_t chimeIndex, uint8_t & chimeID, chip::MutableCharSpan & name) override + { + // Logic to return chime sound details by index + if (chimeIndex == 0) { + chimeID = 1; + return chip::CopyCharSpanToMutableCharSpan(chip::CharSpan("Ding Dong", 9), name); + } + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; + } + + CHIP_ERROR GetChimeIDByIndex(uint8_t chimeIndex, uint8_t & chimeID) override + { + // Logic to return chime ID by index + if (chimeIndex == 0) { + chimeID = 1; + return CHIP_NO_ERROR; + } + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; + } + + chip::Protocols::InteractionModel::Status PlayChimeSound() override + { + // Logic to play the currently selected sound + return chip::Protocols::InteractionModel::Status::Success; + } +}; +``` + +### 2. Instantiate Delegates and Cluster + +Instantiate your delegate and the `ChimeCluster` itself for each endpoint that +requires it. Using `RegisteredServerCluster` simplifies registration. + +```cpp +#include "app/server-cluster/ServerClusterInterfaceRegistry.h" + +// In a .cpp file +MyChimeDelegate gMyChimeDelegate; + +chip::app::RegisteredServerCluster gChimeCluster( + chip::EndpointId{ 1 }, gMyChimeDelegate); +``` + +### 3. Register the Cluster + +In your application's initialization sequence, register the cluster instance +with the `CodegenDataModelProvider`. This hooks the cluster into the Matter data +model and message processing framework. + +```cpp +#include "data-model-providers/codegen/CodegenDataModelProvider.h" + +void ApplicationInit() +{ + // ... other initializations + CHIP_ERROR err = chip::app::CodegenDataModelProvider::Instance().Registry().Register(gChimeCluster.Registration()); + VerifyOrDie(err == CHIP_NO_ERROR); + // ... +} +``` + +## Backwards Compatibility + +For backwards compatibility with applications that rely on older ZAP-generated +patterns, a legacy API is provided in `CodegenIntegration.h` and +`CodegenIntegration.cpp`. This compatibility layer uses a `ChimeServer` wrapper +class. + +The `ChimeDelegate` also maintains a protected member `mChimeServer` (accessible +via `GetChimeCluster()`) to support legacy delegates that accessed the server +instance directly. + +### Migrating from the Legacy API + +We recommend migrating to the new, direct instantiation method to improve +performance and reduce your application's footprint. + +#### Recommended Usage + +The new approach is to instantiate the cluster directly and register it with the +`CodegenDataModelProvider`, as detailed in the "Usage" section above. + +#### Legacy Usage (Discouraged) + +Previously, you might have used `ChimeServer` directly: + +```cpp +// This old pattern is found in `app/clusters/chime-server/chime-server.h` +// and is now considered legacy wrapper. + +#include + +MyChimeDelegate gMyChimeDelegate; +chip::app::Clusters::ChimeServer gChimeServer(chip::EndpointId{ 1 }, gMyChimeDelegate); + +void ApplicationInit() { + gChimeServer.Init(); // Registers internally +} +``` diff --git a/src/app/clusters/chime-server/app_config_dependent_sources.cmake b/src/app/clusters/chime-server/app_config_dependent_sources.cmake index 8fb2215fc84..d8a6cc77b70 100644 --- a/src/app/clusters/chime-server/app_config_dependent_sources.cmake +++ b/src/app/clusters/chime-server/app_config_dependent_sources.cmake @@ -16,6 +16,15 @@ TARGET_SOURCES( ${APP_TARGET} PRIVATE - "${CLUSTER_DIR}/chime-server.cpp" + "${CLUSTER_DIR}/CodegenIntegration.h" + "${CLUSTER_DIR}/CodegenIntegration.cpp" "${CLUSTER_DIR}/chime-server.h" +) + +# These are the things that BUILD.gn dependencies would pull +TARGET_SOURCES( + ${APP_TARGET} + PRIVATE + "${CLUSTER_DIR}/ChimeCluster.cpp" + "${CLUSTER_DIR}/ChimeCluster.h" ) \ No newline at end of file diff --git a/src/app/clusters/chime-server/app_config_dependent_sources.gni b/src/app/clusters/chime-server/app_config_dependent_sources.gni index afde12b56bb..18c14c092f2 100644 --- a/src/app/clusters/chime-server/app_config_dependent_sources.gni +++ b/src/app/clusters/chime-server/app_config_dependent_sources.gni @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. app_config_dependent_sources = [ - "chime-server.cpp", + "CodegenIntegration.cpp", + "CodegenIntegration.h", "chime-server.h", ] diff --git a/src/app/clusters/chime-server/chime-server.cpp b/src/app/clusters/chime-server/chime-server.cpp deleted file mode 100644 index 3609b2aa16e..00000000000 --- a/src/app/clusters/chime-server/chime-server.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/* - * - * Copyright (c) 2024 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/****************************************************************************' - * @file - * @brief Implementation for the Chime Server Cluster - ***************************************************************************/ - -#include "chime-server.h" - -#include -#include -#include -#include -#include - -using namespace chip; -using namespace chip::app; -using namespace chip::app::Clusters::Chime; -using namespace chip::app::Clusters::Chime::Attributes; -using chip::Protocols::InteractionModel::Status; -using ChimeSoundStructType = Structs::ChimeSoundStruct::Type; - -namespace chip { -namespace app { -namespace Clusters { - -ChimeServer::ChimeServer(EndpointId endpointId, ChimeDelegate & delegate) : - AttributeAccessInterface(MakeOptional(endpointId), Chime::Id), CommandHandlerInterface(MakeOptional(endpointId), Chime::Id), - mDelegate(delegate), mSelectedChime(0), mEnabled(true) -{ - mDelegate.SetChimeServer(this); -} - -ChimeServer::~ChimeServer() -{ - // null out the ref to us on the delegate - mDelegate.SetChimeServer(nullptr); - - // unregister - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); - AttributeAccessInterfaceRegistry::Instance().Unregister(this); -} - -CHIP_ERROR ChimeServer::Init() -{ - LoadPersistentAttributes(); - - VerifyOrReturnError(AttributeAccessInterfaceRegistry::Instance().Register(this), CHIP_ERROR_INTERNAL); - ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(this)); - return CHIP_NO_ERROR; -} - -void ChimeServer::LoadPersistentAttributes() -{ - // Load Active Chime ID - uint8_t storedSelectedChime = 0; - CHIP_ERROR err = GetSafeAttributePersistenceProvider()->ReadScalarValue( - ConcreteAttributePath(GetEndpointId(), Chime::Id, SelectedChime::Id), storedSelectedChime); - if (err == CHIP_NO_ERROR) - { - mSelectedChime = storedSelectedChime; - } - else - { - // otherwise defaults - ChipLogDetail(Zcl, "Chime: Unable to load the SelectedChime attribute from the KVS. Defaulting to %u", mSelectedChime); - } - - // Load Enabled - bool storedEnabled = false; - err = GetSafeAttributePersistenceProvider()->ReadScalarValue(ConcreteAttributePath(GetEndpointId(), Chime::Id, Enabled::Id), - storedEnabled); - if (err == CHIP_NO_ERROR) - { - mEnabled = storedEnabled; - } - else - { - // otherwise take the default - ChipLogDetail(Zcl, "Chime: Unable to load the Enabled attribute from the KVS. Defaulting to %u", mEnabled); - } -} - -// AttributeAccessInterface -CHIP_ERROR ChimeServer::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) -{ - VerifyOrDie(aPath.mClusterId == Chime::Id); - - switch (aPath.mAttributeId) - { - case SelectedChime::Id: - ReturnErrorOnFailure(aEncoder.Encode(mSelectedChime)); - break; - case Enabled::Id: - ReturnErrorOnFailure(aEncoder.Encode(mEnabled)); - break; - case InstalledChimeSounds::Id: - ChimeServer * cs = this; - CHIP_ERROR err = - aEncoder.EncodeList([cs](const auto & encoder) -> CHIP_ERROR { return cs->EncodeSupportedChimeSounds(encoder); }); - return err; - } - - return CHIP_NO_ERROR; -} - -uint8_t ChimeServer::GetSelectedChime() const -{ - return mSelectedChime; -} - -bool ChimeServer::GetEnabled() const -{ - return mEnabled; -} - -// helper method to get the Chime Sounds one by one and encode into a list -CHIP_ERROR ChimeServer::EncodeSupportedChimeSounds(const AttributeValueEncoder::ListEncodeHelper & encoder) -{ - - for (uint8_t i = 0; true; i++) - { - ChimeSoundStructType chimeSound; - - // Get the chime sound - // We pass in a MutableCharSpan to avoid any ownership issues - Delegate needs to use - // CopyCharSpanToMutableCharSpan to copy data in - char buffer[kMaxChimeSoundNameSize]; - MutableCharSpan name(buffer); - auto err = mDelegate.GetChimeSoundByIndex(i, chimeSound.chimeID, name); - - // return if we've run off the end of the Chime Sound List on the delegate - if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED) - { - return CHIP_NO_ERROR; - } - - ReturnErrorOnFailure(err); - - // set the name on the struct - chimeSound.name = name; - - // and now encode the struct - ReturnErrorOnFailure(encoder.Encode(chimeSound)); - } - return CHIP_NO_ERROR; -} - -// helper method to check if the chimeID param is supported by the delegate -bool ChimeServer::IsSupportedChimeID(uint8_t chimeID) -{ - uint8_t supportedChimeID; - for (uint8_t i = 0; mDelegate.GetChimeIDByIndex(i, supportedChimeID) != CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; i++) - { - if (supportedChimeID == chimeID) - { - return true; - } - } - - ChipLogDetail(Zcl, "Cannot find a supported ChimeID with value %u", chimeID); - return false; -} - -CHIP_ERROR ChimeServer::Write(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder) -{ - VerifyOrDie(aPath.mClusterId == Chime::Id); - Status status; - - switch (aPath.mAttributeId) - { - case SelectedChime::Id: { - uint8_t newValue; - ReturnErrorOnFailure(aDecoder.Decode(newValue)); - status = SetSelectedChime(newValue); - return StatusIB(status).ToChipError(); - } - case Enabled::Id: { - bool newValue; - ReturnErrorOnFailure(aDecoder.Decode(newValue)); - status = SetEnabled(newValue); - return StatusIB(status).ToChipError(); - } - - default: - // Unknown attribute - return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); - } -} - -Status ChimeServer::SetSelectedChime(uint8_t chimeID) -{ - if (!IsSupportedChimeID(chimeID)) - { - return Protocols::InteractionModel::Status::NotFound; - } - - bool activeIDChanged = !(mSelectedChime == chimeID); - if (activeIDChanged) - { - mSelectedChime = chimeID; - - // Write new value to persistent storage. - auto endpointId = GetEndpointId(); - ConcreteAttributePath path = ConcreteAttributePath(endpointId, Chime::Id, SelectedChime::Id); - GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mSelectedChime); - - // and mark as dirty - MatterReportingAttributeChangeCallback(path); - } - return Protocols::InteractionModel::Status::Success; -} - -Status ChimeServer::SetEnabled(bool Enabled) -{ - bool enableChanged = !(mEnabled == Enabled); - - if (enableChanged) - { - mEnabled = Enabled; - - // Write new value to persistent storage. - auto endpointId = GetEndpointId(); - ConcreteAttributePath path = ConcreteAttributePath(endpointId, Chime::Id, Enabled::Id); - GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mEnabled); - - // and mark as dirty - MatterReportingAttributeChangeCallback(path); - } - - return Protocols::InteractionModel::Status::Success; -} - -void ChimeServer::InvokeCommand(HandlerContext & ctx) -{ - switch (ctx.mRequestPath.mCommandId) - { - case Commands::PlayChimeSound::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & innerCtx, const auto & req) { HandlePlayChimeSound(innerCtx, req); }); - break; - } -} - -void ChimeServer::HandlePlayChimeSound(HandlerContext & ctx, const Commands::PlayChimeSound::DecodableType & req) -{ - - ChipLogDetail(Zcl, "Chime: PlayChimeSound"); - Status status = Status::Success; - - // Only invoke the delegate if enabled, otherwise don't play a sound, and "silently" return - if (mEnabled) - { - // call the delegate to play the chime - status = mDelegate.PlayChimeSound(); - } - - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); -} - -} // namespace Clusters -} // namespace app -} // namespace chip - -/** @brief Chime Cluster Server Init - * - * Server Init - * - */ -void MatterChimePluginServerInitCallback() {} -void MatterChimePluginServerShutdownCallback() {} diff --git a/src/app/clusters/chime-server/chime-server.h b/src/app/clusters/chime-server/chime-server.h index 1a125cc591c..7864b70ee19 100644 --- a/src/app/clusters/chime-server/chime-server.h +++ b/src/app/clusters/chime-server/chime-server.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2024 Project CHIP Authors + * Copyright (c) 2024-2025 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,161 +18,7 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include +// Note: This file exists for backwards compatibility only. +// New code should directly use ChimeCluster.h instead. -namespace chip { -namespace app { -namespace Clusters { - -class ChimeDelegate; - -class ChimeServer : private AttributeAccessInterface, private CommandHandlerInterface -{ -public: - /** - * Creates a chime server instance. The Init() function needs to be called for this instance to be registered and - * called by the interaction model at the appropriate times. - * @param aEndpointId The endpoint on which this cluster exists. This must match the zap configuration. - * @param aDelegate A reference to the delegate to be used by this server. - * Note: the caller must ensure that the delegate lives throughout the instance's lifetime. - */ - ChimeServer(EndpointId endpointId, ChimeDelegate & delegate); - ~ChimeServer(); - - /** - * Initialise the chime server instance. - * @return Returns an error if the CommandHandler or AttributeHandler registration fails. - */ - CHIP_ERROR Init(); - - // Attribute Setters - /** - * Sets the SelectedChime attribute. Note, this also handles writing the new value into non-volatile storage. - * @param chimeSoundID The value to which the SelectedChime is to be set. - * @return Returns a ConstraintError if the chimeSoundID value is not valid. Returns Success otherwise. - */ - Protocols::InteractionModel::Status SetSelectedChime(uint8_t chimeSoundID); - - /** - * Sets the Enabled attribute. Note, this also handles writing the new value into non-volatile storage. - * @param Enabled The value to which the Enabled is to be set. - */ - Protocols::InteractionModel::Status SetEnabled(bool Enabled); - - // Attribute Getters - /** - * @return The Current SelectedChime. - */ - uint8_t GetSelectedChime() const; - - /** - * @return The Enabled attribute.. - */ - bool GetEnabled() const; - - /** - * @return The endpoint ID. - */ - EndpointId GetEndpointId() { return AttributeAccessInterface::GetEndpointId().Value(); } - - // Cluster constants from the spec - static constexpr uint8_t kMaxChimeSoundNameSize = 48; - - // List Change Reporting - /** - * Reports that the contents of the InstalledChimeSounds attribute have changed. - * The device SHALL call this method whenever it changes the list of installed chime sounds. - */ - void ReportInstalledChimeSoundsChange(); - -private: - ChimeDelegate & mDelegate; - - // Attribute local storage - uint8_t mSelectedChime; - bool mEnabled; - - // AttributeAccessInterface - CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; - CHIP_ERROR Write(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder) override; - - // CommandHandlerInterface - void InvokeCommand(HandlerContext & ctx) override; - void HandlePlayChimeSound(HandlerContext & ctx, const Chime::Commands::PlayChimeSound::DecodableType & req); - - // Helpers - // Loads all the persistent attributes from the KVS. - void LoadPersistentAttributes(); - - // Checks if the chimeID is supported by the delegate - bool IsSupportedChimeID(uint8_t chimeID); - - // Encodes all Installed Chime Sounds - CHIP_ERROR EncodeSupportedChimeSounds(const AttributeValueEncoder::ListEncodeHelper & encoder); -}; - -/** @brief - * Defines methods for implementing application-specific logic for the Chime Cluster. - */ -class ChimeDelegate -{ -public: - ChimeDelegate() = default; - - virtual ~ChimeDelegate() = default; - - /** - * Get the installed chime sounds. - * @param index The index of the chime sound to be returned. It is assumed that chime sounds are indexable from 0 and with no - * gaps. - * @param chimeID a reference to the uint8_t variable that is to contain the ChimeID value. - * @param name A reference to the mutable char span which will be mutated to receive the chime sound name on success. Use - * CopyCharSpanToMutableCharSpan to copy into the MutableCharSpan. - * @return Returns a CHIP_NO_ERROR if there was no error and the chime sound details were returned successfully, - * CHIP_ERROR_NOT_FOUND if the index in beyond the list of available chime sounds. - * - * Note: This is used by the SDK to populate the InstalledChimeSounds attribute. If the contents of this list change, - * the device SHALL call the Instance's ReportInstalledChimeSoundsChange method to report that this attribute has changed. - */ - virtual CHIP_ERROR GetChimeSoundByIndex(uint8_t chimeIndex, uint8_t & chimeID, MutableCharSpan & name) = 0; - - /** - * Get the installed chime sound IDs - * @param index The index of the chime ID to be returned. It is assumed that chime sounds are indexable from 0 and with no - * gaps. - * @param chimeID a reference to the uint8_t variable that is to contain the ChimeID value. - * @return Returns a CHIP_NO_ERROR if there was no error and the ChimeID was returned successfully, - * CHIP_ERROR_NOT_FOUND if the index in beyond the list of available chime sounds. - * - * Note: This is used by the SDK to help populate the InstalledChimeSounds attribute. If the contents of this list change, - * the device SHALL call the Instance's ReportInstalledChimeSoundsChange method to report that this attribute has changed. - */ - virtual CHIP_ERROR GetChimeIDByIndex(uint8_t chimeIndex, uint8_t & chimeID) = 0; - - // Commands - /** - * @brief Delegate should implement a handler to play the currently active chime sound. - * It should report Status::Success if successful and may - * return other Status codes if it fails - */ - virtual Protocols::InteractionModel::Status PlayChimeSound() = 0; - -protected: - friend class ChimeServer; - - ChimeServer * mChimeServer = nullptr; - - // sets the Chime Server pointer - void SetChimeServer(ChimeServer * chimeServer) { mChimeServer = chimeServer; } - ChimeServer * GetChimeServer() const { return mChimeServer; } -}; - -} // namespace Clusters -} // namespace app -} // namespace chip +#include diff --git a/src/app/clusters/chime-server/tests/BUILD.gn b/src/app/clusters/chime-server/tests/BUILD.gn new file mode 100644 index 00000000000..0bcf5ef1673 --- /dev/null +++ b/src/app/clusters/chime-server/tests/BUILD.gn @@ -0,0 +1,56 @@ +# Copyright (c) 2025 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") +import("${chip_root}/build/chip/chip_test_suite.gni") + +chip_test_suite("tests") { + output_name = "TestChimeCluster" + + # Comment out the unit test due to missing dependencies + # test_sources = [ "TestChimeCluster.cpp" ] + + public_deps = [ + "${chip_root}/src/app/clusters/chime-server", + "${chip_root}/src/app/clusters/testing", + "${chip_root}/src/app/data-model-provider/tests:encode-decode", + "${chip_root}/src/app/server-cluster/testing:testing", + "${chip_root}/src/lib/support", + ] +} + +chip_test_suite("tests-backwards-compatibility") { + import( + "${chip_root}/src/app/clusters/chime-server/app_config_dependent_sources.gni") + + output_name = "TestChimeClusterBackwardsCompatibility" + + # Comment out the unit test due to missing dependencies + # test_sources = [ "TestChimeClusterBackwardsCompatibility.cpp" ] + + # Prefix app_config_dependent_sources with "../" and add to the sources list + sources = [] + foreach(file, app_config_dependent_sources) { + sources += [ "../" + file ] + } + + public_deps = [ + "${chip_root}/src/app/clusters/chime-server", + "${chip_root}/src/app/clusters/testing", + "${chip_root}/src/app/data-model-provider/tests:encode-decode", + "${chip_root}/src/app/server-cluster/testing:testing", + "${chip_root}/src/data-model-providers/codegen/tests:mock_model", + "${chip_root}/src/lib/support", + ] +} diff --git a/src/app/clusters/chime-server/tests/TestChimeCluster.cpp b/src/app/clusters/chime-server/tests/TestChimeCluster.cpp new file mode 100644 index 00000000000..5ab0740b5d8 --- /dev/null +++ b/src/app/clusters/chime-server/tests/TestChimeCluster.cpp @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::Chime; +using namespace chip::Testing; + +namespace { + +constexpr EndpointId kTestEndpointId = 1; + +class MockChimeDelegate : public ChimeDelegate +{ +public: + struct MockChimeSound + { + uint8_t id; + std::string name; + }; + std::vector sounds = { { 1, "Ding Dong" }, { 2, "Ring Ring" } }; + + bool playChimeSoundCalled = false; + Protocols::InteractionModel::Status playChimeSoundStatus = Protocols::InteractionModel::Status::Success; + CHIP_ERROR getChimeSoundByIndexError = CHIP_NO_ERROR; + + CHIP_ERROR GetChimeSoundByIndex(uint8_t chimeIndex, uint8_t & chimeID, MutableCharSpan & name) override + { + if (getChimeSoundByIndexError != CHIP_NO_ERROR) + { + return getChimeSoundByIndexError; + } + if (chimeIndex < sounds.size()) + { + chimeID = sounds[chimeIndex].id; + return CopyCharSpanToMutableCharSpan(CharSpan(sounds[chimeIndex].name.c_str(), sounds[chimeIndex].name.length()), name); + } + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; + } + CHIP_ERROR GetChimeIDByIndex(uint8_t chimeIndex, uint8_t & chimeID) override + { + if (chimeIndex < sounds.size()) + { + chimeID = sounds[chimeIndex].id; + return CHIP_NO_ERROR; + } + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; + } + Protocols::InteractionModel::Status PlayChimeSound(uint8_t chimeID) override + { + playChimeSoundCalled = true; + return playChimeSoundStatus; + } +}; + +struct TestChimeCluster : public ::testing::Test +{ + static void SetUpTestSuite() { ASSERT_EQ(Platform::MemoryInit(), CHIP_NO_ERROR); } + static void TearDownTestSuite() { Platform::MemoryShutdown(); } + + void SetUp() override + { + VerifyOrDie(mPersistenceProvider.Init(&mClusterTester.GetServerClusterContext().storage) == CHIP_NO_ERROR); + app::SetSafeAttributePersistenceProvider(&mPersistenceProvider); + EXPECT_EQ(mCluster.Startup(mClusterTester.GetServerClusterContext()), CHIP_NO_ERROR); + } + + void TearDown() override { app::SetSafeAttributePersistenceProvider(nullptr); } + + MockChimeDelegate mMockDelegate; + + ChimeCluster mCluster{ kTestEndpointId, mMockDelegate }; + + ClusterTester mClusterTester{ mCluster }; + + app::DefaultSafeAttributePersistenceProvider mPersistenceProvider; +}; + +TEST_F(TestChimeCluster, TestAttributesList) +{ + ReadOnlyBufferBuilder listBuilder; + EXPECT_EQ(mCluster.Attributes(ConcreteClusterPath(kTestEndpointId, Chime::Id), listBuilder), CHIP_NO_ERROR); + + ReadOnlyBufferBuilder expectedListBuilder; + AttributeListBuilder attributeListBuilder(expectedListBuilder); + EXPECT_EQ(attributeListBuilder.Append(Span(Chime::Attributes::kMandatoryMetadata), {}), CHIP_NO_ERROR); + + EXPECT_TRUE(EqualAttributeSets(listBuilder.TakeBuffer(), expectedListBuilder.TakeBuffer())); +} + +TEST_F(TestChimeCluster, TestAcceptedCommands) +{ + ReadOnlyBufferBuilder listBuilder; + EXPECT_EQ(mCluster.AcceptedCommands(ConcreteClusterPath(kTestEndpointId, Chime::Id), listBuilder), CHIP_NO_ERROR); + + static constexpr DataModel::AcceptedCommandEntry kExpectedCommands[] = { + Chime::Commands::PlayChimeSound::kMetadataEntry, + }; + + ReadOnlyBufferBuilder expectedListBuilder; + EXPECT_EQ(expectedListBuilder.ReferenceExisting(kExpectedCommands), CHIP_NO_ERROR); + + EXPECT_TRUE(EqualAcceptedCommandSets(listBuilder.TakeBuffer(), expectedListBuilder.TakeBuffer())); +} + +TEST_F(TestChimeCluster, TestDelegateErrors) +{ + // Test 1: PlayChimeSound delegate failure + mMockDelegate.playChimeSoundStatus = Protocols::InteractionModel::Status::Busy; + auto result = mClusterTester.Invoke(Commands::PlayChimeSound::Type()); + EXPECT_FALSE(result.IsSuccess()); + EXPECT_TRUE(mMockDelegate.playChimeSoundCalled); + if (result.status.has_value()) + { + EXPECT_EQ(result.status.value().GetStatusCode().GetStatus(), Protocols::InteractionModel::Status::Busy); + } + + // Test 2: GetChimeSoundByIndex delegate failure + mMockDelegate.getChimeSoundByIndexError = CHIP_ERROR_INTERNAL; + Attributes::InstalledChimeSounds::TypeInfo::DecodableType list; + EXPECT_NE(mClusterTester.ReadAttribute(Attributes::InstalledChimeSounds::Id, list), CHIP_NO_ERROR); +} + +TEST_F(TestChimeCluster, TestNoOpWrites) +{ + // 1. Write Initial Value (Change) + EXPECT_EQ(mClusterTester.WriteAttribute(Attributes::SelectedChime::Id, static_cast(1)), CHIP_NO_ERROR); + + auto & dirtyList = mClusterTester.GetDirtyList(); + EXPECT_EQ(dirtyList.size(), 1u); + dirtyList.clear(); + + // 2. Write Same Value (No-Op) + EXPECT_EQ(mClusterTester.WriteAttribute(Attributes::SelectedChime::Id, static_cast(1)), CHIP_NO_ERROR); + EXPECT_EQ(dirtyList.size(), 0u); + + // 3. Write Enabled Initial (Change) + EXPECT_EQ(mClusterTester.WriteAttribute(Attributes::Enabled::Id, false), CHIP_NO_ERROR); + EXPECT_EQ(dirtyList.size(), 1u); + dirtyList.clear(); + + // 4. Write Enabled Same (No-Op) + EXPECT_EQ(mClusterTester.WriteAttribute(Attributes::Enabled::Id, false), CHIP_NO_ERROR); + EXPECT_EQ(dirtyList.size(), 0u); +} + +TEST_F(TestChimeCluster, TestReadClusterRevision) +{ + uint16_t clusterRevision = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::ClusterRevision::Id, clusterRevision), CHIP_NO_ERROR); + EXPECT_EQ(clusterRevision, kRevision); +} + +TEST_F(TestChimeCluster, TestReadFeatureMap) +{ + uint32_t featureMap = 1; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::FeatureMap::Id, featureMap), CHIP_NO_ERROR); + EXPECT_EQ(featureMap, 0u); +} + +TEST_F(TestChimeCluster, TestReadSelectedChime) +{ + uint8_t selectedChime = 1; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::SelectedChime::Id, selectedChime), CHIP_NO_ERROR); + EXPECT_EQ(selectedChime, 0); +} + +TEST_F(TestChimeCluster, TestReadEnabled) +{ + bool enabled = false; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::Enabled::Id, enabled), CHIP_NO_ERROR); + EXPECT_EQ(enabled, true); +} + +TEST_F(TestChimeCluster, TestInstalledChimeSoundsLifecycle) +{ + // 1. Verify initial content (TestReadInstalledChimeSounds) + Attributes::InstalledChimeSounds::TypeInfo::DecodableType list; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::InstalledChimeSounds::Id, list), CHIP_NO_ERROR); + + auto it = list.begin(); + ASSERT_TRUE(it.Next()); + EXPECT_EQ(it.GetValue().chimeID, 1); + EXPECT_TRUE(it.GetValue().name.data_equal(CharSpan("Ding Dong", 9))); + + ASSERT_TRUE(it.Next()); + EXPECT_EQ(it.GetValue().chimeID, 2); + EXPECT_TRUE(it.GetValue().name.data_equal(CharSpan("Ring Ring", 9))); + + ASSERT_FALSE(it.Next()); + + // 2. Change content + mMockDelegate.sounds.push_back({ 3, "New Sound" }); + + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::InstalledChimeSounds::Id, list), CHIP_NO_ERROR); + it = list.begin(); + ASSERT_TRUE(it.Next()); + EXPECT_EQ(it.GetValue().chimeID, 1); + ASSERT_TRUE(it.Next()); + EXPECT_EQ(it.GetValue().chimeID, 2); + ASSERT_TRUE(it.Next()); + EXPECT_EQ(it.GetValue().chimeID, 3); + EXPECT_TRUE(it.GetValue().name.data_equal(CharSpan("New Sound", 9))); + ASSERT_FALSE(it.Next()); +} + +TEST_F(TestChimeCluster, TestWriteAttributes) +{ + // Test writing SelectedChime + // Write valid value (1) + EXPECT_EQ(mClusterTester.WriteAttribute(Attributes::SelectedChime::Id, static_cast(1)), CHIP_NO_ERROR); + uint8_t selectedChime = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::SelectedChime::Id, selectedChime), CHIP_NO_ERROR); + EXPECT_EQ(selectedChime, 1); + + // Write valid value (2) + EXPECT_EQ(mClusterTester.WriteAttribute(Attributes::SelectedChime::Id, static_cast(2)), CHIP_NO_ERROR); + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::SelectedChime::Id, selectedChime), CHIP_NO_ERROR); + EXPECT_EQ(selectedChime, 2); + + // Write invalid value (3) - should fail with NotFound as per spec + EXPECT_EQ(mClusterTester.WriteAttribute(Attributes::SelectedChime::Id, static_cast(3)), + Protocols::InteractionModel::Status::NotFound); + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::SelectedChime::Id, selectedChime), CHIP_NO_ERROR); + EXPECT_EQ(selectedChime, 2); // Should remain unchanged + + // Test writing Enabled + EXPECT_EQ(mClusterTester.WriteAttribute(Attributes::Enabled::Id, false), CHIP_NO_ERROR); + bool enabled = true; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::Enabled::Id, enabled), CHIP_NO_ERROR); + EXPECT_EQ(enabled, false); + + EXPECT_EQ(mClusterTester.WriteAttribute(Attributes::Enabled::Id, true), CHIP_NO_ERROR); + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::Enabled::Id, enabled), CHIP_NO_ERROR); + EXPECT_EQ(enabled, true); +} + +TEST_F(TestChimeCluster, TestPersistence) +{ + TestServerClusterContext context; + app::DefaultSafeAttributePersistenceProvider persistenceProvider; + EXPECT_EQ(persistenceProvider.Init(&context.Get().storage), CHIP_NO_ERROR); + app::SetSafeAttributePersistenceProvider(&persistenceProvider); + MockChimeDelegate mockDelegate; + + // 1. Initial startup, verify default values + { + ChimeCluster cluster(kTestEndpointId, mockDelegate); + EXPECT_EQ(cluster.Startup(context.Get()), CHIP_NO_ERROR); + ClusterTester tester(cluster); + + uint8_t selectedChime = 1; + EXPECT_EQ(tester.ReadAttribute(Attributes::SelectedChime::Id, selectedChime), CHIP_NO_ERROR); + EXPECT_EQ(selectedChime, 0); + + bool enabled = false; + EXPECT_EQ(tester.ReadAttribute(Attributes::Enabled::Id, enabled), CHIP_NO_ERROR); + EXPECT_EQ(enabled, true); + + // Modify values + EXPECT_EQ(tester.WriteAttribute(Attributes::SelectedChime::Id, static_cast(2)), CHIP_NO_ERROR); + EXPECT_EQ(tester.WriteAttribute(Attributes::Enabled::Id, false), CHIP_NO_ERROR); + } + + // 2. Restart (create new cluster instance), verify modified values are loaded + { + ChimeCluster cluster(kTestEndpointId, mockDelegate); + EXPECT_EQ(cluster.Startup(context.Get()), CHIP_NO_ERROR); + chip::Testing::ClusterTester tester(cluster); + + uint8_t selectedChime; + EXPECT_EQ(tester.ReadAttribute(Attributes::SelectedChime::Id, selectedChime), CHIP_NO_ERROR); + EXPECT_EQ(selectedChime, 2); + + bool enabled; + EXPECT_EQ(tester.ReadAttribute(Attributes::Enabled::Id, enabled), CHIP_NO_ERROR); + EXPECT_EQ(enabled, false); + } +} + +TEST_F(TestChimeCluster, TestPlayChimeSound) +{ + // 1. Test PlayChimeSound when Enabled is true (default) + auto result = mClusterTester.Invoke(Commands::PlayChimeSound::Type()); + EXPECT_TRUE(result.IsSuccess()); + EXPECT_TRUE(mMockDelegate.playChimeSoundCalled); + + // 2. Test PlayChimeSound when Enabled is false + mMockDelegate.playChimeSoundCalled = false; + EXPECT_EQ(mClusterTester.WriteAttribute(Attributes::Enabled::Id, false), CHIP_NO_ERROR); + + result = mClusterTester.Invoke(Commands::PlayChimeSound::Type()); + EXPECT_TRUE(result.IsSuccess()); + EXPECT_FALSE(mMockDelegate.playChimeSoundCalled); +} + +} // namespace diff --git a/src/app/clusters/chime-server/tests/TestChimeClusterBackwardsCompatibility.cpp b/src/app/clusters/chime-server/tests/TestChimeClusterBackwardsCompatibility.cpp new file mode 100644 index 00000000000..29ad948650e --- /dev/null +++ b/src/app/clusters/chime-server/tests/TestChimeClusterBackwardsCompatibility.cpp @@ -0,0 +1,155 @@ +/* + * + * Copyright (c) 2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::Chime; + +void MatterChimePluginServerInitCallback(); +// Stub for DataModelHandler init function +void InitDataModelHandler() {} + +namespace { + +constexpr EndpointId kTestEndpointId = 1; + +class MockChimeDelegate : public ChimeDelegate +{ +public: + bool playChimeSoundCalled = false; + + CHIP_ERROR GetChimeSoundByIndex(uint8_t chimeIndex, uint8_t & chimeID, MutableCharSpan & name) override + { + if (chimeIndex == 0) + { + chimeID = 1; + return CopyCharSpanToMutableCharSpan(CharSpan("Ding Dong", 9), name); + } + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; + } + CHIP_ERROR GetChimeIDByIndex(uint8_t chimeIndex, uint8_t & chimeID) override + { + if (chimeIndex == 0) + { + chimeID = 1; + return CHIP_NO_ERROR; + } + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; + } + Protocols::InteractionModel::Status PlayChimeSound() override + { + playChimeSoundCalled = true; + return Protocols::InteractionModel::Status::Success; + } +}; + +struct TestChimeClusterBackwardsCompatibility : public ::testing::Test +{ + static void SetUpTestSuite() { ASSERT_EQ(Platform::MemoryInit(), CHIP_NO_ERROR); } + static void TearDownTestSuite() { Platform::MemoryShutdown(); } + + void SetUp() override + { + VerifyOrDie(mPersistenceProvider.Init(&mClusterTester.GetServerClusterContext().storage) == CHIP_NO_ERROR); + app::SetSafeAttributePersistenceProvider(&mPersistenceProvider); + EXPECT_EQ(mChimeServer.Init(), CHIP_NO_ERROR); + EXPECT_EQ(mChimeServer.mCluster.Cluster().Startup(mClusterTester.GetServerClusterContext()), CHIP_NO_ERROR); + } + + void TearDown() override { app::SetSafeAttributePersistenceProvider(nullptr); } + + MockChimeDelegate mMockDelegate; + + ChimeServer mChimeServer{ kTestEndpointId, mMockDelegate }; + + chip::Testing::ClusterTester mClusterTester{ mChimeServer.mCluster.Cluster() }; + + app::DefaultSafeAttributePersistenceProvider mPersistenceProvider; +}; + +TEST_F(TestChimeClusterBackwardsCompatibility, TestLegacyInstantiation) +{ + // Verify it registered with CodegenDataModelProvider + EXPECT_TRUE(CodegenDataModelProvider::Instance().Registry().Get(ConcreteClusterPath(kTestEndpointId, Chime::Id)) != nullptr); + + // Test Reading Attribute (via ChimeCluster logic) + uint8_t selectedChime = 1; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::SelectedChime::Id, selectedChime), CHIP_NO_ERROR); + EXPECT_EQ(selectedChime, 0); + + // Test Writing Attribute (via ChimeCluster logic) + EXPECT_EQ(mClusterTester.WriteAttribute(Attributes::SelectedChime::Id, static_cast(1)), CHIP_NO_ERROR); + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::SelectedChime::Id, selectedChime), CHIP_NO_ERROR); + EXPECT_EQ(selectedChime, 1); + + // Test Command (via ChimeCluster logic, invoking delegate) + auto result = mClusterTester.Invoke(Commands::PlayChimeSound::Type()); + EXPECT_TRUE(result.IsSuccess()); + EXPECT_TRUE(mMockDelegate.playChimeSoundCalled); +} + +TEST_F(TestChimeClusterBackwardsCompatibility, TestLegacySetters) +{ + // Test SetSelectedChime (Legacy API) + EXPECT_EQ(mChimeServer.SetSelectedChime(1), Protocols::InteractionModel::Status::Success); + EXPECT_EQ(mChimeServer.GetSelectedChime(), 1); + + // Verify it affected the attribute + uint8_t selectedChime = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::SelectedChime::Id, selectedChime), CHIP_NO_ERROR); + EXPECT_EQ(selectedChime, 1); + + // Test SetEnabled (Legacy API) + EXPECT_EQ(mChimeServer.SetEnabled(false), Protocols::InteractionModel::Status::Success); + EXPECT_EQ(mChimeServer.GetEnabled(), false); + + bool enabled = true; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::Enabled::Id, enabled), CHIP_NO_ERROR); + EXPECT_EQ(enabled, false); +} + +TEST_F(TestChimeClusterBackwardsCompatibility, TestLegacyLifecycle) +{ + constexpr EndpointId kLifecycleEndpointId = 2; + { + ChimeServer chimeServer(kLifecycleEndpointId, mMockDelegate); + + // Check Init + EXPECT_EQ(chimeServer.Init(), CHIP_NO_ERROR); + + // Check GetEndpointId + EXPECT_EQ(chimeServer.GetEndpointId(), kLifecycleEndpointId); + + // Verify registered + EXPECT_TRUE(CodegenDataModelProvider::Instance().Registry().Get(ConcreteClusterPath(kLifecycleEndpointId, Chime::Id)) != + nullptr); + } + // Verify unregistered after destruction + EXPECT_TRUE(CodegenDataModelProvider::Instance().Registry().Get(ConcreteClusterPath(kLifecycleEndpointId, Chime::Id)) == + nullptr); +} + +} // namespace diff --git a/src/app/clusters/closure-control-server/closure-control-cluster-logic.cpp b/src/app/clusters/closure-control-server/closure-control-cluster-logic.cpp index eddb9644acc..3b94e39d36e 100644 --- a/src/app/clusters/closure-control-server/closure-control-cluster-logic.cpp +++ b/src/app/clusters/closure-control-server/closure-control-cluster-logic.cpp @@ -181,12 +181,12 @@ CHIP_ERROR ClusterLogic::SetMainState(MainStateEnum mainState) // EngageStateChanged event SHALL be generated when the MainStateEnum attribute changes state to and from disengaged state if (mState.mMainState == MainStateEnum::kDisengaged) { - GenerateEngageStateChangedEvent(true); + TEMPORARY_RETURN_IGNORED GenerateEngageStateChangedEvent(true); } if (mainState == MainStateEnum::kDisengaged) { - GenerateEngageStateChangedEvent(false); + TEMPORARY_RETURN_IGNORED GenerateEngageStateChangedEvent(false); } mState.mMainState = mainState; @@ -196,20 +196,20 @@ CHIP_ERROR ClusterLogic::SetMainState(MainStateEnum mainState) { if (mainState == MainStateEnum::kCalibrating) { - SetCountdownTimeFromCluster(mDelegate.GetCalibrationCountdownTime()); + TEMPORARY_RETURN_IGNORED SetCountdownTimeFromCluster(mDelegate.GetCalibrationCountdownTime()); } else if (mainState == MainStateEnum::kMoving) { - SetCountdownTimeFromCluster(mDelegate.GetMovingCountdownTime()); + TEMPORARY_RETURN_IGNORED SetCountdownTimeFromCluster(mDelegate.GetMovingCountdownTime()); } else if (mainState == MainStateEnum::kWaitingForMotion) { - SetCountdownTimeFromCluster(mDelegate.GetWaitingForMotionCountdownTime()); + TEMPORARY_RETURN_IGNORED SetCountdownTimeFromCluster(mDelegate.GetWaitingForMotionCountdownTime()); } else { // Reset the countdown time to 0 when the main state is not in motion or calibration. - SetCountdownTimeFromCluster(DataModel::Nullable(0)); + TEMPORARY_RETURN_IGNORED SetCountdownTimeFromCluster(DataModel::Nullable(0)); } } @@ -297,7 +297,7 @@ CHIP_ERROR ClusterLogic::SetOverallCurrentState(const DataModel::NullableHandleCommissionNode(*params); diff --git a/src/app/clusters/commodity-price-server/commodity-price-server.cpp b/src/app/clusters/commodity-price-server/commodity-price-server.cpp index 06ac8b0d8d5..75026467c0c 100644 --- a/src/app/clusters/commodity-price-server/commodity-price-server.cpp +++ b/src/app/clusters/commodity-price-server/commodity-price-server.cpp @@ -53,7 +53,7 @@ CHIP_ERROR Instance::Init() void Instance::Shutdown() { - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); + TEMPORARY_RETURN_IGNORED CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); AttributeAccessInterfaceRegistry::Instance().Unregister(this); } diff --git a/src/app/clusters/commodity-tariff-server/CommodityTariffAttrsDataMgmt.h b/src/app/clusters/commodity-tariff-server/CommodityTariffAttrsDataMgmt.h index 310b4c57660..e048a929004 100644 --- a/src/app/clusters/commodity-tariff-server/CommodityTariffAttrsDataMgmt.h +++ b/src/app/clusters/commodity-tariff-server/CommodityTariffAttrsDataMgmt.h @@ -704,8 +704,7 @@ class CTC_BaseDataClass : public CTC_BaseDataClassBase if (aValue.IsNull()) { mUpdateState.store(UpdateState::kInitialized); - MarkAsAssigned(); - return CHIP_NO_ERROR; + return MarkAsAssigned(); } } @@ -790,12 +789,8 @@ class CTC_BaseDataClass : public CTC_BaseDataClassBase } } - if (err == CHIP_NO_ERROR) - { - MarkAsAssigned(); - } - - return err; + ReturnErrorOnFailure(err); + return MarkAsAssigned(); } /** diff --git a/src/app/clusters/commodity-tariff-server/commodity-tariff-server.cpp b/src/app/clusters/commodity-tariff-server/commodity-tariff-server.cpp index b15c6b1be59..3a2747764b0 100644 --- a/src/app/clusters/commodity-tariff-server/commodity-tariff-server.cpp +++ b/src/app/clusters/commodity-tariff-server/commodity-tariff-server.cpp @@ -48,7 +48,7 @@ CHIP_ERROR Instance::Init() void Instance::Shutdown() { - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); + TEMPORARY_RETURN_IGNORED CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); AttributeAccessInterfaceRegistry::Instance().Unregister(this); } @@ -658,7 +658,7 @@ CHIP_ERROR Instance::UpdateDayInformation(uint32_t matterEpochNow_s) } ChipLogDetail(AppServer, "UpdateCurrentAttrs: current day date: %u", currentDay.Value().date); - SetCurrentDay(currentDay); + ReturnErrorOnFailure(SetCurrentDay(currentDay)); nextDay.SetNonNull( Utils::FindDay(mServerTariffAttrsCtx, (matterEpochNow_s + (kSecondsPerDay - matterEpochNow_s % kSecondsPerDay)) + 1)); @@ -666,7 +666,7 @@ CHIP_ERROR Instance::UpdateDayInformation(uint32_t matterEpochNow_s) if (Utils::DayIsValid(&nextDay.Value())) { ChipLogDetail(AppServer, "UpdateCurrentAttrs: next day date: %u", nextDay.Value().date); - SetNextDay(nextDay); + ReturnErrorOnFailure(SetNextDay(nextDay)); } return CHIP_NO_ERROR; @@ -700,8 +700,8 @@ CHIP_ERROR Instance::UpdateDayEntryInformation(uint32_t matterEpochNow_s) ChipLogDetail(AppServer, "UpdateCurrentAttrs: current day entry: %u", tmpDayEntry.Value().dayEntryID); } - SetCurrentDayEntry(tmpDayEntry); - SetCurrentDayEntryDate(tmpDate); + ReturnErrorOnFailure(SetCurrentDayEntry(tmpDayEntry)); + ReturnErrorOnFailure(SetCurrentDayEntryDate(tmpDate)); // Handle next day entry tmpDayEntry.SetNull(); @@ -716,10 +716,8 @@ CHIP_ERROR Instance::UpdateDayEntryInformation(uint32_t matterEpochNow_s) tmpDate.SetNonNull(mCurrentDayEntryDate.Value() + currentEntryMinutesRemain * 60); } - SetNextDayEntry(tmpDayEntry); - SetNextDayEntryDate(tmpDate); - - return CHIP_NO_ERROR; + ReturnErrorOnFailure(SetNextDayEntry(tmpDayEntry)); + return SetNextDayEntryDate(tmpDate); } void Instance::DeinitCurrentAttrs() diff --git a/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp b/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp index 9d26f4041cb..1433a7e2a8b 100644 --- a/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp +++ b/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp @@ -47,7 +47,7 @@ CHIP_ERROR Instance::Init() void Instance::Shutdown() { - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); + TEMPORARY_RETURN_IGNORED CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); AttributeAccessInterfaceRegistry::Instance().Unregister(this); } diff --git a/src/app/clusters/diagnostic-logs-server/BDXDiagnosticLogsProvider.cpp b/src/app/clusters/diagnostic-logs-server/BDXDiagnosticLogsProvider.cpp index beb4964b8c5..60e18e6e695 100644 --- a/src/app/clusters/diagnostic-logs-server/BDXDiagnosticLogsProvider.cpp +++ b/src/app/clusters/diagnostic-logs-server/BDXDiagnosticLogsProvider.cpp @@ -178,19 +178,20 @@ void BDXDiagnosticLogsProvider::OnAckReceived() uint16_t blockSize = mTransfer.GetTransferBlockSize(); auto blockBuf = System::PacketBufferHandle::New(blockSize); - VerifyOrReturn(!blockBuf.IsNull(), mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(CHIP_ERROR_NO_MEMORY))); + VerifyOrReturn(!blockBuf.IsNull(), + TEMPORARY_RETURN_IGNORED mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(CHIP_ERROR_NO_MEMORY))); auto buffer = MutableByteSpan(blockBuf->Start(), blockSize); bool isEndOfLog = false; // Get the log next chunk and see if it fits i.e. if is end of log is reported auto err = mDelegate->CollectLog(mLogSessionHandle, buffer, isEndOfLog); - VerifyOrReturn(CHIP_NO_ERROR == err, mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(err))); + VerifyOrReturn(CHIP_NO_ERROR == err, TEMPORARY_RETURN_IGNORED mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(err))); // If the buffer has empty space, end the log collection session. if (isEndOfLog) { - mDelegate->EndLogCollection(mLogSessionHandle, CHIP_ERROR_INTERNAL); + TEMPORARY_RETURN_IGNORED mDelegate->EndLogCollection(mLogSessionHandle, CHIP_ERROR_INTERNAL); mLogSessionHandle = kInvalidLogSessionHandle; } @@ -204,7 +205,7 @@ void BDXDiagnosticLogsProvider::OnAckReceived() if (err != CHIP_NO_ERROR) { ChipLogError(BDX, "PrepareBlock failed: %" CHIP_ERROR_FORMAT, err.Format()); - mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(err)); + TEMPORARY_RETURN_IGNORED mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(err)); } } @@ -278,7 +279,7 @@ void BDXDiagnosticLogsProvider::Reset(CHIP_ERROR error) if (mDelegate != nullptr) { - mDelegate->EndLogCollection(mLogSessionHandle, error); + TEMPORARY_RETURN_IGNORED mDelegate->EndLogCollection(mLogSessionHandle, error); mDelegate = nullptr; } diff --git a/src/app/clusters/diagnostic-logs-server/CodegenIntegration.cpp b/src/app/clusters/diagnostic-logs-server/CodegenIntegration.cpp index 37a97247ab2..d9539ecd418 100644 --- a/src/app/clusters/diagnostic-logs-server/CodegenIntegration.cpp +++ b/src/app/clusters/diagnostic-logs-server/CodegenIntegration.cpp @@ -55,7 +55,7 @@ void MatterDiagnosticLogsClusterShutdownCallback(EndpointId endpointId) { // We implement the cluster as a singleton on the root endpoint. VerifyOrReturn(endpointId == kRootEndpointId); - CodegenDataModelProvider::Instance().Registry().Unregister(&gServer.get()); + TEMPORARY_RETURN_IGNORED CodegenDataModelProvider::Instance().Registry().Unregister(&gServer.get()); } void MatterDiagnosticLogsPluginServerInitCallback() {} diff --git a/src/app/clusters/door-lock-server/door-lock-server.cpp b/src/app/clusters/door-lock-server/door-lock-server.cpp index 4dd0727de31..6011196129f 100644 --- a/src/app/clusters/door-lock-server/door-lock-server.cpp +++ b/src/app/clusters/door-lock-server/door-lock-server.cpp @@ -1181,7 +1181,7 @@ void DoorLockServer::getWeekDayScheduleCommandHandler(chip::app::CommandHandler return; } - EmberAfPluginDoorLockWeekDaySchedule scheduleInfo{}; + EmberAfPluginDoorLockWeekDaySchedule scheduleInfo{ DaysMaskMap(0) }; auto status = emberAfPluginDoorLockGetSchedule(endpointId, weekDayIndex, userIndex, scheduleInfo); if (DlStatus::kSuccess != status) { @@ -3585,7 +3585,7 @@ void DoorLockServer::sendClusterResponse(chip::app::CommandHandler * commandObj, if (const auto clusterStatus = status.GetClusterSpecificCode(); clusterStatus.has_value()) { - VerifyOrDie(commandObj->AddClusterSpecificFailure(commandPath, *clusterStatus) == CHIP_NO_ERROR); + SuccessOrDie(commandObj->AddClusterSpecificFailure(commandPath, *clusterStatus)); } else { @@ -4312,7 +4312,7 @@ void emberAfPluginDoorLockServerRelockEventHandler() {} void MatterDoorLockPluginServerInitCallback() { ChipLogProgress(Zcl, "Door Lock server initialized"); - Server::GetInstance().GetFabricTable().AddFabricDelegate(&gFabricDelegate); + TEMPORARY_RETURN_IGNORED Server::GetInstance().GetFabricTable().AddFabricDelegate(&gFabricDelegate); AttributeAccessInterfaceRegistry::Instance().Register(&DoorLockServer::Instance()); } diff --git a/src/app/clusters/electrical-power-measurement-server/electrical-power-measurement-server.cpp b/src/app/clusters/electrical-power-measurement-server/electrical-power-measurement-server.cpp index c03cd06cc6e..a51f6f202f6 100644 --- a/src/app/clusters/electrical-power-measurement-server/electrical-power-measurement-server.cpp +++ b/src/app/clusters/electrical-power-measurement-server/electrical-power-measurement-server.cpp @@ -248,7 +248,7 @@ CHIP_ERROR Instance::EncodeAccuracy(const AttributeValueEncoder::ListEncodeHelpe exit: // Tell the delegate the read is complete - mDelegate.EndAccuracyRead(); + TEMPORARY_RETURN_IGNORED mDelegate.EndAccuracyRead(); return err; } @@ -278,7 +278,7 @@ CHIP_ERROR Instance::EncodeRanges(const AttributeValueEncoder::ListEncodeHelper exit: // Tell the delegate the read is complete - err = mDelegate.EndRangesRead(); + TEMPORARY_RETURN_IGNORED mDelegate.EndRangesRead(); return err; } diff --git a/src/app/clusters/energy-evse-server/energy-evse-server.cpp b/src/app/clusters/energy-evse-server/energy-evse-server.cpp index 2b1d510264b..1c6f4b68d4f 100644 --- a/src/app/clusters/energy-evse-server/energy-evse-server.cpp +++ b/src/app/clusters/energy-evse-server/energy-evse-server.cpp @@ -47,7 +47,7 @@ CHIP_ERROR Instance::Init() void Instance::Shutdown() { - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); + TEMPORARY_RETURN_IGNORED CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); AttributeAccessInterfaceRegistry::Instance().Unregister(this); } diff --git a/src/app/clusters/general-commissioning-server/general-commissioning-cluster.cpp b/src/app/clusters/general-commissioning-server/general-commissioning-cluster.cpp index 23e4aac45a2..92b0853fdb4 100644 --- a/src/app/clusters/general-commissioning-server/general-commissioning-cluster.cpp +++ b/src/app/clusters/general-commissioning-server/general-commissioning-cluster.cpp @@ -397,9 +397,8 @@ void GeneralCommissioningCluster::SetBreadCrumb(uint64_t value) CHIP_ERROR GeneralCommissioningCluster::Startup(ServerClusterContext & context) { ReturnErrorOnFailure(DefaultServerCluster::Startup(context)); - PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler, reinterpret_cast(this)); - Server::GetInstance().GetFabricTable().AddFabricDelegate(this); - return CHIP_NO_ERROR; + ReturnErrorOnFailure(PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler, reinterpret_cast(this))); + return Server::GetInstance().GetFabricTable().AddFabricDelegate(this); } void GeneralCommissioningCluster::Shutdown() diff --git a/src/app/clusters/group-key-mgmt-server/group-key-mgmt-cluster.cpp b/src/app/clusters/group-key-mgmt-server/group-key-mgmt-cluster.cpp index 336c417d493..2db1b984c5e 100644 --- a/src/app/clusters/group-key-mgmt-server/group-key-mgmt-cluster.cpp +++ b/src/app/clusters/group-key-mgmt-server/group-key-mgmt-cluster.cpp @@ -188,7 +188,7 @@ CHIP_ERROR WriteGroupKeyMap(const ConcreteDataAttributePath & aPath, AttributeVa ReturnErrorOnFailure(list.ComputeSize(&new_count)); // Remove existing keys, ignore errors - provider->RemoveGroupKeys(fabric_index); + TEMPORARY_RETURN_IGNORED provider->RemoveGroupKeys(fabric_index); // Add the new keys auto iter = list.begin(); diff --git a/src/app/clusters/groupcast/GroupcastCluster.cpp b/src/app/clusters/groupcast/GroupcastCluster.cpp index 1d2accc7109..181b25df25b 100644 --- a/src/app/clusters/groupcast/GroupcastCluster.cpp +++ b/src/app/clusters/groupcast/GroupcastCluster.cpp @@ -65,7 +65,7 @@ std::optional GroupcastCluster::InvokeCommand(con Groupcast::Commands::LeaveGroup::DecodableType data; Groupcast::Commands::LeaveGroupResponse::Type response; ReturnErrorOnFailure(data.Decode(arguments, fabric_index)); - mLogic.LeaveGroup(fabric_index, data, response); + TEMPORARY_RETURN_IGNORED mLogic.LeaveGroup(fabric_index, data, response); handler->AddResponse(request.path, response); return std::nullopt; } diff --git a/src/app/clusters/groups-server/groups-server.cpp b/src/app/clusters/groups-server/groups-server.cpp index 00eda43c84b..9310cf2b4b7 100644 --- a/src/app/clusters/groups-server/groups-server.cpp +++ b/src/app/clusters/groups-server/groups-server.cpp @@ -344,7 +344,7 @@ bool emberAfGroupsClusterRemoveAllGroupsCallback(app::CommandHandler * commandOb } #endif - provider->RemoveEndpoint(fabricIndex, commandPath.mEndpointId); + TEMPORARY_RETURN_IGNORED provider->RemoveEndpoint(fabricIndex, commandPath.mEndpointId); status = Status::Success; MatterReportingAttributeChangeCallback(kRootEndpointId, GroupKeyManagement::Id, GroupKeyManagement::Attributes::GroupTable::Id); exit: diff --git a/src/app/clusters/icd-management-server/ICDManagementCluster.cpp b/src/app/clusters/icd-management-server/ICDManagementCluster.cpp index 51bb4f9b058..241369bf9c1 100644 --- a/src/app/clusters/icd-management-server/ICDManagementCluster.cpp +++ b/src/app/clusters/icd-management-server/ICDManagementCluster.cpp @@ -93,7 +93,7 @@ void ICDManagementFabricDelegate::OnFabricRemoved(const FabricTable & fabricTabl { uint16_t supported_clients = mICDConfigurationData->GetClientsSupportedPerFabric(); ICDMonitoringTable table(*mStorage, fabricIndex, supported_clients, mSymmetricKeystore); - table.RemoveAll(); + TEMPORARY_RETURN_IGNORED table.RemoveAll(); ICDNotifier::GetInstance().NotifyICDManagementEvent(ICDListener::ICDManagementEvents::kTableUpdated); } #endif // CHIP_CONFIG_ENABLE_ICD_CIP @@ -284,7 +284,7 @@ Status ICDManagementServer::RegisterClient(CommandHandler * commandObj, const Co if (entry.keyHandleValid) { - entry.DeleteKey(); + TEMPORARY_RETURN_IGNORED entry.DeleteKey(); } err = entry.SetKey(key); @@ -295,7 +295,7 @@ Status ICDManagementServer::RegisterClient(CommandHandler * commandObj, const Co // Delete key upon failure to prevent key storage leakage. if (err != CHIP_NO_ERROR) { - entry.DeleteKey(); + TEMPORARY_RETURN_IGNORED entry.DeleteKey(); } VerifyOrReturnError(CHIP_ERROR_INVALID_ARGUMENT != err, Status::ConstraintError); diff --git a/src/app/clusters/joint-fabric-administrator-server/joint-fabric-administrator-server.cpp b/src/app/clusters/joint-fabric-administrator-server/joint-fabric-administrator-server.cpp index 587d152ea80..3357aba5238 100644 --- a/src/app/clusters/joint-fabric-administrator-server/joint-fabric-administrator-server.cpp +++ b/src/app/clusters/joint-fabric-administrator-server/joint-fabric-administrator-server.cpp @@ -187,7 +187,7 @@ void JointFabricAdministratorGlobalInstance::HandleOJCW(HandlerContext & ctx, if (status.HasValue()) { ChipLogError(Zcl, "Failed to open joint commissioning window. Cluster status 0x%02x", to_underlying(status.Value())); - ctx.mCommandHandler.AddClusterSpecificFailure(ctx.mRequestPath, to_underlying(status.Value())); + TEMPORARY_RETURN_IGNORED ctx.mCommandHandler.AddClusterSpecificFailure(ctx.mRequestPath, to_underlying(status.Value())); } else { diff --git a/src/app/clusters/level-control/level-control.cpp b/src/app/clusters/level-control/level-control.cpp index dab9496045c..b6a7b1cbf93 100644 --- a/src/app/clusters/level-control/level-control.cpp +++ b/src/app/clusters/level-control/level-control.cpp @@ -173,9 +173,6 @@ class DefaultLevelControlSceneHandler : public scenes::DefaultSceneHandlerImpl AttributeValuePair pairs[kLevelMaxScenableAttributes]; - uint8_t maxLevel; - VerifyOrReturnError(Status::Success == Attributes::MaxLevel::Get(endpoint, &maxLevel), CHIP_ERROR_READ_FAILED); - pairs[0].attributeID = Attributes::CurrentLevel::Id; if (!level.IsNull()) { diff --git a/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp b/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp index 052758b761f..8da0ffed2d0 100644 --- a/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp +++ b/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp @@ -60,7 +60,7 @@ Instance::~Instance() { mDelegate->SetInstance(nullptr); } - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); + TEMPORARY_RETURN_IGNORED CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); AttributeAccessInterfaceRegistry::Instance().Unregister(this); } @@ -257,7 +257,7 @@ void Instance::HandleSetCookingParameters(HandlerContext & ctx, const Commands:: ReadOnlyBufferBuilder acceptedCommandsList; - InteractionModelEngine::GetInstance()->GetDataModelProvider()->AcceptedCommands( + TEMPORARY_RETURN_IGNORED InteractionModelEngine::GetInstance()->GetDataModelProvider()->AcceptedCommands( ConcreteClusterPath(mEndpointId, OperationalState::Id), acceptedCommandsList); auto acceptedCommands = acceptedCommandsList.TakeBuffer(); diff --git a/src/app/clusters/mode-base-server/mode-base-server.cpp b/src/app/clusters/mode-base-server/mode-base-server.cpp index 092985d082f..b7d0a0b116d 100644 --- a/src/app/clusters/mode-base-server/mode-base-server.cpp +++ b/src/app/clusters/mode-base-server/mode-base-server.cpp @@ -63,8 +63,8 @@ void Instance::Shutdown() { return; } - UnregisterThisInstance(); - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); + TEMPORARY_RETURN_IGNORED UnregisterThisInstance(); + TEMPORARY_RETURN_IGNORED CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); AttributeAccessInterfaceRegistry::Instance().Unregister(this); } @@ -175,7 +175,7 @@ Status Instance::UpdateCurrentMode(uint8_t aNewMode) { // Write new value to persistent storage. ConcreteAttributePath path = ConcreteAttributePath(mEndpointId, mClusterId, Attributes::CurrentMode::Id); - GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mCurrentMode); + TEMPORARY_RETURN_IGNORED GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mCurrentMode); MatterReportingAttributeChangeCallback(path); } return Protocols::InteractionModel::Status::Success; @@ -196,7 +196,7 @@ Status Instance::UpdateStartUpMode(DataModel::Nullable aNewStartUpMode) { // Write new value to persistent storage. ConcreteAttributePath path = ConcreteAttributePath(mEndpointId, mClusterId, Attributes::StartUpMode::Id); - GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mStartUpMode); + TEMPORARY_RETURN_IGNORED GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mStartUpMode); MatterReportingAttributeChangeCallback(path); } return Protocols::InteractionModel::Status::Success; @@ -217,7 +217,7 @@ Status Instance::UpdateOnMode(DataModel::Nullable aNewOnMode) { // Write new value to persistent storage. ConcreteAttributePath path = ConcreteAttributePath(mEndpointId, mClusterId, Attributes::OnMode::Id); - GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mOnMode); + TEMPORARY_RETURN_IGNORED GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mOnMode); MatterReportingAttributeChangeCallback(path); } return Protocols::InteractionModel::Status::Success; @@ -272,8 +272,7 @@ CHIP_ERROR Instance::GetModeValueByModeTag(uint16_t modeTagValue, uint8_t & valu { if (mTags[ii].value == modeTagValue) { - mDelegate->GetModeValueByIndex(i, value); - return CHIP_NO_ERROR; + return mDelegate->GetModeValueByIndex(i, value); } } mTags = tagsBuffer; @@ -414,7 +413,7 @@ void Instance::HandleChangeToMode(HandlerContext & ctx, const Commands::ChangeTo if (response.status == to_underlying(StatusCode::kSuccess)) { - UpdateCurrentMode(newMode); + TEMPORARY_RETURN_IGNORED UpdateCurrentMode(newMode); ChipLogProgress(Zcl, "ModeBase: HandleChangeToMode changed to mode %u", newMode); } diff --git a/src/app/clusters/mode-select-server/mode-select-server.cpp b/src/app/clusters/mode-select-server/mode-select-server.cpp index 6124b3e68f5..5939efe1a4c 100644 --- a/src/app/clusters/mode-select-server/mode-select-server.cpp +++ b/src/app/clusters/mode-select-server/mode-select-server.cpp @@ -88,15 +88,13 @@ CHIP_ERROR ModeSelectAttrAccess::Read(const ConcreteReadAttributePath & aPath, A if (gSupportedModeManager == nullptr) { ChipLogError(Zcl, "ModeSelect: SupportedModesManager is NULL"); - aEncoder.EncodeEmptyList(); - return CHIP_NO_ERROR; + return aEncoder.EncodeEmptyList(); } const ModeSelect::SupportedModesManager::ModeOptionsProvider modeOptionsProvider = gSupportedModeManager->getModeOptionsProvider(aPath.mEndpointId); if (modeOptionsProvider.begin() == nullptr) { - aEncoder.EncodeEmptyList(); - return CHIP_NO_ERROR; + return aEncoder.EncodeEmptyList(); } CHIP_ERROR err; err = aEncoder.EncodeList([modeOptionsProvider](const auto & encoder) -> CHIP_ERROR { @@ -241,13 +239,13 @@ class DefaultModeSelectSceneHandler : public scenes::DefaultSceneHandlerImpl CHIP_ERROR err = pair_iterator.GetStatus(); if (CHIP_NO_ERROR != err) { - mSceneEndpointStatePairs.RemovePair(endpoint); + TEMPORARY_RETURN_IGNORED mSceneEndpointStatePairs.RemovePair(endpoint); return err; } VerifyOrReturnError(mTransitionTimeInterface.sceneEventControl(endpoint) != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32(timeMs), timerCallback, - mTransitionTimeInterface.sceneEventControl(endpoint)); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32(timeMs), timerCallback, + mTransitionTimeInterface.sceneEventControl(endpoint)); return CHIP_NO_ERROR; } @@ -276,7 +274,7 @@ static void sceneModeSelectCallback(EndpointId endpoint) ModeSelectEndPointPair savedState; ReturnOnFailure(sModeSelectSceneHandler.mSceneEndpointStatePairs.GetPair(endpoint, savedState)); ChangeToMode(endpoint, savedState.mValue); - sModeSelectSceneHandler.mSceneEndpointStatePairs.RemovePair(endpoint); + TEMPORARY_RETURN_IGNORED sModeSelectSceneHandler.mSceneEndpointStatePairs.RemovePair(endpoint); } #endif // defined(MATTER_DM_PLUGIN_SCENES_MANAGEMENT) && CHIP_CONFIG_SCENES_USE_DEFAULT_HANDLERS diff --git a/src/app/clusters/network-commissioning/CodegenInstance.cpp b/src/app/clusters/network-commissioning/CodegenInstance.cpp index a11e6d42f91..4d0e8299c3d 100644 --- a/src/app/clusters/network-commissioning/CodegenInstance.cpp +++ b/src/app/clusters/network-commissioning/CodegenInstance.cpp @@ -45,7 +45,7 @@ CHIP_ERROR Instance::Init() void Instance::Shutdown() { - CodegenDataModelProvider::Instance().Registry().Unregister(&mCluster.Cluster()); + TEMPORARY_RETURN_IGNORED CodegenDataModelProvider::Instance().Registry().Unregister(&mCluster.Cluster()); mCluster.Cluster().Shutdown(); } diff --git a/src/app/clusters/network-commissioning/NetworkCommissioningCluster.cpp b/src/app/clusters/network-commissioning/NetworkCommissioningCluster.cpp index b9b0c04d852..a8b22e2b89e 100644 --- a/src/app/clusters/network-commissioning/NetworkCommissioningCluster.cpp +++ b/src/app/clusters/network-commissioning/NetworkCommissioningCluster.cpp @@ -837,7 +837,7 @@ void NetworkCommissioningCluster::OnResult(Status commissioningError, CharSpan d } if (commissioningError == Status::kSuccess) { - DeviceLayer::DeviceControlServer::DeviceControlSvr().PostConnectedToOperationalNetworkEvent( + TEMPORARY_RETURN_IGNORED DeviceLayer::DeviceControlServer::DeviceControlSvr().PostConnectedToOperationalNetworkEvent( ByteSpan(mLastNetworkID, mLastNetworkIDLen)); SetLastConnectErrorValue(NullNullable); } @@ -950,7 +950,7 @@ void NetworkCommissioningCluster::OnCommissioningComplete() VerifyOrReturn(mpWirelessDriver != nullptr); ChipLogDetail(Zcl, "Commissioning complete, notify platform driver to persist network credentials."); - mpWirelessDriver->CommitConfiguration(); + TEMPORARY_RETURN_IGNORED mpWirelessDriver->CommitConfiguration(); } void NetworkCommissioningCluster::OnFailSafeTimerExpired() @@ -958,7 +958,7 @@ void NetworkCommissioningCluster::OnFailSafeTimerExpired() VerifyOrReturn(mpWirelessDriver != nullptr); ChipLogDetail(Zcl, "Failsafe timeout, tell platform driver to revert network credentials."); - mpWirelessDriver->RevertConfiguration(); + TEMPORARY_RETURN_IGNORED mpWirelessDriver->RevertConfiguration(); mAsyncCommandHandle.Release(); // Mark the network list changed since `mpWirelessDriver->RevertConfiguration()` may have updated it. diff --git a/src/app/clusters/on-off-server/on-off-server.cpp b/src/app/clusters/on-off-server/on-off-server.cpp index 7c2f8a5a159..6b90ae72a1d 100644 --- a/src/app/clusters/on-off-server/on-off-server.cpp +++ b/src/app/clusters/on-off-server/on-off-server.cpp @@ -228,7 +228,7 @@ class DefaultOnOffSceneHandler : public scenes::DefaultSceneHandlerImpl CHIP_ERROR err = pair_iterator.GetStatus(); if (CHIP_NO_ERROR != err) { - mSceneEndpointStatePairs.RemovePair(endpoint); + TEMPORARY_RETURN_IGNORED mSceneEndpointStatePairs.RemovePair(endpoint); return err; } diff --git a/src/app/clusters/operational-credentials-server/operational-credentials-cluster.cpp b/src/app/clusters/operational-credentials-server/operational-credentials-cluster.cpp index 81a5f4c9b83..05955694ded 100644 --- a/src/app/clusters/operational-credentials-server/operational-credentials-cluster.cpp +++ b/src/app/clusters/operational-credentials-server/operational-credentials-cluster.cpp @@ -1111,9 +1111,8 @@ void OperationalCredentialsCluster::FailSafeCleanup(const DeviceLayer::ChipDevic CHIP_ERROR OperationalCredentialsCluster::Startup(ServerClusterContext & context) { ReturnErrorOnFailure(DefaultServerCluster::Startup(context)); - mOpCredsContext.fabricTable.AddFabricDelegate(this); - DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler, reinterpret_cast(this)); - return CHIP_NO_ERROR; + ReturnErrorOnFailure(mOpCredsContext.fabricTable.AddFabricDelegate(this)); + return DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler, reinterpret_cast(this)); } void OperationalCredentialsCluster::Shutdown() @@ -1276,7 +1275,7 @@ void OperationalCredentialsCluster::OnFabricRemoved(const FabricTable & fabricTa // to restart advertising altogether. GetDNSSDServer().StartServer(); - EventManagement::GetInstance().FabricRemoved(fabricIndex); + TEMPORARY_RETURN_IGNORED EventManagement::GetInstance().FabricRemoved(fabricIndex); NotifyAttributeChanged(OperationalCredentials::Attributes::CommissionedFabrics::Id); NotifyAttributeChanged(OperationalCredentials::Attributes::Fabrics::Id); diff --git a/src/app/clusters/operational-state-server/operational-state-server.cpp b/src/app/clusters/operational-state-server/operational-state-server.cpp index 242465ac623..1b1f0df1aee 100644 --- a/src/app/clusters/operational-state-server/operational-state-server.cpp +++ b/src/app/clusters/operational-state-server/operational-state-server.cpp @@ -58,7 +58,7 @@ Instance::~Instance() { mDelegate->SetInstance(nullptr); } - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); + TEMPORARY_RETURN_IGNORED CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); AttributeAccessInterfaceRegistry::Instance().Unregister(this); } diff --git a/src/app/clusters/ota-requestor/BDXDownloader.cpp b/src/app/clusters/ota-requestor/BDXDownloader.cpp index 43e3efca4af..9a08d16c6ad 100644 --- a/src/app/clusters/ota-requestor/BDXDownloader.cpp +++ b/src/app/clusters/ota-requestor/BDXDownloader.cpp @@ -49,7 +49,7 @@ void TransferTimeoutCheckHandler(System::Layer * systemLayer, void * appState) else { // Else restart the timer - systemLayer->StartTimer(bdxDownloader->GetTimeout(), TransferTimeoutCheckHandler, appState); + TEMPORARY_RETURN_IGNORED systemLayer->StartTimer(bdxDownloader->GetTimeout(), TransferTimeoutCheckHandler, appState); } } @@ -119,7 +119,7 @@ CHIP_ERROR BDXDownloader::BeginPrepareDownload() // Note that due to the nature of this timer function, the actual time taken to detect a stalled BDX connection might be // anywhere in the range of [mTimeout, 2*mTimeout) - DeviceLayer::SystemLayer().StartTimer(mTimeout, TransferTimeoutCheckHandler, this); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().StartTimer(mTimeout, TransferTimeoutCheckHandler, this); ReturnErrorOnFailure(mImageProcessor->PrepareDownload()); @@ -178,7 +178,7 @@ void BDXDownloader::OnDownloadTimeout() mBdxTransfer.Reset(); if (mImageProcessor != nullptr) { - mImageProcessor->Abort(); + TEMPORARY_RETURN_IGNORED mImageProcessor->Abort(); } SetState(State::kIdle, OTAChangeReasonEnum::kTimeOut); } @@ -205,12 +205,11 @@ void BDXDownloader::EndDownload(CHIP_ERROR reason) } // There is no method for a BDX receiving driver to cleanly end a transfer - mBdxTransfer.AbortTransfer(status); + TEMPORARY_RETURN_IGNORED mBdxTransfer.AbortTransfer(status); if (mImageProcessor != nullptr) { - mImageProcessor->Abort(); + TEMPORARY_RETURN_IGNORED mImageProcessor->Abort(); } - // Because AbortTransfer() will generate a StatusReport to send. PollTransferSession(); @@ -244,7 +243,7 @@ void BDXDownloader::CleanupOnError(OTAChangeReasonEnum reason) SetState(State::kIdle, reason); if (mImageProcessor) { - mImageProcessor->Abort(); + TEMPORARY_RETURN_IGNORED mImageProcessor->Abort(); } } @@ -280,7 +279,7 @@ CHIP_ERROR BDXDownloader::HandleBdxEvent(const chip::bdx::TransferSession::Outpu // TODO: this will cause problems if Finalize() is not guaranteed to do its work after ProcessBlock(). if (outEvent.blockdata.IsEof) { - mBdxTransfer.PrepareBlockAck(); + TEMPORARY_RETURN_IGNORED mBdxTransfer.PrepareBlockAck(); ReturnErrorOnFailure(mImageProcessor->Finalize()); } diff --git a/src/app/clusters/ota-requestor/DefaultOTARequestor.cpp b/src/app/clusters/ota-requestor/DefaultOTARequestor.cpp index 713a3d9dfa8..ecf7b6e9d41 100644 --- a/src/app/clusters/ota-requestor/DefaultOTARequestor.cpp +++ b/src/app/clusters/ota-requestor/DefaultOTARequestor.cpp @@ -133,7 +133,7 @@ CHIP_ERROR DefaultOTARequestor::Init(Server & server, OTARequestorStorage & stor LoadCurrentUpdateInfo(); // Schedule the initializations that needs to be performed in the CHIP context - DeviceLayer::PlatformMgr().ScheduleWork(InitState, reinterpret_cast(this)); + TEMPORARY_RETURN_IGNORED DeviceLayer::PlatformMgr().ScheduleWork(InitState, reinterpret_cast(this)); return chip::DeviceLayer::PlatformMgrImpl().AddEventHandler(OnCommissioningCompleteRequestor, reinterpret_cast(this)); } @@ -154,7 +154,7 @@ void DefaultOTARequestor::OnQueryImageResponse(void * context, const QueryImageR if (err != CHIP_NO_ERROR) { ChipLogError(SoftwareUpdate, "QueryImageResponse contains invalid fields: %" CHIP_ERROR_FORMAT, err.Format()); - requestorCore->RecordErrorUpdateState(err); + TEMPORARY_RETURN_IGNORED requestorCore->RecordErrorUpdateState(err); return; } @@ -190,7 +190,7 @@ void DefaultOTARequestor::OnQueryImageResponse(void * context, const QueryImageR if (err == CHIP_ERROR_BUFFER_TOO_SMALL) { memset(updateToken.data(), 0, updateToken.size()); - requestorCore->GenerateUpdateToken(); + TEMPORARY_RETURN_IGNORED requestorCore->GenerateUpdateToken(); } requestorCore->mTargetVersion = update.softwareVersion; requestorCore->mUpdateToken = updateToken; @@ -216,9 +216,9 @@ void DefaultOTARequestor::OnQueryImageResponse(void * context, const QueryImageR ChipLogDetail(SoftwareUpdate, "Available update version %" PRIu32 " is <= current version %" PRIu32 ", update ignored", update.softwareVersion, requestorCore->mCurrentVersion); - requestorCore->mOtaRequestorDriver->UpdateNotFound(UpdateNotFoundReason::kUpToDate, - System::Clock::Seconds32(response.delayedActionTime.ValueOr(0))); - requestorCore->RecordNewUpdateState(OTAUpdateStateEnum::kIdle, OTAChangeReasonEnum::kSuccess); + TEMPORARY_RETURN_IGNORED requestorCore->mOtaRequestorDriver->UpdateNotFound( + UpdateNotFoundReason::kUpToDate, System::Clock::Seconds32(response.delayedActionTime.ValueOr(0))); + TEMPORARY_RETURN_IGNORED requestorCore->RecordNewUpdateState(OTAUpdateStateEnum::kIdle, OTAChangeReasonEnum::kSuccess); } break; @@ -238,13 +238,13 @@ void DefaultOTARequestor::OnQueryImageResponse(void * context, const QueryImageR break; } case OTAQueryStatus::kNotAvailable: { - requestorCore->mOtaRequestorDriver->UpdateNotFound(UpdateNotFoundReason::kNotAvailable, - System::Clock::Seconds32(response.delayedActionTime.ValueOr(0))); - requestorCore->RecordNewUpdateState(OTAUpdateStateEnum::kIdle, OTAChangeReasonEnum::kSuccess); + TEMPORARY_RETURN_IGNORED requestorCore->mOtaRequestorDriver->UpdateNotFound( + UpdateNotFoundReason::kNotAvailable, System::Clock::Seconds32(response.delayedActionTime.ValueOr(0))); + TEMPORARY_RETURN_IGNORED requestorCore->RecordNewUpdateState(OTAUpdateStateEnum::kIdle, OTAChangeReasonEnum::kSuccess); break; } default: - requestorCore->RecordErrorUpdateState(CHIP_ERROR_BAD_REQUEST); + TEMPORARY_RETURN_IGNORED requestorCore->RecordErrorUpdateState(CHIP_ERROR_BAD_REQUEST); break; } } @@ -264,7 +264,7 @@ void DefaultOTARequestor::OnQueryImageFailure(void * context, CHIP_ERROR error) error = CHIP_ERROR_CONNECTION_CLOSED_UNEXPECTEDLY; } - requestorCore->RecordErrorUpdateState(error); + TEMPORARY_RETURN_IGNORED requestorCore->RecordErrorUpdateState(error); } void DefaultOTARequestor::OnApplyUpdateResponse(void * context, const ApplyUpdateResponse::DecodableType & response) @@ -565,7 +565,7 @@ void DefaultOTARequestor::ApplyUpdate() RecordNewUpdateState(OTAUpdateStateEnum::kApplying, OTAChangeReasonEnum::kSuccess); // If image is successfully applied, the device will reboot so persist all relevant data - StoreCurrentUpdateInfo(); + TEMPORARY_RETURN_IGNORED StoreCurrentUpdateInfo(); ConnectToProvider(kApplyUpdate); } @@ -911,7 +911,7 @@ void DefaultOTARequestor::StoreCurrentUpdateInfo() void DefaultOTARequestor::LoadCurrentUpdateInfo() { - mStorage->LoadDefaultProviders(mDefaultOtaProviderList); + TEMPORARY_RETURN_IGNORED mStorage->LoadDefaultProviders(mDefaultOtaProviderList); ProviderLocationType providerLocation; if (mStorage->LoadCurrentProviderLocation(providerLocation) == CHIP_NO_ERROR) diff --git a/src/app/clusters/ota-requestor/DefaultOTARequestorDriver.cpp b/src/app/clusters/ota-requestor/DefaultOTARequestorDriver.cpp index f8f54f940ae..6ec9f8f7a3d 100644 --- a/src/app/clusters/ota-requestor/DefaultOTARequestorDriver.cpp +++ b/src/app/clusters/ota-requestor/DefaultOTARequestorDriver.cpp @@ -73,7 +73,7 @@ void DefaultOTARequestorDriver::Init(OTARequestorInterface * requestor, OTAImage if (mImageProcessor->IsFirstImageRun()) { - SystemLayer().ScheduleLambda([this] { + TEMPORARY_RETURN_IGNORED SystemLayer().ScheduleLambda([this] { CHIP_ERROR error = mImageProcessor->ConfirmCurrentImage(); if (error != CHIP_NO_ERROR) @@ -85,7 +85,7 @@ void DefaultOTARequestorDriver::Init(OTARequestorInterface * requestor, OTAImage if (mSendNotifyUpdateApplied) { - mRequestor->NotifyUpdateApplied(); + TEMPORARY_RETURN_IGNORED mRequestor->NotifyUpdateApplied(); } }); } @@ -239,7 +239,7 @@ CHIP_ERROR DefaultOTARequestorDriver::UpdateNotFound(UpdateNotFoundReason reason void DefaultOTARequestorDriver::UpdateDownloaded() { VerifyOrDie(mRequestor != nullptr); - mRequestor->ApplyUpdate(); + TEMPORARY_RETURN_IGNORED mRequestor->ApplyUpdate(); } void DefaultOTARequestorDriver::UpdateConfirmed(System::Clock::Seconds32 delay) @@ -263,7 +263,7 @@ void DefaultOTARequestorDriver::UpdateSuspended(System::Clock::Seconds32 delay) void DefaultOTARequestorDriver::UpdateDiscontinued() { VerifyOrDie(mImageProcessor != nullptr); - mImageProcessor->Abort(); + TEMPORARY_RETURN_IGNORED mImageProcessor->Abort(); // Cancel all update timers UpdateCancelled(); @@ -332,7 +332,7 @@ void DefaultOTARequestorDriver::ProcessAnnounceOTAProviders( } // Point to the announced provider - mRequestor->SetCurrentProviderLocation(providerLocation); + TEMPORARY_RETURN_IGNORED mRequestor->SetCurrentProviderLocation(providerLocation); ScheduleDelayedAction(System::Clock::Seconds32(secToStart), StartDelayTimerHandler, this); } @@ -361,7 +361,7 @@ void DefaultOTARequestorDriver::SendQueryImage() if ((currentUpdateState == OTAUpdateStateEnum::kIdle) || (currentUpdateState == OTAUpdateStateEnum::kDelayedOnQuery)) { mProviderRetryCount++; - DeviceLayer::SystemLayer().ScheduleLambda([this] { mRequestor->TriggerImmediateQueryInternal(); }); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().ScheduleLambda([this] { mRequestor->TriggerImmediateQueryInternal(); }); } else { diff --git a/src/app/clusters/ota-requestor/DefaultOTARequestorStorage.cpp b/src/app/clusters/ota-requestor/DefaultOTARequestorStorage.cpp index a06fa7db2f1..5e3d874c9b1 100644 --- a/src/app/clusters/ota-requestor/DefaultOTARequestorStorage.cpp +++ b/src/app/clusters/ota-requestor/DefaultOTARequestorStorage.cpp @@ -97,7 +97,7 @@ CHIP_ERROR DefaultOTARequestorStorage::LoadDefaultProviders(ProviderLocationList ReturnErrorOnFailure(provider.Decode(reader)); if (!ProviderAlreadyInList(providers, provider)) { - providers.Add(provider); + TEMPORARY_RETURN_IGNORED providers.Add(provider); } } diff --git a/src/app/clusters/ota-requestor/ExtendedOTARequestorDriver.cpp b/src/app/clusters/ota-requestor/ExtendedOTARequestorDriver.cpp index 447096d34bf..d7803928ac0 100644 --- a/src/app/clusters/ota-requestor/ExtendedOTARequestorDriver.cpp +++ b/src/app/clusters/ota-requestor/ExtendedOTARequestorDriver.cpp @@ -108,13 +108,13 @@ void ExtendedOTARequestorDriver::HandleUserConsentState(chip::ota::UserConsentSt ScheduleDelayedAction( mDelayedActionTime, [](System::Layer *, void * context) { - static_cast(context)->mRequestor->CancelImageUpdate(); + TEMPORARY_RETURN_IGNORED static_cast(context)->mRequestor->CancelImageUpdate(); }, this); break; case chip::ota::UserConsentState::kObtaining: - SystemLayer().ScheduleWork( + TEMPORARY_RETURN_IGNORED SystemLayer().ScheduleWork( [](System::Layer *, void * context) { static_cast(context)->mRequestor->DownloadUpdateDelayedOnUserConsent(); }, diff --git a/src/app/clusters/power-source-server/power-source-server.cpp b/src/app/clusters/power-source-server/power-source-server.cpp index 40644873f2c..1e13f84fc85 100644 --- a/src/app/clusters/power-source-server/power-source-server.cpp +++ b/src/app/clusters/power-source-server/power-source-server.cpp @@ -164,13 +164,11 @@ CHIP_ERROR PowerSourceServer::SetEndpointList(EndpointId powerSourceClusterEndpo if (endpointList.size() == 0) { sPowerSourceClusterInfo[idx] = PowerSourceClusterInfo(); + return CHIP_NO_ERROR; } - else - { - sPowerSourceClusterInfo[idx] = PowerSourceClusterInfo(powerSourceClusterEndpoint); - sPowerSourceClusterInfo[idx].SetEndpointList(endpointList); - } - return CHIP_NO_ERROR; + + sPowerSourceClusterInfo[idx] = PowerSourceClusterInfo(powerSourceClusterEndpoint); + return sPowerSourceClusterInfo[idx].SetEndpointList(endpointList); } const Span * PowerSourceServer::GetEndpointList(EndpointId powerSourceClusterEndpoint) const { diff --git a/src/app/clusters/push-av-stream-transport-server/BUILD.gn b/src/app/clusters/push-av-stream-transport-server/BUILD.gn index b7322b24443..2f7958cb6ff 100644 --- a/src/app/clusters/push-av-stream-transport-server/BUILD.gn +++ b/src/app/clusters/push-av-stream-transport-server/BUILD.gn @@ -16,11 +16,11 @@ import("//build_overrides/chip.gni") source_set("push-av-stream-transport-server") { sources = [ - "push-av-stream-transport-cluster.cpp", - "push-av-stream-transport-cluster.h", + "PushAVStreamTransportCluster.cpp", + "PushAVStreamTransportCluster.h", + "PushAVStreamTransportLogic.cpp", + "PushAVStreamTransportLogic.h", "push-av-stream-transport-delegate.h", - "push-av-stream-transport-logic.cpp", - "push-av-stream-transport-logic.h", "push-av-stream-transport-storage.h", ] diff --git a/src/app/clusters/push-av-stream-transport-server/CodegenIntegration.cpp b/src/app/clusters/push-av-stream-transport-server/CodegenIntegration.cpp index 66b76fd3cd3..d9595fd71d3 100644 --- a/src/app/clusters/push-av-stream-transport-server/CodegenIntegration.cpp +++ b/src/app/clusters/push-av-stream-transport-server/CodegenIntegration.cpp @@ -15,7 +15,7 @@ * limitations under the License. */ #include -#include +#include #include #include #include @@ -117,11 +117,11 @@ void SetDelegate(EndpointId endpointId, PushAvStreamTransportDelegate * delegate if (PushAvStreamTransportServer * cluster = FindClusterOnEndpoint(endpointId); cluster != nullptr) { cluster->SetDelegate(delegate); - cluster->Init(); + TEMPORARY_RETURN_IGNORED cluster->Init(); } } -void SetTLSClientManagementDelegate(EndpointId endpointId, TlsClientManagementDelegate * delegate) +void SetTLSClientManagementDelegate(EndpointId endpointId, TLSClientManagementDelegate * delegate) { ChipLogProgress(AppServer, "Setting TLS Client Management delegate on endpoint %u", endpointId); if (PushAvStreamTransportServer * cluster = FindClusterOnEndpoint(endpointId); cluster != nullptr) @@ -130,7 +130,7 @@ void SetTLSClientManagementDelegate(EndpointId endpointId, TlsClientManagementDe } } -void SetTlsCertificateManagementDelegate(EndpointId endpointId, TlsCertificateManagementDelegate * delegate) +void SetTLSCertificateManagementDelegate(EndpointId endpointId, TLSCertificateManagementDelegate * delegate) { ChipLogProgress(AppServer, "Setting TLS Certificate Management delegate on endpoint %u", endpointId); uint16_t arrayIndex = @@ -145,7 +145,7 @@ void SetTlsCertificateManagementDelegate(EndpointId endpointId, TlsCertificateMa ChipLogError(AppServer, "Push AV Stream transport is NOT yet constructed. Cannot set TLS Certificate Management delegate"); return; } - gServers[arrayIndex].Cluster().SetTlsCertificateManagementDelegate(delegate); + gServers[arrayIndex].Cluster().SetTLSCertificateManagementDelegate(delegate); } } // namespace PushAvStreamTransport } // namespace Clusters diff --git a/src/app/clusters/push-av-stream-transport-server/CodegenIntegration.h b/src/app/clusters/push-av-stream-transport-server/CodegenIntegration.h index fd8d9188d3d..50f540c0cce 100644 --- a/src/app/clusters/push-av-stream-transport-server/CodegenIntegration.h +++ b/src/app/clusters/push-av-stream-transport-server/CodegenIntegration.h @@ -19,8 +19,8 @@ #pragma once #include "push-av-stream-transport-delegate.h" -#include -#include +#include +#include namespace chip { namespace app { @@ -31,10 +31,10 @@ namespace PushAvStreamTransport { void SetDelegate(chip::EndpointId endpointId, PushAvStreamTransportDelegate * delegate); /// Sets the given TLS Client Management delegate on an endpoint configured via code-generation -void SetTLSClientManagementDelegate(chip::EndpointId endpointId, TlsClientManagementDelegate * delegate); +void SetTLSClientManagementDelegate(chip::EndpointId endpointId, TLSClientManagementDelegate * delegate); /// Sets the given TLS Certificate Management delegate on an endpoint configured via code-generation -void SetTlsCertificateManagementDelegate(chip::EndpointId endpointId, TlsCertificateManagementDelegate * delegate); +void SetTLSCertificateManagementDelegate(chip::EndpointId endpointId, TLSCertificateManagementDelegate * delegate); } // namespace PushAvStreamTransport } // namespace Clusters diff --git a/src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-cluster.cpp b/src/app/clusters/push-av-stream-transport-server/PushAVStreamTransportCluster.cpp similarity index 98% rename from src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-cluster.cpp rename to src/app/clusters/push-av-stream-transport-server/PushAVStreamTransportCluster.cpp index ccf7036562b..6d1d37237cf 100644 --- a/src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-cluster.cpp +++ b/src/app/clusters/push-av-stream-transport-server/PushAVStreamTransportCluster.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-cluster.h b/src/app/clusters/push-av-stream-transport-server/PushAVStreamTransportCluster.h similarity index 95% rename from src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-cluster.h rename to src/app/clusters/push-av-stream-transport-server/PushAVStreamTransportCluster.h index 10d33d0a8d4..9d03deedddd 100644 --- a/src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-cluster.h +++ b/src/app/clusters/push-av-stream-transport-server/PushAVStreamTransportCluster.h @@ -18,9 +18,9 @@ #pragma once +#include #include #include -#include #include namespace chip { @@ -59,11 +59,11 @@ class PushAvStreamTransportServer : public DefaultServerCluster } } - void SetTLSClientManagementDelegate(TlsClientManagementDelegate * delegate) { mLogic.SetTLSClientManagementDelegate(delegate); } + void SetTLSClientManagementDelegate(TLSClientManagementDelegate * delegate) { mLogic.SetTLSClientManagementDelegate(delegate); } - void SetTlsCertificateManagementDelegate(TlsCertificateManagementDelegate * delegate) + void SetTLSCertificateManagementDelegate(TLSCertificateManagementDelegate * delegate) { - mLogic.SetTlsCertificateManagementDelegate(delegate); + mLogic.SetTLSCertificateManagementDelegate(delegate); } /** diff --git a/src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-logic.cpp b/src/app/clusters/push-av-stream-transport-server/PushAVStreamTransportLogic.cpp similarity index 73% rename from src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-logic.cpp rename to src/app/clusters/push-av-stream-transport-server/PushAVStreamTransportLogic.cpp index 3cc8c750adf..f5974c923a4 100644 --- a/src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-logic.cpp +++ b/src/app/clusters/push-av-stream-transport-server/PushAVStreamTransportLogic.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -149,17 +149,12 @@ void PushAvStreamTransportServerLogic::RemoveTimerAppState(const uint16_t connec void PushAvStreamTransportServerLogic::LoadPersistentAttributes() { - CHIP_ERROR err = CHIP_NO_ERROR; - // Load currentConnections - err = mDelegate->LoadCurrentConnections(mCurrentConnections); - if (err != CHIP_NO_ERROR) - { - ChipLogDetail(Zcl, "PushAVStreamTransport: Unable to load allocated connections from the KVS."); - } + ChipLogFailure(mDelegate->LoadCurrentConnections(mCurrentConnections), Zcl, + "PushAVStreamTransport: Unable to load allocated connections from the KVS."); // Signal delegate that all persistent configuration attributes have been loaded. - mDelegate->PersistentAttributesLoadedCallback(); + TEMPORARY_RETURN_IGNORED mDelegate->PersistentAttributesLoadedCallback(); } TransportConfigurationStorage * PushAvStreamTransportServerLogic::FindStreamTransportConnection(const uint16_t connectionID) @@ -317,10 +312,36 @@ Status PushAvStreamTransportServerLogic::ValidateIncomingTransportOptions( transportOptions.streamUsage != StreamUsageEnum::kUnknownEnumValue, Status::ConstraintError, ChipLogError(Zcl, "Transport Options verification from command data[ep=%d]: Invalid streamUsage ", mEndpointId)); - VerifyOrReturnValue( - transportOptions.videoStreamID.HasValue() || transportOptions.audioStreamID.HasValue(), Status::InvalidCommand, - ChipLogError(Zcl, "Transport Options verification from command data[ep=%d]: Missing videoStreamID and audioStreamID", - mEndpointId)); + // Check for video stream name length constraints + if (transportOptions.videoStreams.HasValue()) + { + for (auto iter = transportOptions.videoStreams.Value().begin(); iter.Next();) + { + auto streamName = iter.GetValue().videoStreamName; + VerifyOrReturnValue(streamName.size() >= kMinStreamNameLength && streamName.size() <= kMaxStreamNameLength, + Status::ConstraintError, + ChipLogError(Zcl, + "Transport Options verification from command data[ep=%d]: Video Stream Name " + "Constraint Error", + mEndpointId)); + } + } + + // Check for audio stream name length constraints + if (transportOptions.audioStreams.HasValue()) + { + for (auto iter = transportOptions.audioStreams.Value().begin(); iter.Next();) + { + auto streamName = iter.GetValue().audioStreamName; + VerifyOrReturnValue(streamName.size() >= kMinStreamNameLength && streamName.size() <= kMaxStreamNameLength, + Status::ConstraintError, + ChipLogError(Zcl, + "Transport Options verification from command data[ep=%d]: Audio Stream Name " + "Constraint Error", + mEndpointId)); + } + } + VerifyOrReturnValue(transportOptions.TLSEndpointID <= kMaxEndpointId, Status::ConstraintError, ChipLogError(Zcl, "Transport Options verification from command data[ep=%d]: EndpointID field Constraint Error", @@ -506,16 +527,6 @@ Status PushAvStreamTransportServerLogic::ValidateIncomingTransportOptions( "Duration field not within allowed range", mEndpointId)); - VerifyOrReturnValue( - containerOptions.CMAFContainerOptions.Value().trackName.size() >= 1 && - containerOptions.CMAFContainerOptions.Value().trackName.size() <= kMaxTrackNameLength, - Status::ConstraintError, - ChipLogError(Zcl, - "Transport Options verification from command data[ep=%d]: CMAF Container Options Track Name " - "Error, actual length: %" PRIu32 " not " - "within expected range of 1 to 16", - mEndpointId, static_cast(containerOptions.CMAFContainerOptions.Value().trackName.size()))); - if (containerOptions.CMAFContainerOptions.Value().CENCKey.HasValue()) { VerifyOrReturnValue( @@ -576,6 +587,218 @@ Status PushAvStreamTransportServerLogic::ValidateIncomingTransportOptions( return Status::Success; } +std::optional PushAvStreamTransportServerLogic::ValidateStreamParameters( + CommandHandler & handler, const ConcreteCommandPath & commandPath, + const PushAvStreamTransport::Structs::TransportOptionsStruct::DecodableType & transportOptions, + const std::shared_ptr transportOptionsPtr) +{ + + // Check mutual exclusivity and presence of stream fields + auto listHasElements = [](const auto & list) { + size_t s = 0; + return list.ComputeSize(&s) == CHIP_NO_ERROR && s > 0; + }; + bool hasNewStreamFields = + (transportOptions.videoStreams.HasValue() && listHasElements(transportOptions.videoStreams.Value())) || + (transportOptions.audioStreams.HasValue() && listHasElements(transportOptions.audioStreams.Value())); + bool hasOldStreamFields = transportOptions.videoStreamID.HasValue() || transportOptions.audioStreamID.HasValue(); + + VerifyOrReturnValue(!(hasNewStreamFields && hasOldStreamFields), Status::InvalidCommand, + ChipLogError(Zcl, "Transport Options[ep=%d]: Both new and old stream fields are present", mEndpointId)); + + VerifyOrReturnValue(hasNewStreamFields || hasOldStreamFields, Status::InvalidCommand, + ChipLogError(Zcl, "Transport Options[ep=%d]: Missing stream fields", mEndpointId)); + + // Validate new multistream fields + if (hasNewStreamFields) + { + std::set videoStreamNames; + + // Validate videoStreams + uint16_t videoStreamsCount = 0; + if (transportOptions.videoStreams.HasValue()) + { + std::set videoStreamIDs; + + for (auto iter = transportOptions.videoStreams.Value().begin(); iter.Next();) + { + auto & videoStream = iter.GetValue(); + + videoStreamsCount++; + videoStreamNames.insert(std::string(videoStream.videoStreamName.data(), videoStream.videoStreamName.size())); + videoStreamIDs.insert(videoStream.videoStreamID); + } + + // Check for duplicates within video streams + if ((videoStreamNames.size() != videoStreamsCount) || (videoStreamIDs.size() != videoStreamsCount)) + { + auto status = to_underlying(StatusCodeEnum::kDuplicateStreamValues); + ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: Duplicate videoStreamName or videoStreamID found", + mEndpointId); + TEMPORARY_RETURN_IGNORED handler.AddClusterSpecificFailure(commandPath, status); + return std::nullopt; + } + + for (auto iter = transportOptions.videoStreams.Value().begin(); iter.Next();) + { + auto & videoStream = iter.GetValue(); + // Validate videoStreamID + auto status = Protocols::InteractionModel::ClusterStatusCode(mDelegate->SetVideoStream(videoStream.videoStreamID)); + VerifyOrReturnValue(status.IsSuccess(), Status::InvalidCommand, + ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: Invalid Video Stream ID", mEndpointId)); + } + } + + // Validate audioStreams + uint16_t audioStreamsCount = 0; + if (transportOptions.audioStreams.HasValue()) + { + std::set audioStreamNames; + std::set audioStreamIDs; + + // Check against video stream names + for (auto iter = transportOptions.audioStreams.Value().begin(); iter.Next();) + { + auto & audioStream = iter.GetValue(); + + audioStreamsCount++; + audioStreamNames.insert(std::string(audioStream.audioStreamName.data(), audioStream.audioStreamName.size())); + audioStreamIDs.insert(audioStream.audioStreamID); + } + + // Check for duplicates within audio streams + if ((audioStreamNames.size() != audioStreamsCount) || (audioStreamIDs.size() != audioStreamsCount)) + { + auto status = to_underlying(StatusCodeEnum::kDuplicateStreamValues); + ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: Duplicate audioStreamName or audioStreamID found", + mEndpointId); + TEMPORARY_RETURN_IGNORED handler.AddClusterSpecificFailure(commandPath, status); + return std::nullopt; + } + + for (auto iter = transportOptions.audioStreams.Value().begin(); iter.Next();) + { + auto & audioStream = iter.GetValue(); + // Check for duplicate with video streams + if (videoStreamNames.find(std::string(audioStream.audioStreamName.data(), audioStream.audioStreamName.size())) != + videoStreamNames.end()) + { + auto status = to_underlying(StatusCodeEnum::kInvalidStream); + ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: AudioStreamName conflicts with video stream", + mEndpointId); + TEMPORARY_RETURN_IGNORED handler.AddClusterSpecificFailure(commandPath, status); + return std::nullopt; + } + + // Validate audioStreamID + auto status = Protocols::InteractionModel::ClusterStatusCode(mDelegate->SetAudioStream(audioStream.audioStreamID)); + VerifyOrReturnValue(status.IsSuccess(), Status::InvalidCommand, + ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: Invalid Audio Stream ID", mEndpointId)); + } + } + + // Check if both videoStreams and audioStreams are empty + if (videoStreamsCount == 0 && audioStreamsCount == 0) + { + auto status = to_underlying(StatusCodeEnum::kInvalidStream); + ChipLogError(Zcl, "Transport Options[ep=%d]: Both VideoStreams and AudioStreams empty", mEndpointId); + TEMPORARY_RETURN_IGNORED handler.AddClusterSpecificFailure(commandPath, status); + return std::nullopt; + } + } + + // Validate old format single stream fields + if (hasOldStreamFields) + { + + if (transportOptions.videoStreamID.HasValue()) + { + uint16_t finalVideoStreamID; + + if (transportOptions.videoStreamID.Value().IsNull()) + { + auto delegateStatus = Protocols::InteractionModel::ClusterStatusCode( + mDelegate->SelectVideoStream(transportOptions.streamUsage, finalVideoStreamID)); + if (!delegateStatus.IsSuccess()) + { + ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: AllocatedVideoStreamsAttribute is empty", mEndpointId); + handler.AddStatus(commandPath, Status::InvalidInState); + return std::nullopt; + } + + transportOptionsPtr->videoStreamID.SetValue(finalVideoStreamID); + } + else + { + auto delegateStatus = Protocols::InteractionModel::ClusterStatusCode( + mDelegate->SetVideoStream(transportOptions.videoStreamID.Value().Value())); + + if (!delegateStatus.IsSuccess()) + { + auto cluster_status = to_underlying(StatusCodeEnum::kInvalidStream); + ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: Invalid Video Stream ", mEndpointId); + TEMPORARY_RETURN_IGNORED handler.AddClusterSpecificFailure(commandPath, cluster_status); + return std::nullopt; + } + + finalVideoStreamID = transportOptions.videoStreamID.Value().Value(); + } + + // Create new video stream entry with name 'video' and the provided or selected VideoStreamID i.e; finalVideoStreamID + Structs::VideoStreamStruct::Type newVideoStream; + newVideoStream.videoStreamName = CharSpan::fromCharString("video"); + newVideoStream.videoStreamID = finalVideoStreamID; + + // Add to storage and update the list + transportOptionsPtr->AddVideoStream(newVideoStream); + } + + if (transportOptions.audioStreamID.HasValue()) + { + uint16_t finalAudioStreamID; + + if (transportOptions.audioStreamID.Value().IsNull()) + { + auto delegateStatus = Protocols::InteractionModel::ClusterStatusCode( + mDelegate->SelectAudioStream(transportOptions.streamUsage, finalAudioStreamID)); + if (!delegateStatus.IsSuccess()) + { + ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: AllocatedAudioStreamsAttribute is empty", mEndpointId); + handler.AddStatus(commandPath, Status::InvalidInState); + return std::nullopt; + } + + transportOptionsPtr->audioStreamID.SetValue(finalAudioStreamID); + } + else + { + auto delegateStatus = Protocols::InteractionModel::ClusterStatusCode( + mDelegate->SetAudioStream(transportOptions.audioStreamID.Value().Value())); + + if (!delegateStatus.IsSuccess()) + { + auto cluster_status = to_underlying(StatusCodeEnum::kInvalidStream); + ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: Invalid Audio Stream ", mEndpointId); + TEMPORARY_RETURN_IGNORED handler.AddClusterSpecificFailure(commandPath, cluster_status); + return std::nullopt; + } + + finalAudioStreamID = transportOptions.audioStreamID.Value().Value(); + } + + // Create new audio stream entry with name 'audio' and the provided or selected AudioStreamID i.e; finalAudioStreamID + Structs::AudioStreamStruct::Type newAudioStream; + newAudioStream.audioStreamName = CharSpan::fromCharString("audio"); + newAudioStream.audioStreamID = finalAudioStreamID; + + // Add to storage and update the list + transportOptionsPtr->AddAudioStream(newAudioStream); + } + } + + return Status::Success; +} + std::optional PushAvStreamTransportServerLogic::HandleAllocatePushTransport(CommandHandler & handler, const ConcreteCommandPath & commandPath, const Commands::AllocatePushTransport::DecodableType & commandData) @@ -605,15 +828,15 @@ PushAvStreamTransportServerLogic::HandleAllocatePushTransport(CommandHandler & h commandPath.mEndpointId, handler.GetAccessingFabricIndex(), commandData.transportOptions.TLSEndpointID, [&](auto & TLSEndpoint) -> CHIP_ERROR { // Use heap allocation for large certificate buffers to reduce stack usage - auto rootCertBuffer = std::make_unique>(); - auto clientCertBuffer = std::make_unique>(); + auto rootCertBuffer = std::make_unique>(); + auto clientCertBuffer = std::make_unique>(); Tls::CertificateTable::BufferedClientCert clientCertEntry(*clientCertBuffer); Tls::CertificateTable::BufferedRootCert rootCertEntry(*rootCertBuffer); - if (mTlsCertificateManagementDelegate != nullptr) + if (mTLSCertificateManagementDelegate != nullptr) { - auto & table = mTlsCertificateManagementDelegate->GetCertificateTable(); + auto & table = mTLSCertificateManagementDelegate->GetCertificateTable(); ReturnErrorOnFailure(table.GetClientCertificateEntry(handler.GetAccessingFabricIndex(), TLSEndpoint.ccdid.Value(), clientCertEntry)); ReturnErrorOnFailure( @@ -632,7 +855,7 @@ PushAvStreamTransportServerLogic::HandleAllocatePushTransport(CommandHandler & h ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: TLSEndpointID of command data is not valid/Provisioned", mEndpointId); auto status = to_underlying(StatusCodeEnum::kInvalidTLSEndpoint); - handler.AddClusterSpecificFailure(commandPath, status); + TEMPORARY_RETURN_IGNORED handler.AddClusterSpecificFailure(commandPath, status); return std::nullopt; }); } @@ -640,7 +863,7 @@ PushAvStreamTransportServerLogic::HandleAllocatePushTransport(CommandHandler & h { ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: TLS Client Management Delegate is not set", mEndpointId); auto status = to_underlying(StatusCodeEnum::kInvalidTLSEndpoint); - handler.AddClusterSpecificFailure(commandPath, status); + TEMPORARY_RETURN_IGNORED handler.AddClusterSpecificFailure(commandPath, status); return std::nullopt; } @@ -668,7 +891,7 @@ PushAvStreamTransportServerLogic::HandleAllocatePushTransport(CommandHandler & h "%02X and Container Format: %02X)", mEndpointId, to_underlying(ingestMethod), to_underlying(commandData.transportOptions.containerOptions.containerType)); - handler.AddClusterSpecificFailure(commandPath, status); + TEMPORARY_RETURN_IGNORED handler.AddClusterSpecificFailure(commandPath, status); return std::nullopt; } @@ -681,7 +904,7 @@ PushAvStreamTransportServerLogic::HandleAllocatePushTransport(CommandHandler & h { auto status = to_underlying(StatusCodeEnum::kInvalidURL); ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: Invalid Url", mEndpointId); - handler.AddClusterSpecificFailure(commandPath, status); + TEMPORARY_RETURN_IGNORED handler.AddClusterSpecificFailure(commandPath, status); return std::nullopt; } } @@ -692,7 +915,7 @@ PushAvStreamTransportServerLogic::HandleAllocatePushTransport(CommandHandler & h auto status = to_underlying(StatusCodeEnum::kInvalidStreamUsage); ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: StreamUsage not present in the StreamUsagePriorities list", mEndpointId); - handler.AddClusterSpecificFailure(commandPath, status); + TEMPORARY_RETURN_IGNORED handler.AddClusterSpecificFailure(commandPath, status); return std::nullopt; } @@ -704,7 +927,7 @@ PushAvStreamTransportServerLogic::HandleAllocatePushTransport(CommandHandler & h auto & motionZonesList = transportOptions.triggerOptions.motionZones; auto iterDupCheck = motionZonesList.Value().Value().begin(); size_t zoneListSize = 0; - motionZonesList.Value().Value().ComputeSize(&zoneListSize); + TEMPORARY_RETURN_IGNORED motionZonesList.Value().Value().ComputeSize(&zoneListSize); // If there are duplicate entries, reject the command std::set zoneIDsFound; @@ -763,23 +986,13 @@ PushAvStreamTransportServerLogic::HandleAllocatePushTransport(CommandHandler & h { auto status = to_underlying(StatusCodeEnum::kInvalidZone); ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: Invalid ZoneId", mEndpointId); - handler.AddClusterSpecificFailure(commandPath, status); + TEMPORARY_RETURN_IGNORED handler.AddClusterSpecificFailure(commandPath, status); return std::nullopt; } } } } - // Validate Bandwidth Requirement - Status status = mDelegate->ValidateBandwidthLimit(transportOptions.streamUsage, transportOptions.videoStreamID, - transportOptions.audioStreamID); - if (status != Status::Success) - { - ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: Resource Exhausted", mEndpointId); - handler.AddStatus(commandPath, status); - return std::nullopt; - } - std::shared_ptr transportOptionsPtr{ new (std::nothrow) TransportOptionsStorage(transportOptions) }; if (transportOptionsPtr == nullptr) @@ -789,68 +1002,12 @@ PushAvStreamTransportServerLogic::HandleAllocatePushTransport(CommandHandler & h return std::nullopt; } - if (transportOptions.videoStreamID.HasValue()) - { - if (transportOptions.videoStreamID.Value().IsNull()) - { - uint16_t videoStreamID; - - auto delegateStatus = Protocols::InteractionModel::ClusterStatusCode( - mDelegate->SelectVideoStream(transportOptions.streamUsage, videoStreamID)); - - if (!delegateStatus.IsSuccess()) - { - handler.AddStatus(commandPath, delegateStatus); - return std::nullopt; - } - - transportOptionsPtr->videoStreamID.SetValue(videoStreamID); - } - else - { - auto delegateStatus = Protocols::InteractionModel::ClusterStatusCode( - mDelegate->SetVideoStream(transportOptions.videoStreamID.Value().Value())); + auto validateStreamStatus = ValidateStreamParameters(handler, commandPath, transportOptions, transportOptionsPtr); - if (!delegateStatus.IsSuccess()) - { - auto cluster_status = to_underlying(StatusCodeEnum::kInvalidStream); - ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: Invalid Video Stream ", mEndpointId); - handler.AddClusterSpecificFailure(commandPath, cluster_status); - return std::nullopt; - } - } - } - - if (transportOptions.audioStreamID.HasValue()) + if (validateStreamStatus != Status::Success) { - if (transportOptions.audioStreamID.Value().IsNull()) - { - uint16_t audioStreamID; - - auto delegateStatus = Protocols::InteractionModel::ClusterStatusCode( - mDelegate->SelectAudioStream(transportOptions.streamUsage, audioStreamID)); - - if (!delegateStatus.IsSuccess()) - { - handler.AddStatus(commandPath, delegateStatus); - return std::nullopt; - } - - transportOptionsPtr->audioStreamID.SetValue(audioStreamID); - } - else - { - auto delegateStatus = Protocols::InteractionModel::ClusterStatusCode( - mDelegate->SetAudioStream(transportOptions.audioStreamID.Value().Value())); - - if (!delegateStatus.IsSuccess()) - { - auto cluster_status = to_underlying(StatusCodeEnum::kInvalidStream); - ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: Invalid Audio Stream ", mEndpointId); - handler.AddClusterSpecificFailure(commandPath, cluster_status); - return std::nullopt; - } - } + ChipLogError(Camera, "HandleAllocatePushTransport[ep=%d]: Stream validation failed", mEndpointId); + return validateStreamStatus; } if (transportOptions.containerOptions.containerType == ContainerFormatEnum::kCmaf && @@ -866,12 +1023,59 @@ PushAvStreamTransportServerLogic::HandleAllocatePushTransport(CommandHandler & h { auto segmentDurationStatus = to_underlying(StatusCodeEnum::kInvalidOptions); ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: Segment Duration not within allowed range", mEndpointId); - handler.AddClusterSpecificFailure(commandPath, segmentDurationStatus); + TEMPORARY_RETURN_IGNORED handler.AddClusterSpecificFailure(commandPath, segmentDurationStatus); return std::nullopt; } } } + // Validate Bandwidth Requirement + Optional> firstVideoStreamID; + Optional> firstAudioStreamID; + + if (transportOptions.videoStreams.HasValue()) + { + auto videoIter = transportOptions.videoStreams.Value().begin(); + if (videoIter.Next()) + { + firstVideoStreamID.SetValue(videoIter.GetValue().videoStreamID); + transportOptionsPtr->videoStreamID = firstVideoStreamID; + } + } + if (transportOptions.audioStreams.HasValue()) + { + auto audioIter = transportOptions.audioStreams.Value().begin(); + if (audioIter.Next()) + { + firstAudioStreamID.SetValue(audioIter.GetValue().audioStreamID); + transportOptionsPtr->audioStreamID = firstAudioStreamID; + } + } + + Status retStatus = mDelegate->ValidateBandwidthLimit(transportOptions.streamUsage, firstVideoStreamID, firstAudioStreamID); + + if (retStatus != Status::Success) + { + ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: Resource Exhausted", mEndpointId); + handler.AddStatus(commandPath, retStatus); + return std::nullopt; + } + + // Validate MaxPreRollLength constraint + if (transportOptionsPtr->videoStreamID.HasValue() && transportOptions.triggerOptions.maxPreRollLen.HasValue()) + { + uint16_t maxPreRollLength = transportOptions.triggerOptions.maxPreRollLen.Value(); + if (maxPreRollLength != 0 && + !mDelegate->ValidateMaxPreRollLength(maxPreRollLength, transportOptionsPtr->videoStreamID.Value())) + { + auto maxPreRollLengthStatus = to_underlying(StatusCodeEnum::kInvalidPreRollLength); + ChipLogError(Zcl, "HandleAllocatePushTransport[ep=%d]: MaxPreRollLength (%u) validation failed", mEndpointId, + maxPreRollLength); + TEMPORARY_RETURN_IGNORED handler.AddClusterSpecificFailure(commandPath, maxPreRollLengthStatus); + return std::nullopt; + } + } + uint16_t connectionID = GenerateConnectionID(); if (connectionID == kMaxConnectionId) @@ -883,9 +1087,9 @@ PushAvStreamTransportServerLogic::HandleAllocatePushTransport(CommandHandler & h FabricIndex accessingFabricIndex = handler.GetAccessingFabricIndex(); - status = mDelegate->AllocatePushTransport(*transportOptionsPtr, connectionID, accessingFabricIndex); + retStatus = mDelegate->AllocatePushTransport(*transportOptionsPtr, connectionID, accessingFabricIndex); - if (status == Status::Success) + if (retStatus == Status::Success) { // add connection to CurrentConnections TransportConfigurationStorage outTransportConfiguration(connectionID, transportOptionsPtr); @@ -901,14 +1105,14 @@ PushAvStreamTransportServerLogic::HandleAllocatePushTransport(CommandHandler & h // ExpiryTime Handling if (transportOptions.expiryTime.HasValue()) { - ScheduleTransportDeallocate(connectionID, transportOptions.expiryTime.Value()); + TEMPORARY_RETURN_IGNORED ScheduleTransportDeallocate(connectionID, transportOptions.expiryTime.Value()); } handler.AddResponse(commandPath, response); } else { - handler.AddStatus(commandPath, status); + handler.AddStatus(commandPath, retStatus); } return std::nullopt; @@ -1006,6 +1210,14 @@ PushAvStreamTransportServerLogic::HandleModifyPushTransport(CommandHandler & han return std::nullopt; } + auto validateStreamStatus = ValidateStreamParameters(handler, commandPath, transportOptions, transportOptionsPtr); + + if (validateStreamStatus != Status::Success) + { + ChipLogError(Camera, "HandleAllocatePushTransport[ep=%d]: Stream validation failed", mEndpointId); + return validateStreamStatus; + } + // Call the delegate status = mDelegate->ModifyPushTransport(connectionID, *transportOptionsPtr); @@ -1153,7 +1365,7 @@ std::optional PushAvStreamTransportServerLogic::H { auto clusterStatus = to_underlying(StatusCodeEnum::kInvalidTransportStatus); ChipLogError(Zcl, "HandleManuallyTriggerTransport[ep=%d]: Invalid Transport status", mEndpointId); - handler.AddClusterSpecificFailure(commandPath, clusterStatus); + TEMPORARY_RETURN_IGNORED handler.AddClusterSpecificFailure(commandPath, clusterStatus); return std::nullopt; } @@ -1161,7 +1373,7 @@ std::optional PushAvStreamTransportServerLogic::H { auto clusterStatus = to_underlying(StatusCodeEnum::kInvalidTriggerType); ChipLogError(Zcl, "HandleManuallyTriggerTransport[ep=%d]: Invalid Trigger type", mEndpointId); - handler.AddClusterSpecificFailure(commandPath, clusterStatus); + TEMPORARY_RETURN_IGNORED handler.AddClusterSpecificFailure(commandPath, clusterStatus); return std::nullopt; } @@ -1184,7 +1396,29 @@ std::optional PushAvStreamTransportServerLogic::H if (status == Status::Success) { - GeneratePushTransportBeginEvent(connectionID, TransportTriggerTypeEnum::kCommand, MakeOptional(activationReason)); + // Get container type from transport configuration + ContainerFormatEnum containerType = transportConfiguration->transportOptions.Value().containerOptions.containerType; + + // For CMAF container type, we need to provide CMAF session number + Optional cmafSessionNumber; + if (containerType == ContainerFormatEnum::kCmaf) + { + uint64_t sessionNumber = 0; + if (mDelegate != nullptr && mDelegate->GetCMAFSessionNumber(connectionID, sessionNumber)) + { + cmafSessionNumber = MakeOptional(sessionNumber); + } + else + { + ChipLogError(Zcl, "GeneratePushTransportBeginEvent: Unable to get CMAF session number for connection %u", + connectionID); + // Don't include the session number if we can't get it + cmafSessionNumber = Optional(); + } + } + + GeneratePushTransportBeginEvent(connectionID, TransportTriggerTypeEnum::kCommand, MakeOptional(activationReason), + containerType, cmafSessionNumber); } handler.AddStatus(commandPath, status); @@ -1310,17 +1544,19 @@ Status PushAvStreamTransportServerLogic::CheckPrivacyModes(StreamUsageEnum strea return Status::Success; } -Status -PushAvStreamTransportServerLogic::GeneratePushTransportBeginEvent(const uint16_t connectionID, - const TransportTriggerTypeEnum triggerType, - const Optional activationReason) +Status PushAvStreamTransportServerLogic::GeneratePushTransportBeginEvent( + const uint16_t connectionID, const TransportTriggerTypeEnum triggerType, + const Optional activationReason, const ContainerFormatEnum containerType, + const Optional cmafSessionNumber) { Events::PushTransportBegin::Type event; EventNumber eventNumber; - event.connectionID = connectionID; - event.triggerType = triggerType; - event.activationReason = activationReason; + event.connectionID = connectionID; + event.triggerType = triggerType; + event.activationReason = activationReason; + event.containerType = containerType; + event.CMAFSessionNumber = cmafSessionNumber; CHIP_ERROR err = LogEvent(event, mEndpointId, eventNumber); if (CHIP_NO_ERROR != err) @@ -1339,6 +1575,40 @@ Status PushAvStreamTransportServerLogic::GeneratePushTransportEndEvent(const uin event.connectionID = connectionID; + // Get container type from transport configuration to include in the event + TransportConfigurationStorage * transportConfig = FindStreamTransportConnection(connectionID); + if (transportConfig != nullptr) + { + event.containerType = transportConfig->transportOptions.Value().containerOptions.containerType; + + // For CMAF container type, we need to provide CMAF session number + if (event.containerType == ContainerFormatEnum::kCmaf) + { + uint64_t sessionNumber = 0; + if (mDelegate != nullptr && mDelegate->GetCMAFSessionNumber(connectionID, sessionNumber)) + { + event.CMAFSessionNumber = MakeOptional(sessionNumber); + } + else + { + ChipLogError(Zcl, "GeneratePushTransportEndEvent: Unable to get CMAF session number for connection %u", + connectionID); + // Don't include the session number if we can't get it + event.CMAFSessionNumber = Optional(); + } + } + else + { + event.CMAFSessionNumber = Optional(); + } + } + else + { + // Fallback values if transport config not found + event.containerType = ContainerFormatEnum::kCmaf; // Default fallback + event.CMAFSessionNumber = Optional(); + } + CHIP_ERROR err = LogEvent(event, mEndpointId, eventNumber); if (CHIP_NO_ERROR != err) { @@ -1363,8 +1633,28 @@ Status PushAvStreamTransportServerLogic::NotifyTransportStarted(uint16_t connect return Status::NotFound; } + // Get container type from transport configuration + ContainerFormatEnum containerType = transportConfig->transportOptions.Value().containerOptions.containerType; + + // For CMAF container type, we need to provide CMAF session number + Optional cmafSessionNumber; + if (containerType == ContainerFormatEnum::kCmaf) + { + uint64_t sessionNumber = 0; + if (mDelegate != nullptr && mDelegate->GetCMAFSessionNumber(connectionID, sessionNumber)) + { + cmafSessionNumber = MakeOptional(sessionNumber); + } + else + { + ChipLogError(Zcl, "NotifyTransportStarted: Unable to get CMAF session number for connection %u", connectionID); + // Don't include the session number if we can't get it + cmafSessionNumber = Optional(); + } + } + // Generate the PushTransportBegin event - return GeneratePushTransportBeginEvent(connectionID, triggerType, activationReason); + return GeneratePushTransportBeginEvent(connectionID, triggerType, activationReason, containerType, cmafSessionNumber); } Status PushAvStreamTransportServerLogic::NotifyTransportStopped(uint16_t connectionID, TransportTriggerTypeEnum triggerType) diff --git a/src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-logic.h b/src/app/clusters/push-av-stream-transport-server/PushAVStreamTransportLogic.h similarity index 85% rename from src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-logic.h rename to src/app/clusters/push-av-stream-transport-server/PushAVStreamTransportLogic.h index 69049c19089..549e434c008 100644 --- a/src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-logic.h +++ b/src/app/clusters/push-av-stream-transport-server/PushAVStreamTransportLogic.h @@ -6,8 +6,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include @@ -33,7 +33,7 @@ class PushAvStreamTransportServerLogic } } - void SetTLSClientManagementDelegate(TlsClientManagementDelegate * delegate) + void SetTLSClientManagementDelegate(TLSClientManagementDelegate * delegate) { mTLSClientManagementDelegate = delegate; if (mTLSClientManagementDelegate == nullptr) @@ -43,10 +43,10 @@ class PushAvStreamTransportServerLogic } } - void SetTlsCertificateManagementDelegate(TlsCertificateManagementDelegate * delegate) + void SetTLSCertificateManagementDelegate(TLSCertificateManagementDelegate * delegate) { - mTlsCertificateManagementDelegate = delegate; - if (mTlsCertificateManagementDelegate == nullptr) + mTLSCertificateManagementDelegate = delegate; + if (mTLSCertificateManagementDelegate == nullptr) { ChipLogError(Zcl, "Push AV Stream Transport: Trying to set TLS Certificate Management delegate to null"); return; @@ -92,6 +92,11 @@ class PushAvStreamTransportServerLogic Protocols::InteractionModel::Status ValidateIncomingTransportOptions( const PushAvStreamTransport::Structs::TransportOptionsStruct::DecodableType & transportOptions); + std::optional + ValidateStreamParameters(CommandHandler & handler, const ConcreteCommandPath & commandPath, + const PushAvStreamTransport::Structs::TransportOptionsStruct::DecodableType & transportOptions, + const std::shared_ptr transportOptionsPtr); + std::optional HandleAllocatePushTransport(CommandHandler & handler, const ConcreteCommandPath & commandPath, const PushAvStreamTransport::Commands::AllocatePushTransport::DecodableType & commandData); @@ -119,13 +124,15 @@ class PushAvStreamTransportServerLogic // Send Push AV Stream Transport events Protocols::InteractionModel::Status GeneratePushTransportBeginEvent(const uint16_t connectionID, const PushAvStreamTransport::TransportTriggerTypeEnum triggerType, - const Optional activationReason); + const Optional activationReason, + const PushAvStreamTransport::ContainerFormatEnum containerType, + const Optional cmafSessionNumber = Optional()); Protocols::InteractionModel::Status GeneratePushTransportEndEvent(const uint16_t connectionID); private: PushAvStreamTransportDelegate * mDelegate = nullptr; - TlsClientManagementDelegate * mTLSClientManagementDelegate = nullptr; - TlsCertificateManagementDelegate * mTlsCertificateManagementDelegate = nullptr; + TLSClientManagementDelegate * mTLSClientManagementDelegate = nullptr; + TLSCertificateManagementDelegate * mTLSCertificateManagementDelegate = nullptr; /// Convenience method that returns if the internal delegate is null and will log /// an error if the check returns true diff --git a/src/app/clusters/push-av-stream-transport-server/app_config_dependent_sources.cmake b/src/app/clusters/push-av-stream-transport-server/app_config_dependent_sources.cmake index 0053a93e482..687cc92fb14 100644 --- a/src/app/clusters/push-av-stream-transport-server/app_config_dependent_sources.cmake +++ b/src/app/clusters/push-av-stream-transport-server/app_config_dependent_sources.cmake @@ -16,10 +16,10 @@ TARGET_SOURCES( ${APP_TARGET} PRIVATE - "${CLUSTER_DIR}/push-av-stream-transport-cluster.cpp" - "${CLUSTER_DIR}/push-av-stream-transport-cluster.h" - "${CLUSTER_DIR}/push-av-stream-transport-logic.cpp" - "${CLUSTER_DIR}/push-av-stream-transport-logic.h" + "${CLUSTER_DIR}/PushAVStreamTransportCluster.cpp" + "${CLUSTER_DIR}/PushAVStreamTransportCluster.h" + "${CLUSTER_DIR}/PushAVStreamTransportLogic.cpp" + "${CLUSTER_DIR}/PushAVStreamTransportLogic.h" "${CLUSTER_DIR}/push-av-stream-transport-delegate.h" "${CLUSTER_DIR}/CodegenIntegration.cpp" "${CLUSTER_DIR}/CodegenIntegration.h" diff --git a/src/app/clusters/push-av-stream-transport-server/constants.h b/src/app/clusters/push-av-stream-transport-server/constants.h index b58c238aa34..44b368ebe5f 100644 --- a/src/app/clusters/push-av-stream-transport-server/constants.h +++ b/src/app/clusters/push-av-stream-transport-server/constants.h @@ -34,13 +34,15 @@ using TransportOptionsStruct = Structs::TransportOptionsStruct: using TransportConfigurationStruct = Structs::TransportConfigurationStruct::Type; using StreamUsageEnum = chip::app::Clusters::Globals::StreamUsageEnum; -static constexpr size_t kMinUrlLength = 13u; -static constexpr size_t kMaxUrlLength = 2000u; -static constexpr size_t kMaxCENCKeyLength = 16u; -static constexpr size_t kMaxCENCKeyIDLength = 16u; -static constexpr size_t kMaxTrackNameLength = 16u; -static constexpr size_t kMinSegmentDuration = 500u; -static constexpr size_t kMaxSegmentDuration = 65500u; +static constexpr size_t kMinUrlLength = 13u; +static constexpr size_t kMaxUrlLength = 2000u; +static constexpr size_t kMaxCENCKeyLength = 16u; +static constexpr size_t kMaxCENCKeyIDLength = 16u; +static constexpr size_t kMaxTrackNameLength = 16u; +static constexpr size_t kMinSegmentDuration = 500u; +static constexpr size_t kMaxSegmentDuration = 65500u; +static constexpr size_t kMinStreamNameLength = 1u; +static constexpr size_t kMaxStreamNameLength = 16u; enum class PushAvStreamTransportStatusEnum : uint8_t { diff --git a/src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-delegate.h b/src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-delegate.h index 764c185f21f..481c192537b 100644 --- a/src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-delegate.h +++ b/src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-delegate.h @@ -21,8 +21,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include @@ -51,7 +51,7 @@ class PushAvStreamTransportDelegate * * @param transportOptions The configuration options of the transport to be allocated * @param connectionID The connectionID to allocate - * @param AccessingFabricIndex The FrabricIndex of the assosciated Fabric + * @param AccessingFabricIndex The FabricIndex of the associated Fabric * @return Success if allocation is successful and a PushTransportConnectionID was produced; * otherwise, the command is rejected with Failure * @@ -84,7 +84,7 @@ class PushAvStreamTransportDelegate * Failure if modification fails * * @note The buffers storing URL, Trigger Options, Motion Zones, Container Options are owned by - * the PushAVStreamTransport Server. The allocated buffers are cleared and reassigned to modified + * the Push AV Stream Transport server. The allocated buffers are cleared and reassigned to modified * transportOptions on success of ModifyPushTransport and deallocated on success of DeallocatePushTransport. */ virtual Protocols::InteractionModel::Status @@ -142,12 +142,22 @@ class PushAvStreamTransportDelegate * @brief Validates the provided Segment Duration. * * @param segmentDuration The Segment Duration to validate - * @param videoStreamId The video stream to eb validated against + * @param videoStreamId The video stream to be validated against * @return true if Segment Duration is multiple of KeyFrameInterval for the provided videoStreamId, false otherwise */ virtual bool ValidateSegmentDuration(uint16_t segmentDuration, const Optional> & videoStreamId) = 0; + /** + * @brief Validates the provided Max Pre Roll Length. + * + * @param maxPreRollLength Max Pre Roll length to validate + * @param videoStreamId The video stream ID to be validated against + * @return true if the Max pre-roll length is greater than or equal to KeyFrameInterval for the provided videoStreamId, false + otherwise + */ + virtual bool ValidateMaxPreRollLength(uint16_t maxPreRollLength, const DataModel::Nullable & videoStreamId) = 0; + /** * @brief Validates bandwidth requirements against camera's resource management. * @@ -275,7 +285,7 @@ class PushAvStreamTransportDelegate /** * @brief Verifies whether Hard privacy mode is active on the device as set against the stream management instance * - * @param isActive boolean that is set by the delgate indicating privacy status, True is active + * @param isActive boolean that is set by the delegate indicating privacy status, True is active * @return CHIP_ERROR indicating success or failure */ virtual CHIP_ERROR IsHardPrivacyModeActive(bool & isActive) = 0; @@ -283,7 +293,7 @@ class PushAvStreamTransportDelegate /** * @brief Verifies whether Soft Recording privacy mode is active on the device as set against the stream management instance * - * @param isActive boolean that is set by the delgate indicating privacy status, True is active + * @param isActive boolean that is set by the delegate indicating privacy status, True is active * @return CHIP_ERROR indicating success or failure */ virtual CHIP_ERROR IsSoftRecordingPrivacyModeActive(bool & isActive) = 0; @@ -291,11 +301,20 @@ class PushAvStreamTransportDelegate /** * @brief Verifies whether Soft Livestream privacy mode is active on the device as set against the stream management instance * - * @param isActive boolean that is set by the delgate indicating privacy status, True is active + * @param isActive boolean that is set by the delegate indicating privacy status, True is active * @return CHIP_ERROR indicating success or failure */ virtual CHIP_ERROR IsSoftLivestreamPrivacyModeActive(bool & isActive) = 0; + /** + * @brief Gets the current CMAF session number for the specified connection. + * + * @param connectionID The connection ID for which to get the session number + * @param sessionNumber Output parameter for the current session number + * @return true if a session number is available, false otherwise + */ + virtual bool GetCMAFSessionNumber(const uint16_t connectionID, uint64_t & sessionNumber) = 0; + /** * @brief Sets the PushAvStreamTransportServer instance for the delegate. * @@ -307,6 +326,7 @@ class PushAvStreamTransportDelegate */ virtual void SetPushAvStreamTransportServer(PushAvStreamTransportServer * server) = 0; }; + } // namespace Clusters } // namespace app } // namespace chip diff --git a/src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-storage.h b/src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-storage.h index f9cb8e04b47..f331914855c 100644 --- a/src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-storage.h +++ b/src/app/clusters/push-av-stream-transport-server/push-av-stream-transport-storage.h @@ -165,7 +165,7 @@ struct CMAFContainerOptionsStorage : public CMAFContainerOptionsStruct { MutableByteSpan CENCKeyBuffer(mCENCKeyBuffer); // ValidateIncomingTransportOptions() function already checked the CENCKey length - CopySpanToMutableSpan(aCMAFContainerOptions.CENCKey.Value(), CENCKeyBuffer); + TEMPORARY_RETURN_IGNORED CopySpanToMutableSpan(aCMAFContainerOptions.CENCKey.Value(), CENCKeyBuffer); CENCKey.SetValue(CENCKeyBuffer); } else @@ -179,7 +179,7 @@ struct CMAFContainerOptionsStorage : public CMAFContainerOptionsStruct { MutableByteSpan CENCKeyIDBuffer(mCENCKeyIDBuffer); // ValidateIncomingTransportOptions() function already checked the CENCKeyID length - CopySpanToMutableSpan(aCMAFContainerOptions.CENCKeyID.Value(), CENCKeyIDBuffer); + TEMPORARY_RETURN_IGNORED CopySpanToMutableSpan(aCMAFContainerOptions.CENCKeyID.Value(), CENCKeyIDBuffer); CENCKeyID.SetValue(CENCKeyIDBuffer); } else @@ -284,6 +284,30 @@ struct TransportOptionsStorage : public TransportOptionsStruct expiryTime = aTransportOptionsStorage.expiryTime; + // Copy video streams storage + mVideoStreamsStorage = aTransportOptionsStorage.mVideoStreamsStorage; + if (!mVideoStreamsStorage.empty()) + { + videoStreams.SetValue( + DataModel::List(mVideoStreamsStorage.data(), mVideoStreamsStorage.size())); + } + else + { + videoStreams.ClearValue(); + } + + // Copy audio streams storage + mAudioStreamsStorage = aTransportOptionsStorage.mAudioStreamsStorage; + if (!mAudioStreamsStorage.empty()) + { + audioStreams.SetValue( + DataModel::List(mAudioStreamsStorage.data(), mAudioStreamsStorage.size())); + } + else + { + audioStreams.ClearValue(); + } + return *this; } @@ -309,15 +333,109 @@ struct TransportOptionsStorage : public TransportOptionsStruct expiryTime = transportOptions.expiryTime; + // Handle videoStreams from decodable type + if (transportOptions.videoStreams.HasValue()) + { + mVideoStreamsStorage.clear(); + auto iter = transportOptions.videoStreams.Value().begin(); + while (iter.Next()) + { + auto & videoStream = iter.GetValue(); + mVideoStreamsStorage.push_back(videoStream); + } + videoStreams.SetValue( + DataModel::List(mVideoStreamsStorage.data(), mVideoStreamsStorage.size())); + } + else + { + mVideoStreamsStorage.clear(); + videoStreams.ClearValue(); + } + + // Handle audioStreams from decodable type + if (transportOptions.audioStreams.HasValue()) + { + mAudioStreamsStorage.clear(); + auto iter = transportOptions.audioStreams.Value().begin(); + while (iter.Next()) + { + auto & audioStream = iter.GetValue(); + mAudioStreamsStorage.push_back(audioStream); + } + audioStreams.SetValue( + DataModel::List(mAudioStreamsStorage.data(), mAudioStreamsStorage.size())); + } + else + { + mAudioStreamsStorage.clear(); + audioStreams.ClearValue(); + } + return *this; } TransportOptionsStorage(const Structs::TransportOptionsStruct::DecodableType & transportOptions) { *this = transportOptions; } + // Public methods to manage video streams without exposing internal storage + void ClearVideoStreams() + { + mVideoStreamsStorage.clear(); + videoStreams.ClearValue(); + } + + void AddVideoStream(const Structs::VideoStreamStruct::Type & videoStream) + { + mVideoStreamsStorage.push_back(videoStream); + videoStreams.SetValue( + DataModel::List(mVideoStreamsStorage.data(), mVideoStreamsStorage.size())); + } + + void UpdateVideoStreamsList() + { + if (!mVideoStreamsStorage.empty()) + { + videoStreams.SetValue( + DataModel::List(mVideoStreamsStorage.data(), mVideoStreamsStorage.size())); + } + else + { + videoStreams.ClearValue(); + } + } + + // Public methods to manage audio streams without exposing internal storage + void ClearAudioStreams() + { + mAudioStreamsStorage.clear(); + audioStreams.ClearValue(); + } + + void AddAudioStream(const Structs::AudioStreamStruct::Type & audioStream) + { + mAudioStreamsStorage.push_back(audioStream); + audioStreams.SetValue( + DataModel::List(mAudioStreamsStorage.data(), mAudioStreamsStorage.size())); + } + + void UpdateAudioStreamsList() + { + if (!mAudioStreamsStorage.empty()) + { + audioStreams.SetValue( + DataModel::List(mAudioStreamsStorage.data(), mAudioStreamsStorage.size())); + } + else + { + audioStreams.ClearValue(); + } + } + private: char mUrlBuffer[kMaxUrlLength]; TransportTriggerOptionsStorage mTriggerOptionsStorage; ContainerOptionsStorage mContainerOptionsStorage; + std::vector mVideoStreamsStorage; + std::vector mAudioStreamsStorage; }; /** diff --git a/src/app/clusters/push-av-stream-transport-server/tests/TestPushAVStreamTransportCluster.cpp b/src/app/clusters/push-av-stream-transport-server/tests/TestPushAVStreamTransportCluster.cpp index 163b814a264..bb7ad29f842 100644 --- a/src/app/clusters/push-av-stream-transport-server/tests/TestPushAVStreamTransportCluster.cpp +++ b/src/app/clusters/push-av-stream-transport-server/tests/TestPushAVStreamTransportCluster.cpp @@ -24,9 +24,9 @@ #include #include #include -#include +#include #include -#include +#include #include #include #include @@ -220,6 +220,11 @@ class TestPushAVStreamTransportDelegateImpl : public PushAvStreamTransportDelega return true; } + bool ValidateMaxPreRollLength(uint16_t maxPreRollLength, const DataModel::Nullable & videoStreamId) override + { + return true; + } + Protocols::InteractionModel::Status ValidateBandwidthLimit(StreamUsageEnum streamUsage, const Optional> & videoStreamId, const Optional> & audioStreamId) override @@ -330,12 +335,18 @@ class TestPushAVStreamTransportDelegateImpl : public PushAvStreamTransportDelega { // No-op implementation for tests } + bool GetCMAFSessionNumber(const uint16_t connectionID, uint64_t & sessionNumber) override + { + // Mock implementation for tests - return a simple session number + sessionNumber = static_cast(connectionID) + 2000; + return true; + } private: std::vector pushavStreams; }; -class TestTlsClientManagementDelegate : public TlsClientManagementDelegate +class TestTLSClientManagementDelegate : public TLSClientManagementDelegate { public: @@ -617,7 +628,7 @@ TEST_F(TestPushAVStreamTransportServerLogic, Test_AllocateTransport_AllocateTran PushAvStreamTransportServer server(1, BitFlags(1)); TestPushAVStreamTransportDelegateImpl mockDelegate; - TestTlsClientManagementDelegate tlsClientManagementDelegate; + TestTLSClientManagementDelegate tlsClientManagementDelegate; MockCommandHandler commandHandler; commandHandler.SetFabricIndex(1); @@ -1004,7 +1015,7 @@ TEST_F(MockEventLogging, Test_AllocateTransport_ModifyTransport_FindTransport_Fi PushAvStreamTransportServer server(1, BitFlags(1)); TestPushAVStreamTransportDelegateImpl mockDelegate; - TestTlsClientManagementDelegate tlsClientManagementDelegate; + TestTLSClientManagementDelegate tlsClientManagementDelegate; MockCommandHandler commandHandler; commandHandler.SetFabricIndex(1); @@ -1339,7 +1350,7 @@ TEST_F(MockEventLogging, Test_AllocateTransport_SetTransportStatus_ManuallyTrigg PushAvStreamTransportServer server(1, BitFlags(1)); TestPushAVStreamTransportDelegateImpl mockDelegate; - TestTlsClientManagementDelegate tlsClientManagementDelegate; + TestTLSClientManagementDelegate tlsClientManagementDelegate; MockCommandHandler commandHandler; commandHandler.SetFabricIndex(1); diff --git a/src/app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.h b/src/app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.h index 22729352e79..1c1f63429a2 100644 --- a/src/app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.h +++ b/src/app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.h @@ -97,13 +97,13 @@ struct ReplacementProductStruct : private HepaFilterMonitoring::Structs::Replace chip::CharSpan aProductIdentifierValue) { SetProductIdentifierType(aProductIdentifierType); - SetProductIdentifierValue(aProductIdentifierValue); + TEMPORARY_RETURN_IGNORED SetProductIdentifierValue(aProductIdentifierValue); } ReplacementProductStruct & operator=(const ReplacementProductStruct & aReplacementProductStruct) { SetProductIdentifierType(aReplacementProductStruct.GetProductIdentifierType()); - SetProductIdentifierValue(aReplacementProductStruct.GetProductIdentifierValue()); + TEMPORARY_RETURN_IGNORED SetProductIdentifierValue(aReplacementProductStruct.GetProductIdentifierValue()); return *this; } diff --git a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp index 6a1cc9cb85a..02d1e887f01 100644 --- a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp +++ b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp @@ -61,7 +61,7 @@ Instance::~Instance() { mDelegate->SetInstance(nullptr); } - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); + TEMPORARY_RETURN_IGNORED CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); AttributeAccessInterfaceRegistry::Instance().Unregister(this); } @@ -134,7 +134,7 @@ chip::Protocols::InteractionModel::Status Instance::UpdateLastChangedTime(DataMo mLastChangedTime = aNewLastChangedTime; if (mLastChangedTime != oldLastchangedTime) { - chip::app::GetSafeAttributePersistenceProvider()->WriteScalarValue( + TEMPORARY_RETURN_IGNORED chip::app::GetSafeAttributePersistenceProvider()->WriteScalarValue( ConcreteAttributePath(mEndpointId, mClusterId, Attributes::LastChangedTime::Id), mLastChangedTime); MatterReportingAttributeChangeCallback(mEndpointId, mClusterId, Attributes::LastChangedTime::Id); } @@ -212,7 +212,7 @@ CHIP_ERROR Instance::ReadReplaceableProductList(AttributeValueEncoder & aEncoder ReplacementProductListManager * productListManagerInstance = GetReplacementProductListManagerInstance(); if (nullptr == productListManagerInstance) { - aEncoder.EncodeEmptyList(); + TEMPORARY_RETURN_IGNORED aEncoder.EncodeEmptyList(); return CHIP_NO_ERROR; } @@ -278,7 +278,7 @@ CHIP_ERROR Instance::Write(const ConcreteDataAttributePath & aPath, AttributeVal case Attributes::LastChangedTime::Id: { DataModel::Nullable newLastChangedTime; ReturnErrorOnFailure(aDecoder.Decode(newLastChangedTime)); - UpdateLastChangedTime(newLastChangedTime); + TEMPORARY_RETURN_IGNORED UpdateLastChangedTime(newLastChangedTime); break; } } diff --git a/src/app/clusters/scenes-server/SceneTableImpl.cpp b/src/app/clusters/scenes-server/SceneTableImpl.cpp index fcd34b6d346..367626a2f46 100644 --- a/src/app/clusters/scenes-server/SceneTableImpl.cpp +++ b/src/app/clusters/scenes-server/SceneTableImpl.cpp @@ -132,14 +132,14 @@ CHIP_ERROR DefaultSceneTableImpl::GetRemainingCapacity(FabricIndex fabric_index, CHIP_ERROR DefaultSceneTableImpl::SetSceneTableEntry(FabricIndex fabric_index, const SceneTableEntry & entry) { // Scene data is small, buffer can be allocated on stack - PersistentStore writeBuffer; + PersistenceBuffer writeBuffer; return this->SetTableEntry(fabric_index, entry.mStorageId, entry.mStorageData, writeBuffer); } CHIP_ERROR DefaultSceneTableImpl::GetSceneTableEntry(FabricIndex fabric_index, SceneStorageId scene_id, SceneTableEntry & entry) { // All data is copied to SceneTableEntry, buffer can be allocated on stack - PersistentStore store; + PersistenceBuffer store; ReturnErrorOnFailure(this->GetTableEntry(fabric_index, scene_id, entry.mStorageData, store)); entry.mStorageId = scene_id; return CHIP_NO_ERROR; @@ -283,7 +283,7 @@ CHIP_ERROR DefaultSceneTableImpl::SceneApplyEFS(const SceneTableEntry & scene) for (uint8_t i = 0; i < scene.mStorageData.mExtensionFieldSets.GetFieldSetCount(); i++) { ExtensionFieldSet EFS; - scene.mStorageData.mExtensionFieldSets.GetFieldSetAtPosition(EFS, i); + TEMPORARY_RETURN_IGNORED scene.mStorageData.mExtensionFieldSets.GetFieldSetAtPosition(EFS, i); ByteSpan EFSSpan = MutableByteSpan(EFS.mBytesBuffer, EFS.mUsedBytes); if (!EFS.IsEmpty()) diff --git a/src/app/clusters/scenes-server/scenes-server.cpp b/src/app/clusters/scenes-server/scenes-server.cpp index b5dfb958e17..1efb58bb7b1 100644 --- a/src/app/clusters/scenes-server/scenes-server.cpp +++ b/src/app/clusters/scenes-server/scenes-server.cpp @@ -317,7 +317,7 @@ class ScenesClusterFabricDelegate : public chip::FabricTable::Delegate SceneTable * sceneTable = scenes::GetSceneTableImpl(); VerifyOrReturn(nullptr != sceneTable); // The implementation of SceneTable::RemoveFabric() must not call back into the FabricTable - sceneTable->RemoveFabric(fabricIndex); + TEMPORARY_RETURN_IGNORED sceneTable->RemoveFabric(fabricIndex); } }; @@ -343,7 +343,7 @@ CHIP_ERROR ScenesServer::Init() void ScenesServer::Shutdown() { Server::GetInstance().GetFabricTable().RemoveFabricDelegate(&gFabricDelegate); - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); + TEMPORARY_RETURN_IGNORED CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); AttributeAccessInterfaceRegistry::Instance().Unregister(this); mGroupProvider = nullptr; @@ -420,7 +420,7 @@ void AddSceneParse(CommandHandlerInterface::HandlerContext & ctx, const CommandD if (!tempEFS.IsEmpty()) { - storageData.mExtensionFieldSets.InsertFieldSet(tempEFS); + TEMPORARY_RETURN_IGNORED storageData.mExtensionFieldSets.InsertFieldSet(tempEFS); } } ReturnOnFailure(AddResponseOnError(ctx, response, fieldSetIter.GetStatus())); @@ -507,7 +507,7 @@ void ViewSceneParse(HandlerContext & ctx, const CommandData & req, GroupDataProv { // gets data from the field in the scene ExtensionFieldSet tempField; - scene.mStorageData.mExtensionFieldSets.GetFieldSetAtPosition(tempField, i); + TEMPORARY_RETURN_IGNORED scene.mStorageData.mExtensionFieldSets.GetFieldSetAtPosition(tempField, i); ByteSpan efsSpan(tempField.mBytesBuffer, tempField.mUsedBytes); // This should only find one handle per cluster @@ -694,7 +694,7 @@ CHIP_ERROR ScenesServer::Read(const ConcreteReadAttributePath & aPath, Attribute for (auto & info : fabricSceneInfoSpan) { // Update the SceneInfoStruct's Capacity in case it's capacity was limited by other fabrics - sceneTable->GetRemainingCapacity(info.fabricIndex, info.remainingCapacity); + TEMPORARY_RETURN_IGNORED sceneTable->GetRemainingCapacity(info.fabricIndex, info.remainingCapacity); ReturnErrorOnFailure(encoder.Encode(info)); } return CHIP_NO_ERROR; @@ -731,7 +731,7 @@ void ScenesServer::GroupWillBeRemoved(FabricIndex aFabricIx, EndpointId aEndpoin // because the scene we have (if any) will also be removed. if (aGroupId == currentGroup) { - MakeSceneInvalid(aEndpointId, aFabricIx); + TEMPORARY_RETURN_IGNORED MakeSceneInvalid(aEndpointId, aFabricIx); } VerifyOrReturn(nullptr != mGroupProvider); @@ -740,31 +740,32 @@ void ScenesServer::GroupWillBeRemoved(FabricIndex aFabricIx, EndpointId aEndpoin return; } - sceneTable->DeleteAllScenesInGroup(aFabricIx, aGroupId); + TEMPORARY_RETURN_IGNORED sceneTable->DeleteAllScenesInGroup(aFabricIx, aGroupId); } void ScenesServer::MakeSceneInvalid(EndpointId aEndpointId, FabricIndex aFabricIx) { - UpdateFabricSceneInfo(aEndpointId, aFabricIx, Optional(), Optional(), Optional(false)); + TEMPORARY_RETURN_IGNORED UpdateFabricSceneInfo(aEndpointId, aFabricIx, Optional(), Optional(), + Optional(false)); } void ScenesServer::MakeSceneInvalidForAllFabrics(EndpointId aEndpointId) { for (auto & info : chip::Server::GetInstance().GetFabricTable()) { - MakeSceneInvalid(aEndpointId, info.GetFabricIndex()); + TEMPORARY_RETURN_IGNORED MakeSceneInvalid(aEndpointId, info.GetFabricIndex()); } } void ScenesServer::StoreCurrentScene(FabricIndex aFabricIx, EndpointId aEndpointId, GroupId aGroupId, SceneId aSceneId) { - StoreSceneParse(aFabricIx, aEndpointId, aGroupId, aSceneId, mGroupProvider); + TEMPORARY_RETURN_IGNORED StoreSceneParse(aFabricIx, aEndpointId, aGroupId, aSceneId, mGroupProvider); } void ScenesServer::RecallScene(FabricIndex aFabricIx, EndpointId aEndpointId, GroupId aGroupId, SceneId aSceneId) { Optional> transitionTime; - RecallSceneParse(aFabricIx, aEndpointId, aGroupId, aSceneId, transitionTime, mGroupProvider); + TEMPORARY_RETURN_IGNORED RecallSceneParse(aFabricIx, aEndpointId, aGroupId, aSceneId, transitionTime, mGroupProvider); } bool ScenesServer::IsHandlerRegistered(EndpointId aEndpointId, scenes::SceneHandler * handler) @@ -796,7 +797,7 @@ void ScenesServer::UnregisterSceneHandler(EndpointId aEndpointId, scenes::SceneH void ScenesServer::RemoveFabric(EndpointId aEndpointId, FabricIndex aFabricIndex) { SceneTable * sceneTable = scenes::GetSceneTableImpl(aEndpointId); - sceneTable->RemoveFabric(aFabricIndex); + TEMPORARY_RETURN_IGNORED sceneTable->RemoveFabric(aFabricIndex); mFabricSceneInfo.ClearSceneInfoStruct(aEndpointId, aFabricIndex); } @@ -1147,7 +1148,8 @@ void emberAfScenesManagementClusterServerInitCallback(EndpointId endpoint) for (auto & info : chip::Server::GetInstance().GetFabricTable()) { auto fabric = info.GetFabricIndex(); - UpdateFabricSceneInfo(endpoint, fabric, Optional(), Optional(), Optional()); + TEMPORARY_RETURN_IGNORED UpdateFabricSceneInfo(endpoint, fabric, Optional(), Optional(), + Optional()); } } @@ -1158,7 +1160,7 @@ void MatterScenesManagementClusterServerShutdownCallback(EndpointId endpoint) // Get Scene Table Instance SceneTable * sceneTable = scenes::GetSceneTableImpl(endpoint, endpointTableSize); - sceneTable->RemoveEndpoint(); + TEMPORARY_RETURN_IGNORED sceneTable->RemoveEndpoint(); } void MatterScenesManagementPluginServerInitCallback() diff --git a/src/app/clusters/service-area-server/service-area-server.cpp b/src/app/clusters/service-area-server/service-area-server.cpp index 34c70aad197..37d0c4d7e82 100644 --- a/src/app/clusters/service-area-server/service-area-server.cpp +++ b/src/app/clusters/service-area-server/service-area-server.cpp @@ -56,7 +56,7 @@ Instance::Instance(StorageDelegate * storageDelegate, Delegate * aDelegate, Endp Instance::~Instance() { - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); + TEMPORARY_RETURN_IGNORED CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); AttributeAccessInterfaceRegistry::Instance().Unregister(this); } diff --git a/src/app/clusters/temperature-control-server/temperature-control-server.cpp b/src/app/clusters/temperature-control-server/temperature-control-server.cpp index 7a991041397..c81bb467db1 100644 --- a/src/app/clusters/temperature-control-server/temperature-control-server.cpp +++ b/src/app/clusters/temperature-control-server/temperature-control-server.cpp @@ -78,8 +78,7 @@ CHIP_ERROR TemperatureControlAttrAccess::Read(const ConcreteReadAttributePath & TemperatureControl::SupportedTemperatureLevelsIteratorDelegate * instance = TemperatureControl::GetInstance(); if (instance == nullptr) { - aEncoder.EncodeEmptyList(); - return CHIP_NO_ERROR; + return aEncoder.EncodeEmptyList(); } instance->Reset(aPath.mEndpointId); err = aEncoder.EncodeList([&](const auto & encoder) -> CHIP_ERROR { diff --git a/src/app/clusters/testing/ValidateGlobalAttributes.h b/src/app/clusters/testing/ValidateGlobalAttributes.h index fa382cc73d0..a83f730fe7f 100644 --- a/src/app/clusters/testing/ValidateGlobalAttributes.h +++ b/src/app/clusters/testing/ValidateGlobalAttributes.h @@ -1,3 +1,5 @@ +#pragma once + #include "AttributeTesting.h" #include #include @@ -9,7 +11,7 @@ namespace Testing { // Compare the attributes of the cluster against the expected set. // Will use the first path returned by `GetPaths()` on the cluster. // Dies if `GetPaths()` doesn't return a list with one path. -bool IsAttributesListEqualTo(app::ServerClusterInterface & cluster, Span expected) +inline bool IsAttributesListEqualTo(app::ServerClusterInterface & cluster, Span expected) { VerifyOrDie(cluster.GetPaths().size() == 1); auto path = cluster.GetPaths()[0]; @@ -24,7 +26,8 @@ bool IsAttributesListEqualTo(app::ServerClusterInterface & cluster, Span expected) +inline bool IsAcceptedCommandsListEqualTo(app::ServerClusterInterface & cluster, + Span expected) { VerifyOrDie(cluster.GetPaths().size() == 1); auto path = cluster.GetPaths()[0]; @@ -39,7 +42,7 @@ bool IsAcceptedCommandsListEqualTo(app::ServerClusterInterface & cluster, Span expected) +inline bool IsGeneratedCommandsListEqualTo(app::ServerClusterInterface & cluster, Span expected) { VerifyOrDie(cluster.GetPaths().size() == 1); auto path = cluster.GetPaths()[0]; diff --git a/src/app/clusters/thermostat-server/thermostat-server-atomic.cpp b/src/app/clusters/thermostat-server/thermostat-server-atomic.cpp index 6cb76fee8c6..acacb8317a3 100644 --- a/src/app/clusters/thermostat-server/thermostat-server-atomic.cpp +++ b/src/app/clusters/thermostat-server/thermostat-server-atomic.cpp @@ -45,7 +45,7 @@ extern ThermostatAttrAccess gThermostatAttrAccess; void TimerExpiredCallback(System::Layer * systemLayer, void * callbackContext) { EndpointId endpoint = static_cast(reinterpret_cast(callbackContext)); - gThermostatAttrAccess.ResetAtomicWrite(endpoint); + TEMPORARY_RETURN_IGNORED gThermostatAttrAccess.ResetAtomicWrite(endpoint); } namespace { @@ -58,8 +58,8 @@ namespace { */ void ScheduleTimer(EndpointId endpoint, System::Clock::Milliseconds16 timeout) { - DeviceLayer::SystemLayer().StartTimer(timeout, TimerExpiredCallback, - reinterpret_cast(static_cast(endpoint))); + TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().StartTimer(timeout, TimerExpiredCallback, + reinterpret_cast(static_cast(endpoint))); } /** diff --git a/src/app/clusters/thermostat-server/thermostat-server-suggestions.cpp b/src/app/clusters/thermostat-server/thermostat-server-suggestions.cpp index 62b80cb7910..f9dadff82a7 100644 --- a/src/app/clusters/thermostat-server/thermostat-server-suggestions.cpp +++ b/src/app/clusters/thermostat-server/thermostat-server-suggestions.cpp @@ -192,7 +192,7 @@ bool AddThermostatSuggestion(CommandHandler * commandObj, const ConcreteCommandP MatterReportingAttributeChangeCallback(endpoint, Thermostat::Id, ThermostatSuggestions::Id); // Re-evaluate the current thermostat suggestion. - delegate->ReEvaluateCurrentSuggestion(); + TEMPORARY_RETURN_IGNORED delegate->ReEvaluateCurrentSuggestion(); Commands::AddThermostatSuggestionResponse::Type response; response.uniqueID = uniqueID; @@ -227,8 +227,8 @@ bool RemoveThermostatSuggestion(CommandHandler * commandObj, const ConcreteComma MatterReportingAttributeChangeCallback(endpoint, Thermostat::Id, ThermostatSuggestions::Id); // Remove expired suggestions if any and re-evaluate the current thermostat suggestion. - RemoveExpiredSuggestions(delegate); - delegate->ReEvaluateCurrentSuggestion(); + TEMPORARY_RETURN_IGNORED RemoveExpiredSuggestions(delegate); + TEMPORARY_RETURN_IGNORED delegate->ReEvaluateCurrentSuggestion(); commandObj->AddStatus(commandPath, Status::Success); return true; diff --git a/src/app/clusters/thermostat-server/thermostat-server.cpp b/src/app/clusters/thermostat-server/thermostat-server.cpp index 22b51f0c208..18fde03c060 100644 --- a/src/app/clusters/thermostat-server/thermostat-server.cpp +++ b/src/app/clusters/thermostat-server/thermostat-server.cpp @@ -1411,12 +1411,12 @@ bool emberAfThermostatClusterSetpointRaiseLowerCallback(app::CommandHandler * co void MatterThermostatPluginServerInitCallback() { - Server::GetInstance().GetFabricTable().AddFabricDelegate(&gThermostatAttrAccess); + TEMPORARY_RETURN_IGNORED Server::GetInstance().GetFabricTable().AddFabricDelegate(&gThermostatAttrAccess); AttributeAccessInterfaceRegistry::Instance().Register(&gThermostatAttrAccess); } void MatterThermostatPluginServerShutdownCallback() { - Server::GetInstance().GetFabricTable().RemoveFabricDelegate(&gThermostatAttrAccess); + TEMPORARY_RETURN_IGNORED Server::GetInstance().GetFabricTable().RemoveFabricDelegate(&gThermostatAttrAccess); AttributeAccessInterfaceRegistry::Instance().Unregister(&gThermostatAttrAccess); } diff --git a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp index c0d41625fe6..c672190ece2 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp +++ b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp @@ -71,7 +71,7 @@ Status ServerInstance::HandleGetDatasetRequest(CommandHandlerInterface::HandlerC if (err == CHIP_ERROR_NOT_FOUND) { // The spec mandates that we return an empty dataset, NOT a NotFound status. - dataset.Init(ByteSpan()); + TEMPORARY_RETURN_IGNORED dataset.Init(ByteSpan()); return Status::Success; } return StatusIB(err).mStatus; @@ -344,7 +344,7 @@ void ServerInstance::OnFailSafeTimerExpired() { if (mDelegate) { - mDelegate->RevertActiveDataset(); + TEMPORARY_RETURN_IGNORED mDelegate->RevertActiveDataset(); } auto commandHandleRef = std::move(mAsyncCommandHandle); auto commandHandle = commandHandleRef.Get(); @@ -364,7 +364,7 @@ void ServerInstance::OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * } else if (event->Type == DeviceLayer::DeviceEventType::kCommissioningComplete) { - _this->mDelegate->CommitActiveDataset(); + TEMPORARY_RETURN_IGNORED _this->mDelegate->CommitActiveDataset(); } } diff --git a/src/app/clusters/thread-network-directory-server/DefaultThreadNetworkDirectoryStorage.cpp b/src/app/clusters/thread-network-directory-server/DefaultThreadNetworkDirectoryStorage.cpp index c272e0acdd7..8794dc471f8 100644 --- a/src/app/clusters/thread-network-directory-server/DefaultThreadNetworkDirectoryStorage.cpp +++ b/src/app/clusters/thread-network-directory-server/DefaultThreadNetworkDirectoryStorage.cpp @@ -104,7 +104,8 @@ CHIP_ERROR DefaultThreadNetworkDirectoryStorage::AddOrUpdateNetwork(const Extend if (err != CHIP_NO_ERROR) { mCount--; - mStorage.SyncDeleteKeyValue(key.KeyName()); + // Return the primary error + RETURN_SAFELY_IGNORED mStorage.SyncDeleteKeyValue(key.KeyName()); return err; } } @@ -137,8 +138,7 @@ CHIP_ERROR DefaultThreadNetworkDirectoryStorage::RemoveNetwork(const ExtendedPan // Delete the dataset itself. Ignore errors since we successfully updated the index. StorageKeyName key = DefaultStorageKeyAllocator::ThreadNetworkDirectoryDataset(exPanId.AsNumber()); - mStorage.SyncDeleteKeyValue(key.KeyName()); - return CHIP_NO_ERROR; + return mStorage.SyncDeleteKeyValue(key.KeyName()); } } // namespace app diff --git a/src/app/clusters/thread-network-directory-server/thread-network-directory-server.cpp b/src/app/clusters/thread-network-directory-server/thread-network-directory-server.cpp index ffb766f630d..39e3ad87789 100644 --- a/src/app/clusters/thread-network-directory-server/thread-network-directory-server.cpp +++ b/src/app/clusters/thread-network-directory-server/thread-network-directory-server.cpp @@ -48,7 +48,7 @@ ThreadNetworkDirectoryServer::ThreadNetworkDirectoryServer(EndpointId endpoint, ThreadNetworkDirectoryServer::~ThreadNetworkDirectoryServer() { AttributeAccessInterfaceRegistry::Instance().Unregister(this); - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); + TEMPORARY_RETURN_IGNORED CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); } CHIP_ERROR ThreadNetworkDirectoryServer::Init() @@ -143,7 +143,7 @@ CHIP_ERROR ThreadNetworkDirectoryServer::ReadThreadNetworks(const ConcreteDataAt char networkName[kSizeNetworkName + 1]; ThreadNetworkStruct::Type network; - dataset.Init(datasetSpan); + TEMPORARY_RETURN_IGNORED dataset.Init(datasetSpan); SuccessOrExit(err = dataset.GetExtendedPanIdAsByteSpan(network.extendedPanID)); SuccessOrExit(err = dataset.GetNetworkName(networkName)); network.networkName = CharSpan::fromCharString(networkName); diff --git a/src/app/clusters/time-synchronization-server/TimeSyncDataProvider.cpp b/src/app/clusters/time-synchronization-server/TimeSyncDataProvider.cpp index 93021a0fae6..86a11b5de9e 100644 --- a/src/app/clusters/time-synchronization-server/TimeSyncDataProvider.cpp +++ b/src/app/clusters/time-synchronization-server/TimeSyncDataProvider.cpp @@ -122,7 +122,7 @@ CHIP_ERROR TimeSyncDataProvider::LoadTimeZone(TimeZoneObj & timeZoneObj) reader.Init(bufferSpan); ReturnErrorOnFailure(reader.Next(TLV::TLVType::kTLVType_Array, TLV::AnonymousTag())); ReturnErrorOnFailure(reader.EnterContainer(outerType)); - reader.CountRemainingInContainer(&count); + TEMPORARY_RETURN_IGNORED reader.CountRemainingInContainer(&count); VerifyOrReturnError(count <= tzStoreList.size(), CHIP_ERROR_BUFFER_TOO_SMALL); while ((err = reader.Next()) == CHIP_NO_ERROR) @@ -195,7 +195,7 @@ CHIP_ERROR TimeSyncDataProvider::LoadDSTOffset(DSTOffsetObj & dstOffsetObj) reader.Init(bufferSpan); ReturnErrorOnFailure(reader.Next(TLV::TLVType::kTLVType_Array, TLV::AnonymousTag())); ReturnErrorOnFailure(reader.EnterContainer(outerType)); - reader.CountRemainingInContainer(&count); + TEMPORARY_RETURN_IGNORED reader.CountRemainingInContainer(&count); VerifyOrReturnError(count <= dstOffsetObj.dstOffsetList.size(), CHIP_ERROR_BUFFER_TOO_SMALL); auto dst = dstOffsetObj.dstOffsetList.begin(); diff --git a/src/app/clusters/time-synchronization-server/time-synchronization-cluster.cpp b/src/app/clusters/time-synchronization-server/time-synchronization-cluster.cpp index 883e45e540a..5b640f9329c 100644 --- a/src/app/clusters/time-synchronization-server/time-synchronization-cluster.cpp +++ b/src/app/clusters/time-synchronization-server/time-synchronization-cluster.cpp @@ -449,11 +449,11 @@ void TimeSynchronizationServer::Init() } if (LoadTimeZone() != CHIP_NO_ERROR) { - ClearTimeZone(); + TEMPORARY_RETURN_IGNORED ClearTimeZone(); } if (LoadDSTOffset() != CHIP_NO_ERROR) { - ClearDSTOffset(); + TEMPORARY_RETURN_IGNORED ClearDSTOffset(); } // Set the granularity to none for now - this will force us to go to the delegate so it can @@ -467,7 +467,7 @@ void TimeSynchronizationServer::Init() { ChipLogError(Zcl, "Unable to register Fabric table delegate for time sync"); } - PlatformMgr().AddEventHandler(OnPlatformEventWrapper, reinterpret_cast(this)); + TEMPORARY_RETURN_IGNORED PlatformMgr().AddEventHandler(OnPlatformEventWrapper, reinterpret_cast(this)); } void TimeSynchronizationServer::Shutdown() @@ -941,7 +941,7 @@ void TimeSynchronizationServer::OnFabricRemoved(const FabricTable & fabricTable, if (!mTrustedTimeSource.IsNull() && mTrustedTimeSource.Value().fabricIndex == fabricIndex) { DataModel::Nullable tts; - TimeSynchronizationServer::Instance().SetTrustedTimeSource(tts); + TEMPORARY_RETURN_IGNORED TimeSynchronizationServer::Instance().SetTrustedTimeSource(tts); emitMissingTrustedTimeSourceEvent(0); } } @@ -1115,7 +1115,7 @@ bool emberAfTimeSynchronizationClusterSetUTCTimeCallback( } else { - commandObj->AddClusterSpecificFailure(commandPath, to_underlying(StatusCode::kTimeNotAccepted)); + TEMPORARY_RETURN_IGNORED commandObj->AddClusterSpecificFailure(commandPath, to_underlying(StatusCode::kTimeNotAccepted)); } return true; } @@ -1142,7 +1142,7 @@ bool emberAfTimeSynchronizationClusterSetTrustedTimeSourceCallback( emitMissingTrustedTimeSourceEvent(commandPath.mEndpointId); } - TimeSynchronizationServer::Instance().SetTrustedTimeSource(tts); + TEMPORARY_RETURN_IGNORED TimeSynchronizationServer::Instance().SetTrustedTimeSource(tts); commandObj->AddStatus(commandPath, Status::Success); return true; } @@ -1204,7 +1204,7 @@ bool emberAfTimeSynchronizationClusterSetTimeZoneCallback( if (response.DSTOffsetRequired) { TimeState dstState = TimeSynchronizationServer::Instance().UpdateDSTOffsetState(); - TimeSynchronizationServer::Instance().ClearDSTOffset(); + TEMPORARY_RETURN_IGNORED TimeSynchronizationServer::Instance().ClearDSTOffset(); if (dstState == TimeState::kActive || dstState == TimeState::kChanged) { emitDSTStatusEvent(commandPath.mEndpointId, false); diff --git a/src/app/clusters/tls-certificate-management-server/BUILD.gn b/src/app/clusters/tls-certificate-management-server/BUILD.gn index 557af70647f..8e70215856d 100644 --- a/src/app/clusters/tls-certificate-management-server/BUILD.gn +++ b/src/app/clusters/tls-certificate-management-server/BUILD.gn @@ -28,15 +28,17 @@ source_set("certificate-table") { } source_set("tls-certificate-management-server") { - public = [ "tls-certificate-management-server.h" ] + sources = [ + "TLSCertificateManagementCluster.cpp", + "TLSCertificateManagementCluster.h", + ] deps = [ ":certificate-table", "${chip_root}/src/app:attribute-persistence", "${chip_root}/src/app/server", + "${chip_root}/src/app/server-cluster:server-cluster", "${chip_root}/zzz_generated/app-common/clusters:all-headers", "${chip_root}/zzz_generated/app-common/clusters:all-metadata", ] - - sources = [ "tls-certificate-management-server.cpp" ] } diff --git a/src/app/clusters/tls-certificate-management-server/CertificateTable.h b/src/app/clusters/tls-certificate-management-server/CertificateTable.h index 4c64760e5d6..a13cf8d5204 100644 --- a/src/app/clusters/tls-certificate-management-server/CertificateTable.h +++ b/src/app/clusters/tls-certificate-management-server/CertificateTable.h @@ -52,12 +52,11 @@ class CertificateTable using IterateRootCertFnType = std::function & iterator)>; using IterateClientCertFnType = std::function & iterator)>; - using RootBuffer = PersistentStore; - using ClientBuffer = PersistentStore; + using RootBuffer = PersistenceBuffer; + using ClientBuffer = PersistenceBuffer; /// @brief a root cert along with an associated buffer for the cert payload. RootCertStruct has a ByteSpan, /// and this wrapper ensures that the underlying buffer for the ByteSpan has a long-enough lifetime. - /// No other functionality from PersistentStore<> is required to be used by the implementation except the underlying buffer. struct BufferedRootCert { BufferedRootCert(RootBuffer & buffer) : mBuffer(buffer) {} @@ -74,7 +73,6 @@ class CertificateTable /// @brief a client cert along with an associated buffer for the cert payload. ClientCertStruct contains various /// lists and bytespans, and this wrapper ensures that the underlying buffers for those data structures /// have long-enough lifetimes. - /// No other functionality from PersistentStore<> is required to be used by the implementation except the underlying buffer. struct BufferedClientCert { BufferedClientCert(ClientBuffer & buffer) : mBuffer(buffer) {} @@ -188,11 +186,11 @@ class CertificateTable virtual CHIP_ERROR RemoveFabric(FabricIndex fabric) = 0; protected: - static inline PersistentStore & GetBuffer(BufferedRootCert & bufferedCert) + static inline PersistenceBuffer & GetBuffer(BufferedRootCert & bufferedCert) { return bufferedCert.mBuffer; } - static inline PersistentStore & GetBuffer(BufferedClientCert & bufferedCert) + static inline PersistenceBuffer & GetBuffer(BufferedClientCert & bufferedCert) { return bufferedCert.mBuffer; } diff --git a/src/app/clusters/tls-certificate-management-server/CertificateTableImpl.cpp b/src/app/clusters/tls-certificate-management-server/CertificateTableImpl.cpp index 4f722fdec9d..4b91842e855 100644 --- a/src/app/clusters/tls-certificate-management-server/CertificateTableImpl.cpp +++ b/src/app/clusters/tls-certificate-management-server/CertificateTableImpl.cpp @@ -72,7 +72,7 @@ static constexpr size_t kPersistentBufferNextIdBytes = EstimateStructOverhead(sizeof(CertificateId), sizeof(FabricIndex)) * (kMaxClientCertificatesPerFabric * CHIP_CONFIG_MAX_FABRICS)); // mClientCertMapping -class GlobalCertificateData : public PersistentData +class GlobalCertificateData : public PersistableData { IncrementingIdHelper mRoot; IncrementingIdHelper mClient; @@ -156,16 +156,10 @@ class GlobalCertificateData : public PersistentData +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::Tls; +using namespace chip::app::DataModel; + +namespace { + +CertificateTableImpl gDefaultCertificateTable; + +TLSCertificateManagementDelegate * gDelegate = nullptr; +CertificateDependencyChecker * gDependencyChecker = nullptr; +CertificateTableImpl * gCertificateTable = &gDefaultCertificateTable; + +LazyRegisteredServerCluster gClusterInstance; + +} // anonymous namespace + +namespace chip { +namespace app { +namespace Clusters { + +void MatterTlsCertificateManagementSetDelegate(TLSCertificateManagementDelegate & delegate) +{ + gDelegate = &delegate; +} + +void MatterTlsCertificateManagementSetCertificateTable(Tls::CertificateTableImpl & certificateTable) +{ + gCertificateTable = &certificateTable; +} + +void MatterTlsCertificateManagementSetDependencyChecker(Tls::CertificateDependencyChecker & dependencyChecker) +{ + gDependencyChecker = &dependencyChecker; +} + +} // namespace Clusters +} // namespace app +} // namespace chip + +void MatterTlsCertificateManagementPluginServerInitCallback() +{ + ChipLogProgress(Zcl, "Initializing TLS Certificate Management cluster."); +} + +void MatterTlsCertificateManagementClusterInitCallback(EndpointId endpointId) +{ + // TODO:(#42638) This cluster SHALL be present on the root node endpoint (endpoint 0) when required, and SHALL NOT be present on + // any other endpoint. if (endpointId != kRootEndpointId) + // { + // ChipLogError(Zcl, + // "TLS Certificate Management Cluster can only be initialized on root endpoint (0). " + // "Ignoring initialization on endpoint %u.", + // endpointId); + // return; + // } + + // Only create once - avoid double initialization if callback is called multiple times + if (gClusterInstance.IsConstructed()) + { + ChipLogError(Zcl, "TLS Certificate Management Cluster already initialized. Ignoring duplicate initialization."); + return; + } + + // Require a proper delegate - the cluster cannot function without one + if (gDelegate == nullptr) + { + ChipLogError(Zcl, + "TLS Certificate Management Cluster cannot be initialized without a delegate. " + "Call MatterTlsCertificateManagementSetDelegate() before ServerInit()."); + return; + } + + if (gDependencyChecker == nullptr) + { + ChipLogError(Zcl, + "TLS Certificate Management Cluster cannot be initialized without a dependency checker. " + "Call MatterTlsCertificateManagementSetDependencyChecker() before ServerInit()."); + return; + } + + LogErrorOnFailure(gCertificateTable->SetEndpoint(endpointId)); + + gClusterInstance.Create(endpointId, *gDelegate, *gDependencyChecker, *gCertificateTable, + static_cast(kMaxRootCertificatesPerFabric), + static_cast(kMaxClientCertificatesPerFabric)); + CHIP_ERROR err = CodegenDataModelProvider::Instance().Registry().Register(gClusterInstance.Registration()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to register TLS Certificate Management Cluster on endpoint %u: %" CHIP_ERROR_FORMAT, endpointId, + err.Format()); + } +} + +void MatterTlsCertificateManagementClusterShutdownCallback(EndpointId endpointId) +{ + VerifyOrReturn(gClusterInstance.IsConstructed()); + VerifyOrReturn(gClusterInstance.Cluster().GetEndpointId() == endpointId); + + LogErrorOnFailure(CodegenDataModelProvider::Instance().Registry().Unregister(&gClusterInstance.Cluster())); + gClusterInstance.Destroy(); +} diff --git a/src/app/clusters/tls-certificate-management-server/CodegenIntegration.h b/src/app/clusters/tls-certificate-management-server/CodegenIntegration.h new file mode 100644 index 00000000000..d9a7d69331a --- /dev/null +++ b/src/app/clusters/tls-certificate-management-server/CodegenIntegration.h @@ -0,0 +1,71 @@ +/* + * + * Copyright (c) 2025 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 + +namespace chip { +namespace app { +namespace Clusters { + +/** + * Set the delegate for the TLS Certificate Management cluster. + * + * MUST be called before Matter data model initialization (e.g. in main() before ServerInit()). + * The delegate is used during cluster initialization. + * If called after cluster initialization, it will have no effect as the cluster instance + * has already been created with the previous delegate. + * + * If not called before initialization, the cluster will NOT be initialized. + * + * @param delegate The delegate to be used by the TLS Certificate Management cluster. + */ +void MatterTlsCertificateManagementSetDelegate(TLSCertificateManagementDelegate & delegate); + +/** + * Set the certificate table for the TLS Certificate Management cluster. + * + * MUST be called before Matter data model initialization (e.g. in main() before ServerInit()). + * The certificate table is used during cluster initialization via emberAfTLSCertificateManagementClusterInitCallback. + * If called after cluster initialization, it will have no effect as the cluster instance + * has already been created with the previous certificate table. + * + * If not called before initialization, a default certificate table will be used. + * + * @param certificateTable The certificate table to be used by the TLS Certificate Management cluster. + */ +void MatterTlsCertificateManagementSetCertificateTable(Tls::CertificateTableImpl & certificateTable); + +/** + * Set the dependency checker for the TLS Certificate Management cluster. + * + * MUST be called before Matter data model initialization (e.g. in main() before ServerInit()). + * The dependency checker is used during cluster initialization via emberAfTLSCertificateManagementClusterInitCallback. + * If called after cluster initialization, it will have no effect as the cluster instance + * has already been created with the previous dependency checker. + * + * If not called before initialization, a default dependency checker will be used. + * + * @param dependencyChecker The dependency checker to be used by the TLS Certificate Management cluster. + */ +void MatterTlsCertificateManagementSetDependencyChecker(Tls::CertificateDependencyChecker & dependencyChecker); + +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/tls-certificate-management-server/TLSCertificateManagementCluster.cpp b/src/app/clusters/tls-certificate-management-server/TLSCertificateManagementCluster.cpp new file mode 100644 index 00000000000..8c04bfcef83 --- /dev/null +++ b/src/app/clusters/tls-certificate-management-server/TLSCertificateManagementCluster.cpp @@ -0,0 +1,576 @@ +/* + * + * Copyright (c) 2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/****************************************************************************' + * @file + * @brief Implementation for the TlsCertificateManagement Server Cluster + ***************************************************************************/ + +#include "TLSCertificateManagementCluster.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::Tls; +using namespace chip::app::Clusters::TlsCertificateManagement; +using namespace chip::app::Clusters::TlsCertificateManagement::Commands; +using namespace chip::app::Clusters::TlsCertificateManagement::Structs; +using namespace chip::app::Clusters::TlsCertificateManagement::Attributes; +using chip::Protocols::InteractionModel::Status; + +static constexpr uint16_t kSpecMaxCertBytes = 3000; +static constexpr uint16_t kSpecMaxFingerprintBytes = 64; +static constexpr uint16_t kMaxIntermediateCertificates = 10; +static constexpr uint16_t kNonceBytes = 32; +static constexpr uint16_t kMaxSignatureBytes = 128; + +constexpr DataModel::AcceptedCommandEntry kAcceptedCommands[] = { + Commands::ProvisionRootCertificate::kMetadataEntry, + Commands::FindRootCertificate::kMetadataEntry, + Commands::LookupRootCertificate::kMetadataEntry, + Commands::RemoveRootCertificate::kMetadataEntry, + Commands::ClientCSR::kMetadataEntry, + Commands::ProvisionClientCertificate::kMetadataEntry, + Commands::FindClientCertificate::kMetadataEntry, + Commands::LookupClientCertificate::kMetadataEntry, + Commands::RemoveClientCertificate::kMetadataEntry, +}; + +TLSCertificateManagementCluster::TLSCertificateManagementCluster(EndpointId endpointId, TLSCertificateManagementDelegate & delegate, + Tls::CertificateDependencyChecker & dependencyChecker, + CertificateTable & certificateTable, uint8_t maxRootCertificates, + uint8_t maxClientCertificates) : + DefaultServerCluster(ConcreteClusterPath(endpointId, TlsCertificateManagement::Id)), + mDelegate(delegate), mDependencyChecker(dependencyChecker), mCertificateTable(certificateTable), + mMaxRootCertificates(maxRootCertificates), mMaxClientCertificates(maxClientCertificates) +{ + VerifyOrDieWithMsg(mMaxRootCertificates >= 5, NotSpecified, "Spec requires MaxRootCertificates be >= 5"); + VerifyOrDieWithMsg(mMaxClientCertificates >= 5, NotSpecified, "Spec requires MaxClientCertificates be >= 5"); + mDelegate.SetTLSCertificateManagementCluster(this); +} + +TLSCertificateManagementCluster::~TLSCertificateManagementCluster() +{ + // null out the ref to us on the delegate + mDelegate.SetTLSCertificateManagementCluster(nullptr); + + mCertificateTable.Finish(); + TEMPORARY_RETURN_IGNORED Server::GetInstance().GetFabricTable().RemoveFabricDelegate(this); +} + +CHIP_ERROR TLSCertificateManagementCluster::Startup(ServerClusterContext & context) +{ + ChipLogProgress(DataManagement, "TLSCertificateManagementCluster: initializing"); + ReturnErrorOnFailure(DefaultServerCluster::Startup(context)); + + ReturnErrorOnFailure(mCertificateTable.Init(context.storage)); + + return Server::GetInstance().GetFabricTable().AddFabricDelegate(this); +} + +void TLSCertificateManagementCluster::Shutdown() +{ + ChipLogProgress(DataManagement, "TLSCertificateManagementCluster: shutdown"); + + DefaultServerCluster::Shutdown(); +} + +// DefaultServerCluster override +DataModel::ActionReturnStatus TLSCertificateManagementCluster::ReadAttribute(const DataModel::ReadAttributeRequest & request, + AttributeValueEncoder & encoder) +{ + TLSCertificateManagementCluster * server = this; + auto matterEndpoint = request.path.mEndpointId; + auto fabric = request.GetAccessingFabricIndex(); + bool largePayload = request.readFlags.Has(DataModel::ReadFlags::kAllowsLargePayload); + + switch (request.path.mAttributeId) + { + case MaxRootCertificates::Id: + return encoder.Encode(mMaxRootCertificates); + case ProvisionedRootCertificates::Id: { + return encoder.EncodeList([server, matterEndpoint, fabric, largePayload](const auto & listEncoder) -> CHIP_ERROR { + return server->EncodeProvisionedRootCertificates(matterEndpoint, fabric, largePayload, listEncoder); + }); + } + case MaxClientCertificates::Id: + return encoder.Encode(mMaxClientCertificates); + case ProvisionedClientCertificates::Id: { + return encoder.EncodeList([server, matterEndpoint, fabric, largePayload](const auto & listEncoder) -> CHIP_ERROR { + return server->EncodeProvisionedClientCertificates(matterEndpoint, fabric, largePayload, listEncoder); + }); + } + case ClusterRevision::Id: + return encoder.Encode(kRevision); + case FeatureMap::Id: + return encoder.Encode(0); + default: + return Status::UnsupportedAttribute; + } +} + +CHIP_ERROR +TLSCertificateManagementCluster::EncodeProvisionedRootCertificates(EndpointId matterEndpoint, FabricIndex fabric, bool largePayload, + const AttributeValueEncoder::ListEncodeHelper & encoder) +{ + return mDelegate.LoadedRootCerts(matterEndpoint, fabric, [&](auto & cert) -> CHIP_ERROR { + if (largePayload) + { + return encoder.Encode(cert); + } + + // Drop the certificate payload if transport doesn't support large payload + TLSCertStruct::Type idOnlyCert; + idOnlyCert.fabricIndex = cert.fabricIndex; + idOnlyCert.caid = cert.caid; + return encoder.Encode(idOnlyCert); + }); +} + +CHIP_ERROR +TLSCertificateManagementCluster::EncodeProvisionedClientCertificates(EndpointId matterEndpoint, FabricIndex fabric, + bool largePayload, + const AttributeValueEncoder::ListEncodeHelper & encoder) +{ + return mDelegate.LoadedClientCerts(matterEndpoint, fabric, [&](auto & cert) -> CHIP_ERROR { + if (largePayload) + { + return encoder.Encode(cert); + } + + // Drop the certificate payload if transport doesn't support large payload + TLSClientCertificateDetailStruct::Type idOnlyCert; + idOnlyCert.fabricIndex = cert.fabricIndex; + idOnlyCert.ccdid = cert.ccdid; + return encoder.Encode(idOnlyCert); + }); +} + +std::optional +TLSCertificateManagementCluster::InvokeCommand(const DataModel::InvokeRequest & request, TLV::TLVReader & input_arguments, + CommandHandler * handler) +{ + FabricIndex accessingFabricIndex = handler->GetAccessingFabricIndex(); + + switch (request.path.mCommandId) + { + case ProvisionRootCertificate::Id: { + ProvisionRootCertificate::DecodableType req; + ReturnErrorOnFailure(req.Decode(input_arguments, accessingFabricIndex)); + return HandleProvisionRootCertificate(*handler, req); + } + case FindRootCertificate::Id: { + FindRootCertificate::DecodableType req; + ReturnErrorOnFailure(req.Decode(input_arguments, accessingFabricIndex)); + return HandleFindRootCertificate(*handler, req); + } + case LookupRootCertificate::Id: { + LookupRootCertificate::DecodableType req; + ReturnErrorOnFailure(req.Decode(input_arguments, accessingFabricIndex)); + return HandleLookupRootCertificate(*handler, req); + } + case RemoveRootCertificate::Id: { + RemoveRootCertificate::DecodableType req; + ReturnErrorOnFailure(req.Decode(input_arguments, accessingFabricIndex)); + return HandleRemoveRootCertificate(*handler, req); + } + case ClientCSR::Id: { + ClientCSR::DecodableType req; + ReturnErrorOnFailure(req.Decode(input_arguments, accessingFabricIndex)); + return HandleGenerateClientCsr(*handler, req); + } + case ProvisionClientCertificate::Id: { + ProvisionClientCertificate::DecodableType req; + ReturnErrorOnFailure(req.Decode(input_arguments, accessingFabricIndex)); + return HandleProvisionClientCertificate(*handler, req); + } + case FindClientCertificate::Id: { + FindClientCertificate::DecodableType req; + ReturnErrorOnFailure(req.Decode(input_arguments, accessingFabricIndex)); + return HandleFindClientCertificate(*handler, req); + } + case LookupClientCertificate::Id: { + LookupClientCertificate::DecodableType req; + ReturnErrorOnFailure(req.Decode(input_arguments, accessingFabricIndex)); + return HandleLookupClientCertificate(*handler, req); + } + case RemoveClientCertificate::Id: { + RemoveClientCertificate::DecodableType req; + ReturnErrorOnFailure(req.Decode(input_arguments, accessingFabricIndex)); + return HandleRemoveClientCertificate(*handler, req); + } + default: + return Status::UnsupportedCommand; + } +} + +std::optional +TLSCertificateManagementCluster::HandleProvisionRootCertificate(CommandHandler & commandHandler, + const ProvisionRootCertificate::DecodableType & req) +{ + ChipLogDetail(Zcl, "TlsCertificateManagement: ProvisionRootCertificate"); + + VerifyOrReturnError(req.certificate.size() <= kSpecMaxCertBytes, Status::ConstraintError); + + auto fabric = commandHandler.GetAccessingFabricIndex(); + DataModel::Nullable foundId; + auto lookupResult = mDelegate.LookupRootCert(mPath.mEndpointId, fabric, req.certificate, [&](auto & certificate) -> CHIP_ERROR { + foundId = certificate.caid; + return CHIP_NO_ERROR; + }); + + VerifyOrReturnError(lookupResult == CHIP_ERROR_NOT_FOUND, Status::AlreadyExists); + + if (req.caid.IsNull()) + { + uint8_t numRootCerts; + VerifyOrReturnError(mCertificateTable.GetRootCertificateCount(fabric, numRootCerts) == CHIP_NO_ERROR, Status::Failure); + VerifyOrReturnError(numRootCerts < mMaxRootCertificates, Status::ResourceExhausted); + } + else + { + auto caid = req.caid.Value(); + VerifyOrReturnError(caid <= kMaxRootCertId, Status::ConstraintError); + VerifyOrReturnError(mCertificateTable.HasRootCertificateEntry(fabric, caid) == CHIP_NO_ERROR, Status::NotFound); + } + +#if CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_TIME + if (Crypto::IsCertificateValidAtCurrentTime(req.certificate) != CHIP_NO_ERROR) + { + return Status::DynamicConstraintError; + } +#endif + + ProvisionRootCertificateResponse::Type response; + auto status = mDelegate.ProvisionRootCert(mPath.mEndpointId, fabric, req, response.caid); + if (status != Status::Success) + { + return status; + } + + VerifyOrDieWithMsg(response.caid <= kMaxRootCertId, NotSpecified, "Spec requires CAID to be <= kMaxRootCertId"); + + ConcreteCommandPath responsePath(mPath.mEndpointId, TlsCertificateManagement::Id, Commands::ProvisionRootCertificate::Id); + commandHandler.AddResponse(responsePath, response); + + NotifyAttributeChanged(TlsCertificateManagement::Attributes::ProvisionedRootCertificates::Id); + + return std::nullopt; +} + +std::optional +TLSCertificateManagementCluster::HandleFindRootCertificate(CommandHandler & commandHandler, + const FindRootCertificate::DecodableType & req) +{ + ChipLogDetail(Zcl, "TlsCertificateManagement: FindRootCertificate"); + CHIP_ERROR result; + if (req.caid.IsNull()) + { + result = mDelegate.RootCertsForFabric(mPath.mEndpointId, commandHandler.GetAccessingFabricIndex(), + [&](auto & certs) -> CHIP_ERROR { + if (certs.size() == 0) + { + return CHIP_ERROR_NOT_FOUND; + } + FindRootCertificateResponse::Type response; + response.certificateDetails = certs; + ConcreteCommandPath responsePath(mPath.mEndpointId, TlsCertificateManagement::Id, + Commands::FindRootCertificate::Id); + commandHandler.AddResponse(responsePath, response); + return CHIP_NO_ERROR; + }); + } + else + { + VerifyOrReturnError(req.caid.Value() <= kMaxRootCertId, Status::ConstraintError); + + result = mDelegate.FindRootCert(mPath.mEndpointId, commandHandler.GetAccessingFabricIndex(), req.caid.Value(), + [&](auto & certificate) -> CHIP_ERROR { + FindRootCertificateResponse::Type response; + DataModel::List details(&certificate, 1); + response.certificateDetails = details; + ConcreteCommandPath responsePath(mPath.mEndpointId, TlsCertificateManagement::Id, + Commands::FindRootCertificate::Id); + commandHandler.AddResponse(responsePath, response); + return CHIP_NO_ERROR; + }); + } + + if (result == CHIP_ERROR_NOT_FOUND) + { + return Status::NotFound; + } + + VerifyOrReturnError(result == CHIP_NO_ERROR, Status::Failure); + return std::nullopt; +} + +std::optional +TLSCertificateManagementCluster::HandleLookupRootCertificate(CommandHandler & commandHandler, + const LookupRootCertificate::DecodableType & req) +{ + ChipLogDetail(Zcl, "TlsCertificateManagement: LookupRootCertificate"); + + VerifyOrReturnError(req.fingerprint.size() <= kSpecMaxFingerprintBytes, Status::ConstraintError); + + auto result = mDelegate.LookupRootCertByFingerprint( + mPath.mEndpointId, commandHandler.GetAccessingFabricIndex(), req.fingerprint, [&](auto & certificate) -> CHIP_ERROR { + LookupRootCertificateResponse::Type response; + response.caid = certificate.caid; + ConcreteCommandPath responsePath(mPath.mEndpointId, TlsCertificateManagement::Id, Commands::LookupRootCertificate::Id); + commandHandler.AddResponse(responsePath, response); + return CHIP_NO_ERROR; + }); + + if (result == CHIP_ERROR_NOT_FOUND) + { + return Status::NotFound; + } + + VerifyOrReturnError(result == CHIP_NO_ERROR, Status::Failure); + return std::nullopt; +} + +std::optional +TLSCertificateManagementCluster::HandleRemoveRootCertificate(CommandHandler & commandHandler, + const RemoveRootCertificate::DecodableType & req) +{ + ChipLogDetail(Zcl, "TlsCertificateManagement: RemoveRootCertificate"); + + VerifyOrReturnError(req.caid <= kMaxRootCertId, Status::ConstraintError); + VerifyOrReturnError(mDependencyChecker.RootCertCanBeRemoved(mPath.mEndpointId, commandHandler.GetAccessingFabricIndex(), + req.caid) == CHIP_NO_ERROR, + Status::InvalidInState); + + auto status = mDelegate.RemoveRootCert(mPath.mEndpointId, commandHandler.GetAccessingFabricIndex(), req.caid); + + if (status == Status::Success) + { + NotifyAttributeChanged(TlsCertificateManagement::Attributes::ProvisionedRootCertificates::Id); + } + + return status; +} + +std::optional +TLSCertificateManagementCluster::HandleGenerateClientCsr(CommandHandler & commandHandler, const ClientCSR::DecodableType & req) +{ + ChipLogDetail(Zcl, "TlsCertificateManagement: ClientCSR"); + + VerifyOrReturnError(req.nonce.size() == kNonceBytes, Status::ConstraintError); + + auto fabric = commandHandler.GetAccessingFabricIndex(); + + // If no CCDID is specified, ensure we have capacity for a new client certificate. + if (req.ccdid.IsNull()) + { + uint8_t numClientCerts; + VerifyOrReturnError(mCertificateTable.GetClientCertificateCount(fabric, numClientCerts) == CHIP_NO_ERROR, Status::Failure); + VerifyOrReturnError(numClientCerts < mMaxClientCertificates, Status::ResourceExhausted); + } + + auto status = mDelegate.GenerateClientCsr(mPath.mEndpointId, fabric, req, [&](auto & response) -> Status { + VerifyOrDieWithMsg(response.ccdid <= kMaxClientCertId, NotSpecified, "Spec requires CCDID to be <= kMaxClientCertId"); + VerifyOrDieWithMsg(response.csr.size() <= 3000, NotSpecified, "Spec requires csr.size() to be <= 3000"); + VerifyOrDieWithMsg(response.nonceSignature.size() <= kMaxSignatureBytes, NotSpecified, + "Spec requires nonceSignature.size() to be < kMaxSignatureBytes"); + ConcreteCommandPath responsePath(mPath.mEndpointId, TlsCertificateManagement::Id, Commands::ClientCSR::Id); + commandHandler.AddResponse(responsePath, response); + return Status::Success; + }); + + if (status == Status::Success) + { + return std::nullopt; + } + + return status; +} + +std::optional +TLSCertificateManagementCluster::HandleProvisionClientCertificate(CommandHandler & commandHandler, + const ProvisionClientCertificate::DecodableType & req) +{ + ChipLogDetail(Zcl, "TlsCertificateManagement: ProvisionClientCertificate"); + + VerifyOrReturnError(req.ccdid <= kMaxClientCertId, Status::ConstraintError); + VerifyOrReturnError(req.clientCertificate.size() <= kSpecMaxCertBytes, Status::ConstraintError); + +#if CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_TIME + if (Crypto::IsCertificateValidAtCurrentTime(req.clientCertificate) != CHIP_NO_ERROR) + { + return Status::DynamicConstraintError; + } +#endif + + size_t intermediateSize; + VerifyOrReturnError(req.intermediateCertificates.ComputeSize(&intermediateSize) == CHIP_NO_ERROR, Status::InvalidCommand); + VerifyOrReturnError(intermediateSize <= kMaxIntermediateCertificates, Status::ConstraintError); + + auto srcIter = req.intermediateCertificates.begin(); + while (srcIter.Next()) + { + auto & cert = srcIter.GetValue(); + VerifyOrReturnError(cert.size() <= kSpecMaxCertBytes, Status::ConstraintError); + VerifyOrReturnError(Crypto::IsCertificateValidAtCurrentTime(cert) == CHIP_NO_ERROR, Status::DynamicConstraintError); + } + VerifyOrReturnError(srcIter.GetStatus() == CHIP_NO_ERROR, Status::InvalidAction); + + auto fabric = commandHandler.GetAccessingFabricIndex(); + DataModel::Nullable foundId; + auto lookupResult = + mDelegate.LookupClientCert(mPath.mEndpointId, fabric, req.clientCertificate, [&](auto & certificate) -> CHIP_ERROR { + foundId = certificate.ccdid; + return CHIP_NO_ERROR; + }); + + VerifyOrReturnError(lookupResult == CHIP_ERROR_NOT_FOUND, Status::AlreadyExists); + VerifyOrReturnError(mCertificateTable.HasClientCertificateEntry(fabric, req.ccdid) == CHIP_NO_ERROR, Status::NotFound); + + auto status = mDelegate.ProvisionClientCert(mPath.mEndpointId, fabric, req); + + if (status == Status::Success) + { + NotifyAttributeChanged(TlsCertificateManagement::Attributes::ProvisionedClientCertificates::Id); + } + + return status; +} + +std::optional +TLSCertificateManagementCluster::HandleFindClientCertificate(CommandHandler & commandHandler, + const FindClientCertificate::DecodableType & req) +{ + ChipLogDetail(Zcl, "TlsCertificateManagement: FindClientCertificate"); + CHIP_ERROR result; + if (req.ccdid.IsNull()) + { + result = mDelegate.ClientCertsForFabric( + mPath.mEndpointId, commandHandler.GetAccessingFabricIndex(), [&](auto & certs) -> CHIP_ERROR { + VerifyOrReturnError(certs.size() > 0, CHIP_ERROR_NOT_FOUND); + FindClientCertificateResponse::Type response; + response.certificateDetails = certs; + ConcreteCommandPath responsePath(mPath.mEndpointId, TlsCertificateManagement::Id, + Commands::FindClientCertificate::Id); + commandHandler.AddResponse(responsePath, response); + return CHIP_NO_ERROR; + }); + } + else + { + VerifyOrReturnError(req.ccdid.Value() <= kMaxClientCertId, Status::ConstraintError); + + result = mDelegate.FindClientCert( + mPath.mEndpointId, commandHandler.GetAccessingFabricIndex(), req.ccdid.Value(), [&](auto & certificate) -> CHIP_ERROR { + FindClientCertificateResponse::Type response; + DataModel::List details(&certificate, 1); + response.certificateDetails = details; + ConcreteCommandPath responsePath(mPath.mEndpointId, TlsCertificateManagement::Id, + Commands::FindClientCertificate::Id); + commandHandler.AddResponse(responsePath, response); + return CHIP_NO_ERROR; + }); + } + + if (result == CHIP_ERROR_NOT_FOUND) + { + return Status::NotFound; + } + + VerifyOrReturnError(result == CHIP_NO_ERROR, Status::Failure); + return std::nullopt; +} + +std::optional +TLSCertificateManagementCluster::HandleLookupClientCertificate(CommandHandler & commandHandler, + const LookupClientCertificate::DecodableType & req) +{ + ChipLogDetail(Zcl, "TlsCertificateManagement: LookupClientCertificate"); + + VerifyOrReturnError(req.fingerprint.size() <= kSpecMaxFingerprintBytes, Status::ConstraintError); + + auto result = mDelegate.LookupClientCertByFingerprint( + mPath.mEndpointId, commandHandler.GetAccessingFabricIndex(), req.fingerprint, [&](auto & certificate) -> CHIP_ERROR { + LookupClientCertificateResponse::Type response; + response.ccdid = certificate.ccdid; + ConcreteCommandPath responsePath(mPath.mEndpointId, TlsCertificateManagement::Id, + Commands::LookupClientCertificate::Id); + commandHandler.AddResponse(responsePath, response); + return CHIP_NO_ERROR; + }); + + if (result == CHIP_ERROR_NOT_FOUND) + { + return Status::NotFound; + } + + VerifyOrReturnError(result == CHIP_NO_ERROR, Status::Failure); + return std::nullopt; +} + +std::optional +TLSCertificateManagementCluster::HandleRemoveClientCertificate(CommandHandler & commandHandler, + const RemoveClientCertificate::DecodableType & req) +{ + ChipLogDetail(Zcl, "TlsCertificateManagement: RemoveClientCertificate"); + + VerifyOrReturnError(req.ccdid <= kMaxClientCertId, Status::ConstraintError); + VerifyOrReturnError(mDependencyChecker.ClientCertCanBeRemoved(mPath.mEndpointId, commandHandler.GetAccessingFabricIndex(), + req.ccdid) == CHIP_NO_ERROR, + Status::InvalidInState); + + auto status = mDelegate.RemoveClientCert(mPath.mEndpointId, commandHandler.GetAccessingFabricIndex(), req.ccdid); + + if (status == Status::Success) + { + NotifyAttributeChanged(TlsCertificateManagement::Attributes::ProvisionedClientCertificates::Id); + } + + return status; +} + +CHIP_ERROR TLSCertificateManagementCluster::AcceptedCommands(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) +{ + return builder.ReferenceExisting(kAcceptedCommands); +} + +CHIP_ERROR TLSCertificateManagementCluster::Attributes(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) +{ + AttributeListBuilder listBuilder(builder); + + // TlsCertificateManagement does not have optional attributes implemented yet, + // so we just return mandatory ones. + return listBuilder.Append(Span(kMandatoryMetadata), {}); +} + +void TLSCertificateManagementCluster::OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) +{ + ReturnAndLogOnFailure(mCertificateTable.RemoveFabric(fabricIndex), Zcl, "Failed to remove TLS certificate data for fabric 0x%x", + fabricIndex); +} diff --git a/src/app/clusters/tls-certificate-management-server/tls-certificate-management-server.h b/src/app/clusters/tls-certificate-management-server/TLSCertificateManagementCluster.h similarity index 77% rename from src/app/clusters/tls-certificate-management-server/tls-certificate-management-server.h rename to src/app/clusters/tls-certificate-management-server/TLSCertificateManagementCluster.h index f460965a18e..69c8fa05ce0 100644 --- a/src/app/clusters/tls-certificate-management-server/tls-certificate-management-server.h +++ b/src/app/clusters/tls-certificate-management-server/TLSCertificateManagementCluster.h @@ -19,11 +19,11 @@ #pragma once #include "CertificateTable.h" -#include -#include #include #include +#include #include +#include #include #include #include @@ -32,16 +32,13 @@ namespace chip { namespace app { namespace Clusters { -class TlsCertificateManagementDelegate; +class TLSCertificateManagementDelegate; -class TlsCertificateManagementServer : private AttributeAccessInterface, - private CommandHandlerInterface, - private FabricTable::Delegate +class TLSCertificateManagementCluster : public DefaultServerCluster, private FabricTable::Delegate { public: /** - * Creates a TlsCertificateManagement server instance. The Init() function needs to be called for this instance to be registered - * and called by the interaction model at the appropriate times. + * Creates a TlsCertificateManagement server instance. * @param endpointId The endpoint on which this cluster exists. This must match the zap configuration. * @param delegate A reference to the delegate to be used by this server. * @param dependencyChecker A reference to a CertificateDependencyChecker which checks for transitive dependencies @@ -50,22 +47,10 @@ class TlsCertificateManagementServer : private AttributeAccessInterface, * @param maxClientCertificates The maximum number of client certificates which can be provisioned * Note: the caller must ensure that the delegate lives throughout the instance's lifetime. */ - TlsCertificateManagementServer(EndpointId endpointId, TlsCertificateManagementDelegate & delegate, - Tls::CertificateDependencyChecker & dependencyChecker, Tls::CertificateTable & certificateTable, - uint8_t maxRootCertificates, uint8_t maxClientCertificates); - ~TlsCertificateManagementServer(); - - /** - * Initializes the TLS Certificate Management server instance. - * @return Returns an error if the CommandHandler or AttributeHandler registration fails. - */ - CHIP_ERROR Init(); - - /** - * Shuts down the TLS Certificate Management server instance. - * @return Returns an error if the destruction fails. - */ - CHIP_ERROR Finish(); + TLSCertificateManagementCluster(EndpointId endpointId, TLSCertificateManagementDelegate & delegate, + Tls::CertificateDependencyChecker & dependencyChecker, Tls::CertificateTable & certificateTable, + uint8_t maxRootCertificates, uint8_t maxClientCertificates); + ~TLSCertificateManagementCluster(); // Attribute Getters @@ -82,12 +67,29 @@ class TlsCertificateManagementServer : private AttributeAccessInterface, /** * @return The endpoint ID. */ - EndpointId GetEndpointId() { return AttributeAccessInterface::GetEndpointId().Value(); } + EndpointId GetEndpointId() const { return mPath.mEndpointId; } Tls::CertificateTable & GetCertificateTable() { return mCertificateTable; } + /** + * @brief ServerClusterInterface methods. + */ + CHIP_ERROR Startup(ServerClusterContext & context) override; + void Shutdown() override; + + DataModel::ActionReturnStatus ReadAttribute(const DataModel::ReadAttributeRequest & request, + AttributeValueEncoder & encoder) override; + + std::optional InvokeCommand(const DataModel::InvokeRequest & request, + TLV::TLVReader & input_arguments, CommandHandler * handler) override; + + CHIP_ERROR AcceptedCommands(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) override; + + CHIP_ERROR Attributes(const ConcreteClusterPath & path, ReadOnlyBufferBuilder & builder) override; + private: - TlsCertificateManagementDelegate & mDelegate; + TLSCertificateManagementDelegate & mDelegate; Tls::CertificateDependencyChecker & mDependencyChecker; Tls::CertificateTable & mCertificateTable; @@ -95,36 +97,35 @@ class TlsCertificateManagementServer : private AttributeAccessInterface, uint8_t mMaxRootCertificates; uint8_t mMaxClientCertificates; - // AttributeAccessInterface - CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override - { - ChipLogError(NotSpecified, "DataModel::ReadAttributeRequest overload should be called"); - chipAbort(); - } - - CHIP_ERROR Read(const DataModel::ReadAttributeRequest & aRequest, AttributeValueEncoder & aEncoder) override; - - // CommandHandlerInterface - void InvokeCommand(HandlerContext & ctx) override; - void HandleProvisionRootCertificate(HandlerContext & ctx, - const TlsCertificateManagement::Commands::ProvisionRootCertificate::DecodableType & req); - void HandleFindRootCertificate(HandlerContext & ctx, - const TlsCertificateManagement::Commands::FindRootCertificate::DecodableType & req); - void HandleLookupRootCertificate(HandlerContext & ctx, - const TlsCertificateManagement::Commands::LookupRootCertificate::DecodableType & req); - void HandleRemoveRootCertificate(HandlerContext & ctx, - const TlsCertificateManagement::Commands::RemoveRootCertificate::DecodableType & req); - - void HandleGenerateClientCsr(HandlerContext & ctx, const TlsCertificateManagement::Commands::ClientCSR::DecodableType & req); - void - HandleProvisionClientCertificate(HandlerContext & ctx, + // Command Handlers + std::optional + HandleProvisionRootCertificate(CommandHandler & commandHandler, + const TlsCertificateManagement::Commands::ProvisionRootCertificate::DecodableType & req); + std::optional + HandleFindRootCertificate(CommandHandler & commandHandler, + const TlsCertificateManagement::Commands::FindRootCertificate::DecodableType & req); + std::optional + HandleLookupRootCertificate(CommandHandler & commandHandler, + const TlsCertificateManagement::Commands::LookupRootCertificate::DecodableType & req); + std::optional + HandleRemoveRootCertificate(CommandHandler & commandHandler, + const TlsCertificateManagement::Commands::RemoveRootCertificate::DecodableType & req); + + std::optional + HandleGenerateClientCsr(CommandHandler & commandHandler, + const TlsCertificateManagement::Commands::ClientCSR::DecodableType & req); + std::optional + HandleProvisionClientCertificate(CommandHandler & commandHandler, const TlsCertificateManagement::Commands::ProvisionClientCertificate::DecodableType & req); - void HandleFindClientCertificate(HandlerContext & ctx, - const TlsCertificateManagement::Commands::FindClientCertificate::DecodableType & req); - void HandleLookupClientCertificate(HandlerContext & ctx, - const TlsCertificateManagement::Commands::LookupClientCertificate::DecodableType & req); - void HandleRemoveClientCertificate(HandlerContext & ctx, - const TlsCertificateManagement::Commands::RemoveClientCertificate::DecodableType & req); + std::optional + HandleFindClientCertificate(CommandHandler & commandHandler, + const TlsCertificateManagement::Commands::FindClientCertificate::DecodableType & req); + std::optional + HandleLookupClientCertificate(CommandHandler & commandHandler, + const TlsCertificateManagement::Commands::LookupClientCertificate::DecodableType & req); + std::optional + HandleRemoveClientCertificate(CommandHandler & commandHandler, + const TlsCertificateManagement::Commands::RemoveClientCertificate::DecodableType & req); // Encodes all provisioned root certificates CHIP_ERROR EncodeProvisionedRootCertificates(EndpointId matterEndpoint, FabricIndex fabric, bool largePayload, @@ -139,7 +140,7 @@ class TlsCertificateManagementServer : private AttributeAccessInterface, /** @brief * Defines methods for implementing application-specific logic for the TlsCertificateManagement Cluster. */ -class TlsCertificateManagementDelegate +class TLSCertificateManagementDelegate { public: using RootCertStructType = TlsCertificateManagement::Structs::TLSCertStruct::Type; @@ -149,9 +150,9 @@ class TlsCertificateManagementDelegate using ClientCsrType = TlsCertificateManagement::Commands::ClientCSR::DecodableType; using ClientCsrResponseType = TlsCertificateManagement::Commands::ClientCSRResponse::Type; - TlsCertificateManagementDelegate() = default; + TLSCertificateManagementDelegate() = default; - virtual ~TlsCertificateManagementDelegate() = default; + virtual ~TLSCertificateManagementDelegate() = default; using RootCertificateListCallback = std::function & certs)>; using ClientCertificateListCallback = std::function & certs)>; @@ -337,19 +338,19 @@ class TlsCertificateManagementDelegate virtual Protocols::InteractionModel::Status RemoveClientCert(EndpointId matterEndpoint, FabricIndex fabric, Tls::TLSCCDID id) = 0; - Tls::CertificateTable & GetCertificateTable() { return mTlsCertificateManagementServer->GetCertificateTable(); } + Tls::CertificateTable & GetCertificateTable() { return mTLSCertificateManagementCluster->GetCertificateTable(); } protected: - friend class TlsCertificateManagementServer; + friend class TLSCertificateManagementCluster; - TlsCertificateManagementServer * mTlsCertificateManagementServer = nullptr; + TLSCertificateManagementCluster * mTLSCertificateManagementCluster = nullptr; - // sets the TlsCertificateManagement Server pointer - void SetTlsCertificateManagementServer(TlsCertificateManagementServer * tlsCertificateManagementServer) + // sets the TlsCertificateManagement Cluster pointer + void SetTLSCertificateManagementCluster(TLSCertificateManagementCluster * tlsCertificateManagementServer) { - mTlsCertificateManagementServer = tlsCertificateManagementServer; + mTLSCertificateManagementCluster = tlsCertificateManagementServer; } - TlsCertificateManagementServer * GetTlsCertificateManagementServer() const { return mTlsCertificateManagementServer; } + TLSCertificateManagementCluster * GetTLSCertificateManagementCluster() const { return mTLSCertificateManagementCluster; } }; } // namespace Clusters diff --git a/src/app/clusters/tls-certificate-management-server/app_config_dependent_sources.cmake b/src/app/clusters/tls-certificate-management-server/app_config_dependent_sources.cmake index fb8886c7d6f..ace17e9b293 100644 --- a/src/app/clusters/tls-certificate-management-server/app_config_dependent_sources.cmake +++ b/src/app/clusters/tls-certificate-management-server/app_config_dependent_sources.cmake @@ -18,6 +18,7 @@ TARGET_SOURCES( PRIVATE "${CLUSTER_DIR}/CertificateTableImpl.cpp" "${CLUSTER_DIR}/CertificateTableImpl.h" - "${CLUSTER_DIR}/tls-certificate-management-server.cpp" - "${CLUSTER_DIR}/tls-certificate-management-server.h" + "${CLUSTER_DIR}/CodegenIntegration.cpp" + "${CLUSTER_DIR}/TLSCertificateManagementCluster.cpp" + "${CLUSTER_DIR}/TLSCertificateManagementCluster.h" ) \ No newline at end of file diff --git a/src/app/clusters/tls-certificate-management-server/app_config_dependent_sources.gni b/src/app/clusters/tls-certificate-management-server/app_config_dependent_sources.gni index b7b7a9baccc..be7224f0bbc 100644 --- a/src/app/clusters/tls-certificate-management-server/app_config_dependent_sources.gni +++ b/src/app/clusters/tls-certificate-management-server/app_config_dependent_sources.gni @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import("//build_overrides/chip.gni") - -app_config_dependent_sources = [] +app_config_dependent_sources = [ + "CodegenIntegration.cpp", + "CodegenIntegration.h", +] diff --git a/src/app/clusters/tls-certificate-management-server/tests/BUILD.gn b/src/app/clusters/tls-certificate-management-server/tests/BUILD.gn new file mode 100644 index 00000000000..04862609a87 --- /dev/null +++ b/src/app/clusters/tls-certificate-management-server/tests/BUILD.gn @@ -0,0 +1,34 @@ +# Copyright (c) 2025 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +import("${chip_root}/build/chip/chip_test_suite.gni") + +chip_test_suite("tests") { + output_name = "libTestTLSCertificateManagementCluster" + + test_sources = [ "TestTLSCertificateManagementCluster.cpp" ] + + cflags = [ "-Wconversion" ] + + public_deps = [ + "${chip_root}/src/app:attribute-persistence", + "${chip_root}/src/app/clusters/tls-certificate-management-server", + "${chip_root}/src/app/data-model-provider/tests:encode-decode", + "${chip_root}/src/app/server-cluster/testing:testing", + "${chip_root}/src/lib/support", + ] +} diff --git a/src/app/clusters/tls-certificate-management-server/tests/TestTLSCertificateManagementCluster.cpp b/src/app/clusters/tls-certificate-management-server/tests/TestTLSCertificateManagementCluster.cpp new file mode 100644 index 00000000000..aea5abc6281 --- /dev/null +++ b/src/app/clusters/tls-certificate-management-server/tests/TestTLSCertificateManagementCluster.cpp @@ -0,0 +1,841 @@ +/* + * Copyright (c) 2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::Tls; +using namespace chip::app::Clusters::TlsCertificateManagement; +using namespace chip::Testing; + +namespace { + +constexpr EndpointId kTestEndpointId = 1; +constexpr uint8_t kMaxRootCertificates = 10; +constexpr uint8_t kMaxClientCertificates = 10; + +// Helper function to generate a valid test certificate +CHIP_ERROR GenerateTestCertificate(MutableByteSpan & certSpan) +{ + using namespace Credentials; + using namespace Crypto; + + // Generate a keypair for the certificate + P256Keypair keypair; + ReturnErrorOnFailure(keypair.Initialize(Crypto::ECPKeyTarget::ECDSA)); + + // Set up certificate parameters with valid dates + // validityStart = 1: Just after CHIP epoch (2000-01-01 00:00:01 UTC) - always in the past + // Note: 0 is special (kNullCertTime) and maps to 9999-12-31, which would fail + // validityEnd = 0: kNullCertTime maps to 9999-12-31 23:59:59 UTC - always in the future + // This ensures the certificate passes IsCertificateValidAtCurrentTime regardless of system time + uint32_t validityStart = 1; + uint32_t validityEnd = kNullCertTime; + + ChipDN subjectDN; + ReturnErrorOnFailure(subjectDN.AddAttribute_MatterRCACId(0x1234ABCD)); + + X509CertRequestParams certParams = { 1, validityStart, validityEnd, subjectDN, subjectDN }; + + // Generate the certificate + return NewRootX509Cert(certParams, keypair, certSpan); +} + +// Mock implementations +class MockCertificateTable : public CertificateTable +{ +public: + struct MockRootCert + { + FabricIndex fabric; + TLSCAID caid; + }; + + struct MockClientCert + { + FabricIndex fabric; + TLSCCDID ccdid; + }; + + std::vector rootCerts; + std::vector clientCerts; + + CHIP_ERROR Init(PersistentStorageDelegate & storage) override { return CHIP_NO_ERROR; } + + void Finish() override {} + + CHIP_ERROR UpsertRootCertificateEntry(FabricIndex fabric_index, Optional & id, RootBuffer & buffer, + const ByteSpan & certificate) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetRootCertificateEntry(FabricIndex fabric_index, TLSCAID id, BufferedRootCert & entry) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR HasRootCertificateEntry(FabricIndex fabric_index, TLSCAID id) override + { + for (const auto & cert : rootCerts) + { + if (cert.fabric == fabric_index && cert.caid == id) + { + return CHIP_NO_ERROR; + } + } + return CHIP_ERROR_NOT_FOUND; + } + + CHIP_ERROR IterateRootCertificates(FabricIndex fabric, BufferedRootCert & store, IterateRootCertFnType iterateFn) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetClientCertificateEntry(FabricIndex fabric_index, TLSCCDID id, BufferedClientCert & entry) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR HasClientCertificateEntry(FabricIndex fabric_index, TLSCCDID id) override + { + for (const auto & cert : clientCerts) + { + if (cert.fabric == fabric_index && cert.ccdid == id) + { + return CHIP_NO_ERROR; + } + } + return CHIP_ERROR_NOT_FOUND; + } + + CHIP_ERROR IterateClientCertificates(FabricIndex fabric, BufferedClientCert & store, IterateClientCertFnType iterateFn) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR RemoveRootCertificate(FabricIndex fabric_index, TLSCAID id) override { return CHIP_NO_ERROR; } + + CHIP_ERROR GetRootCertificateCount(FabricIndex fabric, uint8_t & outCount) override + { + outCount = 0; + return CHIP_NO_ERROR; + } + + CHIP_ERROR PrepareClientCertificate(FabricIndex fabric, const ByteSpan & nonce, ClientBuffer & buffer, Optional & id, + MutableByteSpan & csr, MutableByteSpan & nonceSignature) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR UpdateClientCertificateEntry(FabricIndex fabric_index, TLSCCDID id, ClientBuffer & buffer, + const ClientCertStruct & entry) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR RemoveClientCertificate(FabricIndex fabric_index, TLSCCDID id) override { return CHIP_NO_ERROR; } + + CHIP_ERROR GetClientCertificateCount(FabricIndex fabric, uint8_t & outCount) override + { + outCount = 0; + return CHIP_NO_ERROR; + } + + CHIP_ERROR RemoveFabric(FabricIndex fabricIndex) override { return CHIP_NO_ERROR; } +}; + +class MockCertificateDependencyChecker : public CertificateDependencyChecker +{ +public: + CHIP_ERROR RootCertCanBeRemoved(EndpointId matterEndpoint, FabricIndex fabric, TLSCAID id) override { return CHIP_NO_ERROR; } + + CHIP_ERROR ClientCertCanBeRemoved(EndpointId matterEndpoint, FabricIndex fabric, TLSCCDID id) override { return CHIP_NO_ERROR; } +}; + +class MockTLSCertificateManagementDelegate : public TLSCertificateManagementDelegate +{ +public: + struct MockRootCert + { + EndpointId matterEndpoint; + FabricIndex fabric; + TLSCAID caid; + std::vector certificate; + std::vector fingerprint; + }; + + struct MockClientCert + { + EndpointId matterEndpoint; + FabricIndex fabric; + TLSCCDID ccdid; + std::vector certificate; + std::vector fingerprint; + TLSCAID caid; + }; + + std::vector rootCerts; + std::vector clientCerts; + + Protocols::InteractionModel::Status provisionRootStatus = Protocols::InteractionModel::Status::Success; + Protocols::InteractionModel::Status provisionClientStatus = Protocols::InteractionModel::Status::Success; + Protocols::InteractionModel::Status removeRootStatus = Protocols::InteractionModel::Status::Success; + Protocols::InteractionModel::Status removeClientStatus = Protocols::InteractionModel::Status::Success; + Protocols::InteractionModel::Status generateCsrStatus = Protocols::InteractionModel::Status::Success; + + TLSCAID nextRootCertId = 1; + mutable TLSCCDID nextClientCertId = 1; + + // Reference to mock certificate table for coordinating GenerateClientCsr with HasClientCertificateEntry + MockCertificateTable * mCertTable = nullptr; + + void SetCertificateTable(MockCertificateTable * certTable) { mCertTable = certTable; } + + Protocols::InteractionModel::Status ProvisionRootCert(EndpointId matterEndpoint, FabricIndex fabric, + const ProvisionRootCertificateType & provisionReq, + TLSCAID & outCaid) override + { + if (provisionRootStatus != Protocols::InteractionModel::Status::Success) + { + return provisionRootStatus; + } + + outCaid = nextRootCertId++; + MockRootCert cert; + cert.matterEndpoint = matterEndpoint; + cert.fabric = fabric; + cert.caid = outCaid; + cert.certificate = std::vector(provisionReq.certificate.data(), + provisionReq.certificate.data() + provisionReq.certificate.size()); + rootCerts.push_back(cert); + + return Protocols::InteractionModel::Status::Success; + } + + CHIP_ERROR LoadedRootCerts(EndpointId matterEndpoint, FabricIndex fabric, + LoadedRootCertificateCallback loadedCallback) const override + { + for (const auto & cert : rootCerts) + { + if (cert.matterEndpoint == matterEndpoint && cert.fabric == fabric) + { + Structs::TLSCertStruct::Type decodable; + decodable.caid = cert.caid; + decodable.certificate.SetValue(ByteSpan(cert.certificate.data(), cert.certificate.size())); + ReturnErrorOnFailure(loadedCallback(decodable)); + } + } + return CHIP_NO_ERROR; + } + + CHIP_ERROR RootCertsForFabric(EndpointId matterEndpoint, FabricIndex fabric, + RootCertificateListCallback loadedCallback) const override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR FindRootCert(EndpointId matterEndpoint, FabricIndex fabric, TLSCAID id, + LoadedRootCertificateCallback loadedCallback) const override + { + for (const auto & cert : rootCerts) + { + if (cert.matterEndpoint == matterEndpoint && cert.fabric == fabric && cert.caid == id) + { + Structs::TLSCertStruct::Type decodable; + decodable.caid = cert.caid; + decodable.certificate.SetValue(ByteSpan(cert.certificate.data(), cert.certificate.size())); + return loadedCallback(decodable); + } + } + return CHIP_ERROR_NOT_FOUND; + } + + CHIP_ERROR LookupRootCertByFingerprint(EndpointId matterEndpoint, FabricIndex fabric, const ByteSpan & fingerprint, + LoadedRootCertificateCallback loadedCallback) const override + { + for (const auto & cert : rootCerts) + { + if (cert.matterEndpoint == matterEndpoint && cert.fabric == fabric && cert.fingerprint.size() == fingerprint.size() && + memcmp(cert.fingerprint.data(), fingerprint.data(), fingerprint.size()) == 0) + { + Structs::TLSCertStruct::Type decodable; + decodable.caid = cert.caid; + decodable.certificate.SetValue(ByteSpan(cert.certificate.data(), cert.certificate.size())); + return loadedCallback(decodable); + } + } + return CHIP_ERROR_NOT_FOUND; + } + + CHIP_ERROR LookupRootCert(EndpointId matterEndpoint, FabricIndex fabric, const ByteSpan & cert, + LoadedRootCertificateCallback loadedCallback) const override + { + return CHIP_ERROR_NOT_FOUND; + } + + Protocols::InteractionModel::Status RemoveRootCert(EndpointId matterEndpoint, FabricIndex fabric, TLSCAID id) override + { + if (removeRootStatus != Protocols::InteractionModel::Status::Success) + { + return removeRootStatus; + } + + for (auto it = rootCerts.begin(); it != rootCerts.end(); ++it) + { + if (it->matterEndpoint == matterEndpoint && it->fabric == fabric && it->caid == id) + { + rootCerts.erase(it); + return Protocols::InteractionModel::Status::Success; + } + } + return Protocols::InteractionModel::Status::NotFound; + } + + Protocols::InteractionModel::Status GenerateClientCsr(EndpointId matterEndpoint, FabricIndex fabric, + const ClientCsrType & request, + GeneratedCsrCallback loadedCallback) const override + { + if (generateCsrStatus != Protocols::InteractionModel::Status::Success) + { + return generateCsrStatus; + } + + ClientCsrResponseType response; + uint8_t dummyCsr[32] = { 0x01, 0x02, 0x03 }; + uint8_t dummySig[32] = { 0x04, 0x05, 0x06 }; + response.csr = ByteSpan(dummyCsr, sizeof(dummyCsr)); + response.nonceSignature = ByteSpan(dummySig, sizeof(dummySig)); + + // Allocate a ccdid and add entry to certificate table (simulates real delegate behavior) + TLSCCDID ccdid = nextClientCertId++; + if (mCertTable != nullptr) + { + mCertTable->clientCerts.push_back({ fabric, ccdid }); + } + response.ccdid = ccdid; + + return loadedCallback(response); + } + + Protocols::InteractionModel::Status ProvisionClientCert(EndpointId matterEndpoint, FabricIndex fabric, + const ProvisionClientCertificateType & provisionReq) override + { + if (provisionClientStatus != Protocols::InteractionModel::Status::Success) + { + return provisionClientStatus; + } + + MockClientCert cert; + cert.matterEndpoint = matterEndpoint; + cert.fabric = fabric; + cert.ccdid = provisionReq.ccdid; + cert.certificate = std::vector(provisionReq.clientCertificate.data(), + provisionReq.clientCertificate.data() + provisionReq.clientCertificate.size()); + clientCerts.push_back(cert); + + return Protocols::InteractionModel::Status::Success; + } + + CHIP_ERROR LoadedClientCerts(EndpointId matterEndpoint, FabricIndex fabric, + LoadedClientCertificateCallback loadedCallback) const override + { + for (const auto & cert : clientCerts) + { + if (cert.matterEndpoint == matterEndpoint && cert.fabric == fabric) + { + Structs::TLSClientCertificateDetailStruct::Type decodable; + decodable.ccdid = cert.ccdid; + decodable.clientCertificate.SetValue( + DataModel::MakeNullable(ByteSpan(cert.certificate.data(), cert.certificate.size()))); + ReturnErrorOnFailure(loadedCallback(decodable)); + } + } + return CHIP_NO_ERROR; + } + + CHIP_ERROR ClientCertsForFabric(EndpointId matterEndpoint, FabricIndex fabric, + ClientCertificateListCallback loadedCallback) const override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR FindClientCert(EndpointId matterEndpoint, FabricIndex fabric, TLSCCDID id, + LoadedClientCertificateCallback loadedCallback) const override + { + for (const auto & cert : clientCerts) + { + if (cert.matterEndpoint == matterEndpoint && cert.fabric == fabric && cert.ccdid == id) + { + Structs::TLSClientCertificateDetailStruct::Type decodable; + decodable.ccdid = cert.ccdid; + decodable.clientCertificate.SetValue( + DataModel::MakeNullable(ByteSpan(cert.certificate.data(), cert.certificate.size()))); + return loadedCallback(decodable); + } + } + return CHIP_ERROR_NOT_FOUND; + } + + CHIP_ERROR LookupClientCertByFingerprint(EndpointId matterEndpoint, FabricIndex fabric, const ByteSpan & fingerprint, + LoadedClientCertificateCallback loadedCallback) const override + { + for (const auto & cert : clientCerts) + { + if (cert.matterEndpoint == matterEndpoint && cert.fabric == fabric && cert.fingerprint.size() == fingerprint.size() && + memcmp(cert.fingerprint.data(), fingerprint.data(), fingerprint.size()) == 0) + { + Structs::TLSClientCertificateDetailStruct::Type decodable; + decodable.ccdid = cert.ccdid; + decodable.clientCertificate.SetValue( + DataModel::MakeNullable(ByteSpan(cert.certificate.data(), cert.certificate.size()))); + return loadedCallback(decodable); + } + } + return CHIP_ERROR_NOT_FOUND; + } + + CHIP_ERROR LookupClientCert(EndpointId matterEndpoint, FabricIndex fabric, const ByteSpan & certificate, + LoadedClientCertificateCallback loadedCallback) const override + { + return CHIP_ERROR_NOT_FOUND; + } + + Protocols::InteractionModel::Status RemoveClientCert(EndpointId matterEndpoint, FabricIndex fabric, TLSCCDID id) override + { + if (removeClientStatus != Protocols::InteractionModel::Status::Success) + { + return removeClientStatus; + } + + for (auto it = clientCerts.begin(); it != clientCerts.end(); ++it) + { + if (it->matterEndpoint == matterEndpoint && it->fabric == fabric && it->ccdid == id) + { + clientCerts.erase(it); + return Protocols::InteractionModel::Status::Success; + } + } + return Protocols::InteractionModel::Status::NotFound; + } +}; + +struct TestTLSCertificateManagementCluster : public ::testing::Test +{ + static void SetUpTestSuite() { ASSERT_EQ(Platform::MemoryInit(), CHIP_NO_ERROR); } + static void TearDownTestSuite() { Platform::MemoryShutdown(); } + + void SetUp() override + { + VerifyOrDie(mPersistenceProvider.Init(&mClusterTester.GetServerClusterContext().storage) == CHIP_NO_ERROR); + app::SetSafeAttributePersistenceProvider(&mPersistenceProvider); + + // Wire up mock delegate to mock certificate table so GenerateClientCsr adds entries + mMockDelegate.SetCertificateTable(&mMockCertTable); + + // Add some test root certificates for the test fabric index (151) + constexpr FabricIndex kMockTestFabric = static_cast(151); + mMockCertTable.rootCerts.push_back({ kMockTestFabric, 1 }); + mMockCertTable.rootCerts.push_back({ kMockTestFabric, 2 }); + + EXPECT_EQ(mCluster.Startup(mClusterTester.GetServerClusterContext()), CHIP_NO_ERROR); + } + + void TearDown() override { app::SetSafeAttributePersistenceProvider(nullptr); } + + MockTLSCertificateManagementDelegate mMockDelegate; + MockCertificateTable mMockCertTable; + MockCertificateDependencyChecker mMockDependencyChecker; + + TLSCertificateManagementCluster mCluster{ kTestEndpointId, mMockDelegate, mMockDependencyChecker, + mMockCertTable, kMaxRootCertificates, kMaxClientCertificates }; + + ClusterTester mClusterTester{ mCluster }; + + app::DefaultSafeAttributePersistenceProvider mPersistenceProvider; +}; + +TEST_F(TestTLSCertificateManagementCluster, TestReadMaxRootCertificates) +{ + uint8_t maxRootCertificates = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::MaxRootCertificates::Id, maxRootCertificates), CHIP_NO_ERROR); + EXPECT_EQ(maxRootCertificates, kMaxRootCertificates); +} + +TEST_F(TestTLSCertificateManagementCluster, TestReadMaxClientCertificates) +{ + uint8_t maxClientCertificates = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::MaxClientCertificates::Id, maxClientCertificates), CHIP_NO_ERROR); + EXPECT_EQ(maxClientCertificates, kMaxClientCertificates); +} + +TEST_F(TestTLSCertificateManagementCluster, TestReadClusterRevision) +{ + uint16_t clusterRevision = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::ClusterRevision::Id, clusterRevision), CHIP_NO_ERROR); + EXPECT_EQ(clusterRevision, kRevision); +} + +TEST_F(TestTLSCertificateManagementCluster, TestReadFeatureMap) +{ + uint32_t featureMap = 1; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::FeatureMap::Id, featureMap), CHIP_NO_ERROR); + EXPECT_EQ(featureMap, 0u); +} + +TEST_F(TestTLSCertificateManagementCluster, TestReadProvisionedRootCertificatesEmpty) +{ + Attributes::ProvisionedRootCertificates::TypeInfo::DecodableType list; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::ProvisionedRootCertificates::Id, list), CHIP_NO_ERROR); + + auto it = list.begin(); + EXPECT_FALSE(it.Next()); +} + +TEST_F(TestTLSCertificateManagementCluster, TestReadProvisionedClientCertificatesEmpty) +{ + Attributes::ProvisionedClientCertificates::TypeInfo::DecodableType list; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::ProvisionedClientCertificates::Id, list), CHIP_NO_ERROR); + + auto it = list.begin(); + EXPECT_FALSE(it.Next()); +} + +TEST_F(TestTLSCertificateManagementCluster, TestProvisionRootCertificateSuccess) +{ + // Generate a valid test certificate + uint8_t certBuffer[Credentials::kMaxDERCertLength]; + MutableByteSpan certSpan(certBuffer); + CHIP_ERROR certGenErr = GenerateTestCertificate(certSpan); + ASSERT_EQ(certGenErr, CHIP_NO_ERROR); + EXPECT_GT(certSpan.size(), 0u); + ChipLogProgress(Zcl, "Generated certificate of size %u", static_cast(certSpan.size())); + + Commands::ProvisionRootCertificate::Type request; + request.certificate = certSpan; + + auto result = mClusterTester.Invoke(request); + EXPECT_TRUE(result.IsSuccess()); + if (!result.IsSuccess()) + { + if (result.status.has_value()) + { + ChipLogError(Zcl, "ProvisionRootCertificate failed with status: 0x%x", + to_underlying(result.status.value().GetStatusCode().GetStatus())); + } + else + { + ChipLogError(Zcl, "ProvisionRootCertificate failed with no status code"); + } + } + + if (result.response.has_value()) + { + EXPECT_EQ(result.response.value().caid, 1); + } + + // Verify certificate was added + EXPECT_EQ(mMockDelegate.rootCerts.size(), 1u); + if (mMockDelegate.rootCerts.size() > 0) + { + EXPECT_EQ(mMockDelegate.rootCerts[0].caid, 1); + } +} + +TEST_F(TestTLSCertificateManagementCluster, TestFindRootCertificateSuccess) +{ + // Generate a valid test certificate + uint8_t certBuffer[Credentials::kMaxDERCertLength]; + MutableByteSpan certSpan(certBuffer); + EXPECT_EQ(GenerateTestCertificate(certSpan), CHIP_NO_ERROR); + + // First provision a certificate + Commands::ProvisionRootCertificate::Type provisionReq; + provisionReq.certificate = certSpan; + + auto provisionResult = mClusterTester.Invoke(provisionReq); + EXPECT_TRUE(provisionResult.IsSuccess()); + ASSERT_TRUE(provisionResult.response.has_value()); + + TLSCAID provisionedId = 0; + if (provisionResult.response.has_value()) + { + provisionedId = provisionResult.response.value().caid; + } + + // Now find it + Commands::FindRootCertificate::Type findReq; + findReq.caid = provisionedId; + + auto findResult = mClusterTester.Invoke(findReq); + EXPECT_TRUE(findResult.IsSuccess()); + + if (findResult.response.has_value()) + { + auto iter = findResult.response.value().certificateDetails.begin(); + ASSERT_TRUE(iter.Next()); + EXPECT_EQ(iter.GetValue().caid, provisionedId); + EXPECT_TRUE(iter.GetValue().certificate.Value().data_equal(certSpan)); + } +} + +TEST_F(TestTLSCertificateManagementCluster, TestFindRootCertificateNotFound) +{ + Commands::FindRootCertificate::Type request; + request.caid = 999; // Non-existent certificate + + auto result = mClusterTester.Invoke(request); + EXPECT_FALSE(result.IsSuccess()); + if (result.status.has_value()) + { + EXPECT_EQ(result.status.value().GetStatusCode().GetStatus(), Protocols::InteractionModel::Status::NotFound); + } +} + +TEST_F(TestTLSCertificateManagementCluster, TestRemoveRootCertificateSuccess) +{ + // Generate a valid test certificate + uint8_t certBuffer[Credentials::kMaxDERCertLength]; + MutableByteSpan certSpan(certBuffer); + EXPECT_EQ(GenerateTestCertificate(certSpan), CHIP_NO_ERROR); + + // First provision a certificate + Commands::ProvisionRootCertificate::Type provisionReq; + provisionReq.certificate = certSpan; + + auto provisionResult = mClusterTester.Invoke(provisionReq); + EXPECT_TRUE(provisionResult.IsSuccess()); + ASSERT_TRUE(provisionResult.response.has_value()); + + TLSCAID provisionedId = 0; + if (provisionResult.response.has_value()) + { + provisionedId = provisionResult.response.value().caid; + } + + EXPECT_EQ(mMockDelegate.rootCerts.size(), 1u); + + // Now remove it + Commands::RemoveRootCertificate::Type removeReq; + removeReq.caid = provisionedId; + + auto removeResult = mClusterTester.Invoke(removeReq); + EXPECT_TRUE(removeResult.IsSuccess()); + + // Verify it was removed + EXPECT_EQ(mMockDelegate.rootCerts.size(), 0u); +} + +TEST_F(TestTLSCertificateManagementCluster, TestRemoveRootCertificateNotFound) +{ + Commands::RemoveRootCertificate::Type request; + request.caid = 999; // Non-existent certificate + + auto result = mClusterTester.Invoke(request); + EXPECT_FALSE(result.IsSuccess()); + if (result.status.has_value()) + { + EXPECT_EQ(result.status.value().GetStatusCode().GetStatus(), Protocols::InteractionModel::Status::NotFound); + } +} + +TEST_F(TestTLSCertificateManagementCluster, TestGenerateClientCsrSuccess) +{ + Commands::ClientCSR::Type request; + uint8_t dummyNonce[32] = { 0x01, 0x02, 0x03 }; + request.nonce = ByteSpan(dummyNonce, sizeof(dummyNonce)); + + auto result = mClusterTester.Invoke(request); + EXPECT_TRUE(result.IsSuccess()); + + if (result.response.has_value()) + { + EXPECT_GT(result.response.value().csr.size(), 0u); + EXPECT_GT(result.response.value().nonceSignature.size(), 0u); + EXPECT_EQ(result.response.value().ccdid, 1); + } +} + +TEST_F(TestTLSCertificateManagementCluster, TestProvisionClientCertificateSuccess) +{ + // Step 1: Generate a CSR to create the key pair and get the ccdid + Commands::ClientCSR::Type csrRequest; + uint8_t dummyNonce[32] = { 0x01, 0x02, 0x03 }; + csrRequest.nonce = ByteSpan(dummyNonce, sizeof(dummyNonce)); + + auto csrResult = mClusterTester.Invoke(csrRequest); + EXPECT_TRUE(csrResult.IsSuccess()); + ASSERT_TRUE(csrResult.response.has_value()); + + TLSCCDID ccdid = 0; + if (csrResult.response.has_value()) + { + ccdid = csrResult.response.value().ccdid; + } + + // Step 2: Generate a valid test certificate + uint8_t certBuffer[Credentials::kMaxDERCertLength]; + MutableByteSpan certSpan(certBuffer); + EXPECT_EQ(GenerateTestCertificate(certSpan), CHIP_NO_ERROR); + + // Step 3: Provision the client certificate using the ccdid from the CSR + Commands::ProvisionClientCertificate::Type request; + request.clientCertificate = certSpan; + request.ccdid = ccdid; + + auto result = mClusterTester.Invoke(request); + EXPECT_TRUE(result.IsSuccess()); + + // Verify certificate was added + EXPECT_EQ(mMockDelegate.clientCerts.size(), 1u); + if (mMockDelegate.clientCerts.size() > 0) + { + EXPECT_EQ(mMockDelegate.clientCerts[0].ccdid, ccdid); + } +} + +TEST_F(TestTLSCertificateManagementCluster, TestFindClientCertificateSuccess) +{ + // Step 1: Generate a CSR to create the key pair and get the ccdid + Commands::ClientCSR::Type csrRequest; + uint8_t dummyNonce[32] = { 0x01, 0x02, 0x03 }; + csrRequest.nonce = ByteSpan(dummyNonce, sizeof(dummyNonce)); + + auto csrResult = mClusterTester.Invoke(csrRequest); + EXPECT_TRUE(csrResult.IsSuccess()); + ASSERT_TRUE(csrResult.response.has_value()); + + TLSCCDID ccdid = 0; + if (csrResult.response.has_value()) + { + ccdid = csrResult.response.value().ccdid; + } + + // Step 2: Generate a valid test client certificate + uint8_t certBuffer[Credentials::kMaxDERCertLength]; + MutableByteSpan certSpan(certBuffer); + EXPECT_EQ(GenerateTestCertificate(certSpan), CHIP_NO_ERROR); + + // Step 3: Provision the client certificate + Commands::ProvisionClientCertificate::Type provisionReq; + provisionReq.clientCertificate = certSpan; + provisionReq.ccdid = ccdid; + + auto provisionResult = mClusterTester.Invoke(provisionReq); + EXPECT_TRUE(provisionResult.IsSuccess()); + + // Now find it + Commands::FindClientCertificate::Type findReq; + findReq.ccdid = ccdid; + + auto findResult = mClusterTester.Invoke(findReq); + EXPECT_TRUE(findResult.IsSuccess()); + + if (findResult.response.has_value()) + { + auto iter = findResult.response.value().certificateDetails.begin(); + ASSERT_TRUE(iter.Next()); + EXPECT_EQ(iter.GetValue().ccdid, ccdid); + EXPECT_TRUE(iter.GetValue().clientCertificate.Value().Value().data_equal(certSpan)); + } +} + +TEST_F(TestTLSCertificateManagementCluster, TestFindClientCertificateNotFound) +{ + Commands::FindClientCertificate::Type request; + request.ccdid = 999; // Non-existent certificate + + auto result = mClusterTester.Invoke(request); + EXPECT_FALSE(result.IsSuccess()); + if (result.status.has_value()) + { + EXPECT_EQ(result.status.value().GetStatusCode().GetStatus(), Protocols::InteractionModel::Status::NotFound); + } +} + +TEST_F(TestTLSCertificateManagementCluster, TestRemoveClientCertificateSuccess) +{ + // Step 1: Generate a CSR to create the key pair and get the ccdid + Commands::ClientCSR::Type csrRequest; + uint8_t dummyNonce[32] = { 0x01, 0x02, 0x03 }; + csrRequest.nonce = ByteSpan(dummyNonce, sizeof(dummyNonce)); + + auto csrResult = mClusterTester.Invoke(csrRequest); + EXPECT_TRUE(csrResult.IsSuccess()); + ASSERT_TRUE(csrResult.response.has_value()); + + TLSCCDID ccdid = 0; + if (csrResult.response.has_value()) + { + ccdid = csrResult.response.value().ccdid; + } + + // Step 2: Generate a valid test client certificate + uint8_t certBuffer[Credentials::kMaxDERCertLength]; + MutableByteSpan certSpan(certBuffer); + EXPECT_EQ(GenerateTestCertificate(certSpan), CHIP_NO_ERROR); + + // Step 3: Provision the client certificate + Commands::ProvisionClientCertificate::Type provisionReq; + provisionReq.clientCertificate = certSpan; + provisionReq.ccdid = ccdid; + + auto provisionResult = mClusterTester.Invoke(provisionReq); + EXPECT_TRUE(provisionResult.IsSuccess()); + + EXPECT_EQ(mMockDelegate.clientCerts.size(), 1u); + + // Now remove it + Commands::RemoveClientCertificate::Type removeReq; + removeReq.ccdid = ccdid; + + auto removeResult = mClusterTester.Invoke(removeReq); + EXPECT_TRUE(removeResult.IsSuccess()); + + // Verify it was removed + EXPECT_EQ(mMockDelegate.clientCerts.size(), 0u); +} + +TEST_F(TestTLSCertificateManagementCluster, TestRemoveClientCertificateNotFound) +{ + Commands::RemoveClientCertificate::Type request; + request.ccdid = 999; // Non-existent certificate + + auto result = mClusterTester.Invoke(request); + EXPECT_FALSE(result.IsSuccess()); + if (result.status.has_value()) + { + EXPECT_EQ(result.status.value().GetStatusCode().GetStatus(), Protocols::InteractionModel::Status::NotFound); + } +} + +} // namespace diff --git a/src/app/clusters/tls-certificate-management-server/tls-certificate-management-server.cpp b/src/app/clusters/tls-certificate-management-server/tls-certificate-management-server.cpp deleted file mode 100644 index bf44d18095a..00000000000 --- a/src/app/clusters/tls-certificate-management-server/tls-certificate-management-server.cpp +++ /dev/null @@ -1,515 +0,0 @@ -/* - * - * Copyright (c) 2025 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/****************************************************************************' - * @file - * @brief Implementation for the TlsCertificateManagement Server Cluster - ***************************************************************************/ - -#include "tls-certificate-management-server.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace chip; -using namespace chip::app; -using namespace chip::app::Clusters; -using namespace chip::app::Clusters::Tls; -using namespace chip::app::Clusters::TlsCertificateManagement; -using namespace chip::app::Clusters::TlsCertificateManagement::Commands; -using namespace chip::app::Clusters::TlsCertificateManagement::Structs; -using namespace chip::app::Clusters::TlsCertificateManagement::Attributes; -using chip::Protocols::InteractionModel::Status; - -static constexpr uint16_t kSpecMaxCertBytes = 3000; -static constexpr uint16_t kSpecMaxFingerprintBytes = 64; -static constexpr uint16_t kMaxIntermediateCertificates = 10; -static constexpr uint16_t kNonceBytes = 32; -static constexpr uint16_t kMaxSignatureBytes = 128; - -TlsCertificateManagementServer::TlsCertificateManagementServer(EndpointId endpointId, TlsCertificateManagementDelegate & delegate, - Tls::CertificateDependencyChecker & dependencyChecker, - CertificateTable & certificateTable, uint8_t maxRootCertificates, - uint8_t maxClientCertificates) : - AttributeAccessInterface(MakeOptional(endpointId), TlsCertificateManagement::Id), - CommandHandlerInterface(MakeOptional(endpointId), TlsCertificateManagement::Id), mDelegate(delegate), - mDependencyChecker(dependencyChecker), mCertificateTable(certificateTable), mMaxRootCertificates(maxRootCertificates), - mMaxClientCertificates(maxClientCertificates) -{ - VerifyOrDieWithMsg(mMaxRootCertificates >= 5, NotSpecified, "Spec requires MaxRootCertificates be >= 5"); - VerifyOrDieWithMsg(mMaxClientCertificates >= 5, NotSpecified, "Spec requires MaxClientCertificates be >= 5"); - mDelegate.SetTlsCertificateManagementServer(this); -} - -TlsCertificateManagementServer::~TlsCertificateManagementServer() -{ - // null out the ref to us on the delegate - mDelegate.SetTlsCertificateManagementServer(nullptr); - - // unregister - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); - AttributeAccessInterfaceRegistry::Instance().Unregister(this); -} - -CHIP_ERROR TlsCertificateManagementServer::Init() -{ - mCertificateTable.Init(Server::GetInstance().GetPersistentStorage()); - - VerifyOrReturnError(AttributeAccessInterfaceRegistry::Instance().Register(this), CHIP_ERROR_INTERNAL); - ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(this)); - - return Server::GetInstance().GetFabricTable().AddFabricDelegate(this); -} - -CHIP_ERROR TlsCertificateManagementServer::Finish() -{ - mCertificateTable.Finish(); - - Server::GetInstance().GetFabricTable().RemoveFabricDelegate(this); - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); - AttributeAccessInterfaceRegistry::Instance().Unregister(this); - - return CHIP_NO_ERROR; -} - -// AttributeAccessInterface -CHIP_ERROR TlsCertificateManagementServer::Read(const DataModel::ReadAttributeRequest & aRequest, AttributeValueEncoder & aEncoder) -{ - const auto & aPath = aRequest.path; - bool largePayload = aRequest.readFlags.Has(DataModel::ReadFlags::kAllowsLargePayload); - VerifyOrDie(aPath.mClusterId == TlsCertificateManagement::Id); - - switch (aPath.mAttributeId) - { - case MaxRootCertificates::Id: - return aEncoder.Encode(mMaxRootCertificates); - case ProvisionedRootCertificates::Id: { - auto matterEndpoint = aPath.mEndpointId; - auto fabric = aEncoder.AccessingFabricIndex(); - return aEncoder.EncodeList([this, matterEndpoint, fabric, largePayload](const auto & encoder) -> CHIP_ERROR { - return EncodeProvisionedRootCertificates(matterEndpoint, fabric, largePayload, encoder); - }); - } - case MaxClientCertificates::Id: - return aEncoder.Encode(mMaxClientCertificates); - case ProvisionedClientCertificates::Id: { - auto matterEndpoint = aPath.mEndpointId; - auto fabric = aEncoder.AccessingFabricIndex(); - return aEncoder.EncodeList([this, matterEndpoint, fabric, largePayload](const auto & encoder) -> CHIP_ERROR { - return EncodeProvisionedClientCertificates(matterEndpoint, fabric, largePayload, encoder); - }); - } - case ClusterRevision::Id: - return aEncoder.Encode(kRevision); - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR -TlsCertificateManagementServer::EncodeProvisionedRootCertificates(EndpointId matterEndpoint, FabricIndex fabric, bool largePayload, - const AttributeValueEncoder::ListEncodeHelper & encoder) -{ - return mDelegate.LoadedRootCerts(matterEndpoint, fabric, [&](auto & cert) -> CHIP_ERROR { - if (largePayload) - { - return encoder.Encode(cert); - } - - // Drop the certificate payload if transport doesn't support large payload - TLSCertStruct::Type idOnlyCert; - idOnlyCert.fabricIndex = cert.fabricIndex; - idOnlyCert.caid = cert.caid; - return encoder.Encode(idOnlyCert); - }); -} - -CHIP_ERROR -TlsCertificateManagementServer::EncodeProvisionedClientCertificates(EndpointId matterEndpoint, FabricIndex fabric, - bool largePayload, - const AttributeValueEncoder::ListEncodeHelper & encoder) -{ - return mDelegate.LoadedClientCerts(matterEndpoint, fabric, [&](auto & cert) -> CHIP_ERROR { - if (largePayload) - { - return encoder.Encode(cert); - } - - // Drop the certificate payload if transport doesn't support large payload - TLSClientCertificateDetailStruct::Type idOnlyCert; - idOnlyCert.fabricIndex = cert.fabricIndex; - idOnlyCert.ccdid = cert.ccdid; - return encoder.Encode(idOnlyCert); - }); -} - -void TlsCertificateManagementServer::InvokeCommand(HandlerContext & ctx) -{ - switch (ctx.mRequestPath.mCommandId) - { - case ProvisionRootCertificate::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleProvisionRootCertificate(innerCtx, req); }); - break; - case FindRootCertificate::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleFindRootCertificate(innerCtx, req); }); - break; - case LookupRootCertificate::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleLookupRootCertificate(innerCtx, req); }); - break; - case RemoveRootCertificate::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleRemoveRootCertificate(innerCtx, req); }); - break; - case ClientCSR::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleGenerateClientCsr(innerCtx, req); }); - break; - case ProvisionClientCertificate::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleProvisionClientCertificate(innerCtx, req); }); - break; - case FindClientCertificate::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleFindClientCertificate(innerCtx, req); }); - break; - case LookupClientCertificate::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleLookupClientCertificate(innerCtx, req); }); - break; - case RemoveClientCertificate::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleRemoveClientCertificate(innerCtx, req); }); - break; - } -} - -void TlsCertificateManagementServer::HandleProvisionRootCertificate(HandlerContext & ctx, - const ProvisionRootCertificate::DecodableType & req) -{ - ChipLogDetail(Zcl, "TlsCertificateManagement: ProvisionRootCertificate"); - - VerifyOrReturn(req.certificate.size() <= kSpecMaxCertBytes, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); - auto fabric = ctx.mCommandHandler.GetAccessingFabricIndex(); - DataModel::Nullable foundId; - auto lookupResult = - mDelegate.LookupRootCert(ctx.mRequestPath.mEndpointId, fabric, req.certificate, [&](auto & certificate) -> CHIP_ERROR { - foundId = certificate.caid; - return CHIP_NO_ERROR; - }); - if (lookupResult != CHIP_ERROR_NOT_FOUND) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::AlreadyExists); - return; - } - - if (req.caid.IsNull()) - { - uint8_t numRootCerts; - ReturnOnFailure(mCertificateTable.GetRootCertificateCount(fabric, numRootCerts), - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure)); - VerifyOrReturn(numRootCerts < mMaxRootCertificates, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ResourceExhausted)); - } - else - { - auto caid = req.caid.Value(); - VerifyOrReturn(caid <= kMaxRootCertId, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); - - ReturnOnFailure(mCertificateTable.HasRootCertificateEntry(fabric, caid), - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound)); - } - - ReturnOnFailure(Crypto::IsCertificateValidAtCurrentTime(req.certificate), - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::DynamicConstraintError)); - - ProvisionRootCertificateResponse::Type response; - auto status = mDelegate.ProvisionRootCert(ctx.mRequestPath.mEndpointId, fabric, req, response.caid); - if (status != Status::Success) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); - return; - } - - VerifyOrDieWithMsg(response.caid <= kMaxRootCertId, NotSpecified, "Spec requires CAID to be < kMaxRootCertId"); - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); -} - -void TlsCertificateManagementServer::HandleFindRootCertificate(HandlerContext & ctx, const FindRootCertificate::DecodableType & req) -{ - ChipLogDetail(Zcl, "TlsCertificateManagement: FindRootCertificate"); - CHIP_ERROR result; - if (req.caid.IsNull()) - { - result = mDelegate.RootCertsForFabric(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(), - [&](auto & certs) -> CHIP_ERROR { - if (certs.size() == 0) - { - return CHIP_ERROR_NOT_FOUND; - } - FindRootCertificateResponse::Type response; - response.certificateDetails = certs; - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); - return CHIP_NO_ERROR; - }); - } - else - { - VerifyOrReturn(req.caid.Value() <= kMaxRootCertId, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); - - result = mDelegate.FindRootCert(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(), - req.caid.Value(), [&](auto & certificate) -> CHIP_ERROR { - FindRootCertificateResponse::Type response; - DataModel::List details(&certificate, 1); - response.certificateDetails = details; - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); - return CHIP_NO_ERROR; - }); - } - if (result == CHIP_ERROR_NOT_FOUND) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); - } - else if (result != CHIP_NO_ERROR) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); - } -} - -void TlsCertificateManagementServer::HandleLookupRootCertificate(HandlerContext & ctx, - const LookupRootCertificate::DecodableType & req) -{ - ChipLogDetail(Zcl, "TlsCertificateManagement: LookupRootCertificate"); - VerifyOrReturn(req.fingerprint.size() <= kSpecMaxFingerprintBytes, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); - - auto result = mDelegate.LookupRootCertByFingerprint(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(), - req.fingerprint, [&](auto & certificate) -> CHIP_ERROR { - LookupRootCertificateResponse::Type response; - response.caid = certificate.caid; - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); - return CHIP_NO_ERROR; - }); - if (result == CHIP_ERROR_NOT_FOUND) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); - } - else if (result != CHIP_NO_ERROR) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); - } -} - -void TlsCertificateManagementServer::HandleRemoveRootCertificate(HandlerContext & ctx, - const RemoveRootCertificate::DecodableType & req) -{ - ChipLogDetail(Zcl, "TlsCertificateManagement: RemoveRootCertificate"); - - VerifyOrReturn(req.caid <= kMaxRootCertId, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); - - ReturnOnFailure(mDependencyChecker.RootCertCanBeRemoved(ctx.mRequestPath.mEndpointId, - ctx.mCommandHandler.GetAccessingFabricIndex(), req.caid), - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidInState)); - - auto result = mDelegate.RemoveRootCert(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(), req.caid); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, result); -} - -void TlsCertificateManagementServer::HandleGenerateClientCsr(HandlerContext & ctx, const ClientCSR::DecodableType & req) -{ - ChipLogDetail(Zcl, "TlsCertificateManagement: ClientCSR"); - - VerifyOrReturn(req.nonce.size() == kNonceBytes, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); - - auto fabric = ctx.mCommandHandler.GetAccessingFabricIndex(); - uint8_t numClientCerts; - VerifyOrReturn(mCertificateTable.GetClientCertificateCount(fabric, numClientCerts) == CHIP_NO_ERROR, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure)); - VerifyOrReturn(numClientCerts < mMaxClientCertificates, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ResourceExhausted)); - - auto status = mDelegate.GenerateClientCsr(ctx.mRequestPath.mEndpointId, fabric, req, [&](auto & response) -> Status { - VerifyOrDieWithMsg(response.ccdid <= kMaxClientCertId, NotSpecified, "Spec requires CCDID to be <= kMaxClientCertId"); - VerifyOrDieWithMsg(response.csr.size() <= 3000, NotSpecified, "Spec requires csr.size() to be <= 3000"); - VerifyOrDieWithMsg(response.nonceSignature.size() <= kMaxSignatureBytes, NotSpecified, - "Spec requires nonceSignature.size() to be < kMaxSignatureBytes"); - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); - return Status::Success; - }); - - if (status != Status::Success) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); - } -} - -void TlsCertificateManagementServer::HandleProvisionClientCertificate(HandlerContext & ctx, - const ProvisionClientCertificate::DecodableType & req) -{ - ChipLogDetail(Zcl, "TlsCertificateManagement: ProvisionClientCertificate"); - - VerifyOrReturn(req.ccdid <= kMaxClientCertId, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); - VerifyOrReturn(req.clientCertificate.size() <= kSpecMaxCertBytes, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); - ReturnOnFailure(Crypto::IsCertificateValidAtCurrentTime(req.clientCertificate), - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::DynamicConstraintError)); - size_t intermediateSize; - ReturnOnFailure(req.intermediateCertificates.ComputeSize(&intermediateSize), - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand)); - VerifyOrReturn(intermediateSize <= kMaxIntermediateCertificates, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); - auto srcIter = req.intermediateCertificates.begin(); - while (srcIter.Next()) - { - auto & cert = srcIter.GetValue(); - VerifyOrReturn(cert.size() <= kSpecMaxCertBytes, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); - - ReturnOnFailure(Crypto::IsCertificateValidAtCurrentTime(cert), - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::DynamicConstraintError)); - } - ReturnOnFailure(srcIter.GetStatus(), ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidAction)); - - auto fabric = ctx.mCommandHandler.GetAccessingFabricIndex(); - DataModel::Nullable foundId; - auto lookupResult = mDelegate.LookupClientCert(ctx.mRequestPath.mEndpointId, fabric, req.clientCertificate, - [&](auto & certificate) -> CHIP_ERROR { - foundId = certificate.ccdid; - return CHIP_NO_ERROR; - }); - if (lookupResult != CHIP_ERROR_NOT_FOUND) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::AlreadyExists); - return; - } - - ReturnOnFailure(mCertificateTable.HasClientCertificateEntry(fabric, req.ccdid), - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound)); - - auto status = mDelegate.ProvisionClientCert(ctx.mRequestPath.mEndpointId, fabric, req); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); -} - -void TlsCertificateManagementServer::HandleFindClientCertificate(HandlerContext & ctx, - const FindClientCertificate::DecodableType & req) -{ - ChipLogDetail(Zcl, "TlsCertificateManagement: FindClientCertificate"); - CHIP_ERROR result; - if (req.ccdid.IsNull()) - { - result = mDelegate.ClientCertsForFabric(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(), - [&](auto & certs) -> CHIP_ERROR { - if (certs.size() == 0) - { - return CHIP_ERROR_NOT_FOUND; - } - FindClientCertificateResponse::Type response; - response.certificateDetails = certs; - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); - return CHIP_NO_ERROR; - }); - } - else - { - VerifyOrReturn(req.ccdid.Value() <= kMaxRootCertId, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); - - result = - mDelegate.FindClientCert(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(), req.ccdid.Value(), - [&](auto & certificate) -> CHIP_ERROR { - FindClientCertificateResponse::Type response; - DataModel::List details(&certificate, 1); - response.certificateDetails = details; - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); - return CHIP_NO_ERROR; - }); - } - if (result == CHIP_ERROR_NOT_FOUND) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); - } - else if (result != CHIP_NO_ERROR) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); - } -} - -void TlsCertificateManagementServer::HandleLookupClientCertificate(HandlerContext & ctx, - const LookupClientCertificate::DecodableType & req) -{ - ChipLogDetail(Zcl, "TlsCertificateManagement: LookupClientCertificate"); - - VerifyOrReturn(req.fingerprint.size() <= kSpecMaxFingerprintBytes, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); - - auto result = - mDelegate.LookupClientCertByFingerprint(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(), - req.fingerprint, [&](auto & certificate) -> CHIP_ERROR { - LookupClientCertificateResponse::Type response; - response.ccdid = certificate.ccdid; - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); - return CHIP_NO_ERROR; - }); - if (result == CHIP_ERROR_NOT_FOUND) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); - } - else if (result != CHIP_NO_ERROR) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); - } -} - -void TlsCertificateManagementServer::HandleRemoveClientCertificate(HandlerContext & ctx, - const RemoveClientCertificate::DecodableType & req) -{ - ChipLogDetail(Zcl, "TlsCertificateManagement: RemoveClientCertificate"); - - VerifyOrReturn(req.ccdid <= kMaxClientCertId, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); - - ReturnOnFailure(mDependencyChecker.ClientCertCanBeRemoved(ctx.mRequestPath.mEndpointId, - ctx.mCommandHandler.GetAccessingFabricIndex(), req.ccdid), - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidInState)); - - auto result = - mDelegate.RemoveClientCert(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(), req.ccdid); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, result); -} - -void TlsCertificateManagementServer::OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) -{ - ReturnAndLogOnFailure(mCertificateTable.RemoveFabric(fabricIndex), Zcl, "Failed to remove TLS certificate data for fabric 0x%x", - fabricIndex); -} - -/** @brief TlsCertificateManagement Cluster Server Init - * - * Server Init - * - */ -void MatterTlsCertificateManagementPluginServerInitCallback() {} diff --git a/src/app/clusters/tls-client-management-server/BUILD.gn b/src/app/clusters/tls-client-management-server/BUILD.gn index 357180e9415..0ad4532561a 100644 --- a/src/app/clusters/tls-client-management-server/BUILD.gn +++ b/src/app/clusters/tls-client-management-server/BUILD.gn @@ -14,7 +14,10 @@ import("//build_overrides/chip.gni") source_set("tls-client-management-server") { - sources = [ "tls-client-management-server.h" ] + sources = [ + "TLSClientManagementCluster.cpp", + "TLSClientManagementCluster.h", + ] public_deps = [ "${chip_root}/src/app/", diff --git a/src/app/clusters/tls-client-management-server/CodegenIntegration.cpp b/src/app/clusters/tls-client-management-server/CodegenIntegration.cpp new file mode 100644 index 00000000000..380d6e6bff3 --- /dev/null +++ b/src/app/clusters/tls-client-management-server/CodegenIntegration.cpp @@ -0,0 +1,115 @@ +/* + * + * Copyright (c) 2025 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 "CodegenIntegration.h" + +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::Tls; +using namespace chip::app::DataModel; + +namespace { + +CertificateTableImpl gDefaultCertificateTable; + +TLSClientManagementDelegate * gDelegate = nullptr; +CertificateTableImpl * gCertificateTable = &gDefaultCertificateTable; +constexpr uint8_t kDefaultMaxProvisionedEndpoints = CHIP_CONFIG_TLS_MAX_PROVISIONED_ENDPOINTS; + +LazyRegisteredServerCluster gClusterInstance; + +} // anonymous namespace + +namespace chip { +namespace app { +namespace Clusters { + +void MatterTlsClientManagementSetDelegate(TLSClientManagementDelegate & delegate) +{ + gDelegate = &delegate; +} + +void MatterTlsClientManagementSetCertificateTable(Tls::CertificateTableImpl & certificateTable) +{ + gCertificateTable = &certificateTable; +} + +} // namespace Clusters +} // namespace app +} // namespace chip + +void MatterTlsClientManagementPluginServerInitCallback() +{ + ChipLogProgress(Zcl, "Initializing TLS Client Management cluster."); +} + +void MatterTlsClientManagementClusterInitCallback(EndpointId endpointId) +{ + // TODO:(#42638) This cluster SHALL be present on the root node endpoint (endpoint 0) when required, and SHALL NOT be present on + // any other endpoint. if (endpointId != kRootEndpointId) + // { + // ChipLogError(Zcl, + // "TLS Client Management Cluster can only be initialized on root endpoint (0). " + // "Ignoring initialization on endpoint %u.", + // endpointId); + // return; + // } + + // Only create once - avoid double initialization if callback is called multiple times + if (gClusterInstance.IsConstructed()) + { + ChipLogError(Zcl, "TLS Client Management Cluster already initialized on endpoint 0. Ignoring duplicate initialization."); + return; + } + + // Require a proper delegate - the cluster cannot function without one + if (gDelegate == nullptr) + { + ChipLogError(Zcl, + "TLS Client Management Cluster cannot be initialized without a delegate. " + "Call MatterTlsClientManagementSetDelegate() before ServerInit()."); + return; + } + + LogErrorOnFailure(gCertificateTable->SetEndpoint(endpointId)); + + gClusterInstance.Create(endpointId, *gDelegate, *gCertificateTable, kDefaultMaxProvisionedEndpoints); + CHIP_ERROR err = CodegenDataModelProvider::Instance().Registry().Register(gClusterInstance.Registration()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to register TLS Client Management Cluster on endpoint %u: %" CHIP_ERROR_FORMAT, endpointId, + err.Format()); + } +} + +void MatterTlsClientManagementClusterShutdownCallback(EndpointId endpointId) +{ + VerifyOrReturn(gClusterInstance.IsConstructed()); + VerifyOrReturn(gClusterInstance.Cluster().GetEndpointId() == endpointId); + + LogErrorOnFailure(CodegenDataModelProvider::Instance().Registry().Unregister(&gClusterInstance.Cluster())); + gClusterInstance.Destroy(); +} diff --git a/src/app/clusters/tls-client-management-server/CodegenIntegration.h b/src/app/clusters/tls-client-management-server/CodegenIntegration.h new file mode 100644 index 00000000000..c2b80c8439a --- /dev/null +++ b/src/app/clusters/tls-client-management-server/CodegenIntegration.h @@ -0,0 +1,57 @@ +/* + * + * Copyright (c) 2025 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 + +namespace chip { +namespace app { +namespace Clusters { + +/** + * Set the delegate for the TLS Client Management cluster. + * + * MUST be called before Matter data model initialization (e.g. in main() before ServerInit()). + * The delegate is used during cluster initialization. + * If called after cluster initialization, it will have no effect as the cluster instance + * has already been created with the previous delegate. + * + * If not called before initialization, the cluster will NOT be initialized. + * + * @param delegate The delegate to be used by the TLS Client Management cluster. + */ +void MatterTlsClientManagementSetDelegate(TLSClientManagementDelegate & delegate); + +/** + * Set the certificate table for the TLS Client Management cluster. + * + * MUST be called before Matter data model initialization (e.g. in main() before ServerInit()). + * The certificate table is used during cluster initialization via MatterTLSClientManagementClusterInitCallback. + * If called after cluster initialization, it will have no effect as the cluster instance + * has already been created with the previous certificate table. + * + * If not called before initialization, a default certificate table will be used. + * + * @param certificateTable The certificate table to be used by the TLS Client Management cluster. + */ +void MatterTlsClientManagementSetCertificateTable(Tls::CertificateTableImpl & certificateTable); + +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/tls-client-management-server/TLSClientManagementCluster.cpp b/src/app/clusters/tls-client-management-server/TLSClientManagementCluster.cpp new file mode 100644 index 00000000000..8606311f099 --- /dev/null +++ b/src/app/clusters/tls-client-management-server/TLSClientManagementCluster.cpp @@ -0,0 +1,275 @@ +/* + * + * Copyright (c) 2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/****************************************************************************' + * @file + * @brief Implementation for the TlsClientManagement Server Cluster + ***************************************************************************/ + +#include "TLSClientManagementCluster.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::Tls; +using namespace chip::app::Clusters::TlsClientManagement; +using namespace chip::app::Clusters::TlsClientManagement::Structs; +using namespace chip::app::Clusters::TlsClientManagement::Attributes; +using namespace Protocols::InteractionModel; + +static constexpr uint16_t kMaxTlsEndpointId = 65534; +// Minimum hostname length of 4 allows for shortest valid format: single char + dot + 2-letter TLD (e.g., "a.bc") +static constexpr size_t kMinHostnameLength = 4; + +constexpr DataModel::AcceptedCommandEntry kAcceptedCommands[] = { + Commands::ProvisionEndpoint::kMetadataEntry, + Commands::FindEndpoint::kMetadataEntry, + Commands::RemoveEndpoint::kMetadataEntry, +}; + +TLSClientManagementCluster::TLSClientManagementCluster(EndpointId endpointId, TLSClientManagementDelegate & delegate, + CertificateTable & certificateTable, uint8_t maxProvisioned) : + DefaultServerCluster({ endpointId, TlsClientManagement::Id }), + mDelegate(delegate), mCertificateTable(certificateTable), mMaxProvisioned(maxProvisioned) +{ + VerifyOrDieWithMsg(mMaxProvisioned >= 5, NotSpecified, "Spec requires MaxProvisioned be >= 5"); + VerifyOrDieWithMsg(mMaxProvisioned <= 254, NotSpecified, "Spec requires MaxProvisioned be <= 254"); + mDelegate.SetTLSClientManagementCluster(this); +} + +TLSClientManagementCluster::~TLSClientManagementCluster() +{ + // null out the ref to us on the delegate + mDelegate.SetTLSClientManagementCluster(nullptr); +} + +CHIP_ERROR TLSClientManagementCluster::Startup(ServerClusterContext & context) +{ + ChipLogProgress(DataManagement, "TLSClientManagementCluster: initializing"); + ReturnErrorOnFailure(DefaultServerCluster::Startup(context)); + + ReturnErrorOnFailure(mCertificateTable.Init(context.storage)); + ReturnErrorOnFailure(mDelegate.Init(context.storage)); + + return Server::GetInstance().GetFabricTable().AddFabricDelegate(this); +} + +void TLSClientManagementCluster::Shutdown() +{ + ChipLogProgress(DataManagement, "TLSClientManagementCluster: shutdown"); + + mCertificateTable.Finish(); + Server::GetInstance().GetFabricTable().RemoveFabricDelegate(this); + + DefaultServerCluster::Shutdown(); +} + +DataModel::ActionReturnStatus TLSClientManagementCluster::ReadAttribute(const DataModel::ReadAttributeRequest & request, + AttributeValueEncoder & encoder) +{ + switch (request.path.mAttributeId) + { + case MaxProvisioned::Id: + return encoder.Encode(mMaxProvisioned); + case ProvisionedEndpoints::Id: { + TLSClientManagementCluster * server = this; + auto matterEndpoint = request.path.mEndpointId; + auto fabric = request.GetAccessingFabricIndex(); + return encoder.EncodeList([server, matterEndpoint, fabric](const auto & listEncoder) -> CHIP_ERROR { + return server->EncodeProvisionedEndpoints(matterEndpoint, fabric, listEncoder); + }); + } + case ClusterRevision::Id: + return encoder.Encode(kRevision); + case FeatureMap::Id: + // TODO: Allow delegate to specify supported features + // Currently hardcoded to 0 (no features supported) + // METADATA feature (bit 0) should be configurable based on delegate capabilities + return encoder.Encode(0); + default: + return Status::UnsupportedAttribute; + } +} + +CHIP_ERROR TLSClientManagementCluster::Attributes(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) +{ + AttributeListBuilder listBuilder(builder); + // TlsClientManagement does not have optional attributes implemented yet, + // so we just return mandatory ones. + return listBuilder.Append(Span(kMandatoryMetadata), {}); +} + +CHIP_ERROR TLSClientManagementCluster::AcceptedCommands(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) +{ + return builder.ReferenceExisting(kAcceptedCommands); +} + +uint8_t TLSClientManagementCluster::GetMaxProvisioned() const +{ + return mMaxProvisioned; +} + +// helper method to get the TlsClientManagement provisioned endpoints encoded into a list +CHIP_ERROR +TLSClientManagementCluster::EncodeProvisionedEndpoints(EndpointId matterEndpoint, FabricIndex fabric, + const AttributeValueEncoder::ListEncodeHelper & encoder) +{ + return mDelegate.ForEachEndpoint(matterEndpoint, fabric, + [&](auto & endpoint) -> CHIP_ERROR { return encoder.Encode(endpoint); }); +} + +std::optional TLSClientManagementCluster::InvokeCommand(const DataModel::InvokeRequest & request, + chip::TLV::TLVReader & input_arguments, + CommandHandler * handler) +{ + FabricIndex accessingFabricIndex = request.GetAccessingFabricIndex(); + + switch (request.path.mCommandId) + { + case Commands::ProvisionEndpoint::Id: { + Commands::ProvisionEndpoint::DecodableType req; + ReturnErrorOnFailure(req.Decode(input_arguments, accessingFabricIndex)); + return HandleProvisionEndpoint(*handler, req); + } + case Commands::FindEndpoint::Id: { + Commands::FindEndpoint::DecodableType req; + ReturnErrorOnFailure(req.Decode(input_arguments, accessingFabricIndex)); + return HandleFindEndpoint(*handler, req); + } + case Commands::RemoveEndpoint::Id: { + Commands::RemoveEndpoint::DecodableType req; + ReturnErrorOnFailure(req.Decode(input_arguments, accessingFabricIndex)); + return HandleRemoveEndpoint(*handler, req); + } + default: + return Status::UnsupportedCommand; + } +} + +std::optional +TLSClientManagementCluster::HandleProvisionEndpoint(CommandHandler & commandHandler, + const Commands::ProvisionEndpoint::DecodableType & req) +{ + ChipLogDetail(Zcl, "TlsClientManagement: ProvisionEndpoint"); + + if (req.hostname.size() < kMinHostnameLength || req.hostname.size() > kSpecMaxHostname) + { + return Status::ConstraintError; + } + + if (req.caid > kMaxRootCertId) + { + return Status::ConstraintError; + } + + auto fabric = commandHandler.GetAccessingFabricIndex(); + if (mCertificateTable.HasRootCertificateEntry(fabric, req.caid) != CHIP_NO_ERROR) + { + return ClusterStatusCode::ClusterSpecificFailure(StatusCodeEnum::kRootCertificateNotFound); + } + if (!req.ccdid.IsNull() && mCertificateTable.HasClientCertificateEntry(fabric, req.ccdid.Value()) != CHIP_NO_ERROR) + { + return ClusterStatusCode::ClusterSpecificFailure(StatusCodeEnum::kClientCertificateNotFound); + } + + Commands::ProvisionEndpointResponse::Type response; + auto status = mDelegate.ProvisionEndpoint(mPath.mEndpointId, fabric, req, response.endpointID); + + if (status.IsSuccess()) + { + ConcreteCommandPath requestPath(mPath.mEndpointId, TlsClientManagement::Id, Commands::ProvisionEndpoint::Id); + commandHandler.AddResponse(requestPath, response); + NotifyAttributeChanged(TlsClientManagement::Attributes::ProvisionedEndpoints::Id); + return std::nullopt; + } + + return status; +} + +std::optional +TLSClientManagementCluster::HandleFindEndpoint(CommandHandler & commandHandler, const Commands::FindEndpoint::DecodableType & req) +{ + ChipLogDetail(Zcl, "TlsClientManagement: FindEndpoint"); + + VerifyOrReturnError(req.endpointID <= kMaxTlsEndpointId, Status::ConstraintError); + + auto fabric = commandHandler.GetAccessingFabricIndex(); + auto endpointId = mPath.mEndpointId; + + CHIP_ERROR result = + mDelegate.FindProvisionedEndpointByID(endpointId, fabric, req.endpointID, [&](auto & endpoint) -> CHIP_ERROR { + Commands::FindEndpointResponse::Type response; + response.endpoint = endpoint; + ConcreteCommandPath requestPath(mPath.mEndpointId, TlsClientManagement::Id, Commands::FindEndpoint::Id); + commandHandler.AddResponse(requestPath, response); + return CHIP_NO_ERROR; + }); + + if (result == CHIP_ERROR_NOT_FOUND) + { + return Status::NotFound; + } + + if (result != CHIP_NO_ERROR) + { + return Status::Failure; + } + + return std::nullopt; +} + +std::optional +TLSClientManagementCluster::HandleRemoveEndpoint(CommandHandler & commandHandler, + const Commands::RemoveEndpoint::DecodableType & req) +{ + ChipLogDetail(Zcl, "TlsClientManagement: RemoveEndpoint"); + + if (req.endpointID > kMaxTlsEndpointId) + { + return Status::ConstraintError; + } + + auto fabric = commandHandler.GetAccessingFabricIndex(); + auto endpointId = mPath.mEndpointId; + + auto status = mDelegate.RemoveProvisionedEndpointByID(endpointId, fabric, req.endpointID); + + if (status == Status::Success) + { + NotifyAttributeChanged(TlsClientManagement::Attributes::ProvisionedEndpoints::Id); + } + + return status; +} + +void TLSClientManagementCluster::OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) +{ + TEMPORARY_RETURN_IGNORED mDelegate.RemoveFabric(fabricIndex); +} diff --git a/src/app/clusters/tls-client-management-server/tls-client-management-server.h b/src/app/clusters/tls-client-management-server/TLSClientManagementCluster.h similarity index 68% rename from src/app/clusters/tls-client-management-server/tls-client-management-server.h rename to src/app/clusters/tls-client-management-server/TLSClientManagementCluster.h index 95c5606879d..32084122833 100644 --- a/src/app/clusters/tls-client-management-server/tls-client-management-server.h +++ b/src/app/clusters/tls-client-management-server/TLSClientManagementCluster.h @@ -18,12 +18,12 @@ #pragma once -#include -#include -#include #include +#include #include +#include #include +#include #include #include #include @@ -33,65 +33,64 @@ namespace app { namespace Clusters { static constexpr uint16_t kSpecMaxHostname = 253; -class TlsClientManagementDelegate; +class TLSClientManagementDelegate; -class TlsClientManagementServer : private AttributeAccessInterface, - private CommandHandlerInterface, - private chip::FabricTable::Delegate +class TLSClientManagementCluster : public DefaultServerCluster, private chip::FabricTable::Delegate { public: /** - * Creates a TLSClientManagement server instance. The Init() function needs to be called for this instance to be registered and - * called by the interaction model at the appropriate times. + * Creates a TLSClientManagement server instance. * @param endpointId The endpoint on which this cluster exists. This must match the zap configuration. * @param delegate A reference to the delegate to be used by this server. - * @param certificateTable A reference to the certificate table for looking up certiciates + * @param certificateTable A reference to the certificate table for looking up certificates * @param maxProvisioned The maximum number of endpoints which can be provisioned * Note: the caller must ensure that the delegate lives throughout the instance's lifetime. */ - TlsClientManagementServer(EndpointId endpointId, TlsClientManagementDelegate & delegate, - Tls::CertificateTable & certificateTable, uint8_t maxProvisioned); - ~TlsClientManagementServer(); - - /** - * Initialise the TLS Client Management server instance. - * @return Returns an error if the CommandHandler or AttributeHandler registration fails. - */ - CHIP_ERROR Init(); - - /** - * Shuts down the TLS Client Management server instance. - * @return Returns an error if the destruction fails. - */ - CHIP_ERROR Finish(); + TLSClientManagementCluster(EndpointId endpointId, TLSClientManagementDelegate & delegate, + Tls::CertificateTable & certificateTable, uint8_t maxProvisioned); + ~TLSClientManagementCluster(); // Attribute Getters - /** - * @return The MaxProvisioned attribute. - */ uint8_t GetMaxProvisioned() const; + EndpointId GetEndpointId() const { return mPath.mEndpointId; } + /** - * @return The endpoint ID. + * @brief ServerClusterInterface methods. */ - EndpointId GetEndpointId() { return AttributeAccessInterface::GetEndpointId().Value(); } + CHIP_ERROR Startup(ServerClusterContext & context) override; + void Shutdown() override; + + CHIP_ERROR Attributes(const ConcreteClusterPath & path, ReadOnlyBufferBuilder & builder) override; + + CHIP_ERROR AcceptedCommands(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) override; + + DataModel::ActionReturnStatus ReadAttribute(const DataModel::ReadAttributeRequest & request, + AttributeValueEncoder & encoder) override; + + std::optional InvokeCommand(const DataModel::InvokeRequest & request, + chip::TLV::TLVReader & input_arguments, + CommandHandler * handler) override; private: - TlsClientManagementDelegate & mDelegate; + TLSClientManagementDelegate & mDelegate; Tls::CertificateTable & mCertificateTable; // Attribute local storage uint8_t mMaxProvisioned; - // AttributeAccessInterface - CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; + // Command handlers + std::optional + HandleProvisionEndpoint(CommandHandler & commandHandler, + const TlsClientManagement::Commands::ProvisionEndpoint::DecodableType & req); + + std::optional + HandleFindEndpoint(CommandHandler & commandHandler, const TlsClientManagement::Commands::FindEndpoint::DecodableType & req); - // CommandHandlerInterface - void InvokeCommand(HandlerContext & ctx) override; - void HandleProvisionEndpoint(HandlerContext & ctx, const TlsClientManagement::Commands::ProvisionEndpoint::DecodableType & req); - void HandleFindEndpoint(HandlerContext & ctx, const TlsClientManagement::Commands::FindEndpoint::DecodableType & req); - void HandleRemoveEndpoint(HandlerContext & ctx, const TlsClientManagement::Commands::RemoveEndpoint::DecodableType & req); + std::optional + HandleRemoveEndpoint(CommandHandler & commandHandler, const TlsClientManagement::Commands::RemoveEndpoint::DecodableType & req); // Encodes all provisioned endpoints CHIP_ERROR EncodeProvisionedEndpoints(EndpointId matterEndpoint, FabricIndex fabric, @@ -103,15 +102,15 @@ class TlsClientManagementServer : private AttributeAccessInterface, /** @brief * Defines methods for implementing application-specific logic for the TLSClientManagement Cluster. */ -class TlsClientManagementDelegate : public Tls::CertificateDependencyChecker +class TLSClientManagementDelegate : public Tls::CertificateDependencyChecker { public: using EndpointStructType = TlsClientManagement::Structs::TLSEndpointStruct::DecodableType; using LoadedEndpointCallback = std::function; - TlsClientManagementDelegate() = default; + TLSClientManagementDelegate() = default; - virtual ~TlsClientManagementDelegate() = default; + virtual ~TLSClientManagementDelegate() = default; virtual CHIP_ERROR Init(PersistentStorageDelegate & storage) = 0; @@ -184,16 +183,16 @@ class TlsClientManagementDelegate : public Tls::CertificateDependencyChecker int8_t delta) = 0; protected: - friend class TlsClientManagementServer; + friend class TLSClientManagementCluster; - TlsClientManagementServer * mTlsClientManagementServer = nullptr; + TLSClientManagementCluster * mTLSClientManagementCluster = nullptr; - // sets the TlsClientManagement Server pointer - void SetTlsClientManagementServer(TlsClientManagementServer * tlsClientManagementServer) + // sets the TlsClientManagement Cluster pointer + void SetTLSClientManagementCluster(TLSClientManagementCluster * tlsClientManagementServer) { - mTlsClientManagementServer = tlsClientManagementServer; + mTLSClientManagementCluster = tlsClientManagementServer; } - TlsClientManagementServer * GetTlsClientManagementServer() const { return mTlsClientManagementServer; } + TLSClientManagementCluster * GetTLSClientManagementCluster() const { return mTLSClientManagementCluster; } }; } // namespace Clusters diff --git a/src/app/clusters/tls-client-management-server/app_config_dependent_sources.cmake b/src/app/clusters/tls-client-management-server/app_config_dependent_sources.cmake index 5d8e991a41f..0bd5f5b6857 100644 --- a/src/app/clusters/tls-client-management-server/app_config_dependent_sources.cmake +++ b/src/app/clusters/tls-client-management-server/app_config_dependent_sources.cmake @@ -18,6 +18,7 @@ TARGET_SOURCES( PRIVATE "${CHIP_APP_BASE_DIR}/clusters/tls-certificate-management-server/CertificateTableImpl.cpp" "${CHIP_APP_BASE_DIR}/clusters/tls-certificate-management-server/CertificateTableImpl.h" - "${CLUSTER_DIR}/tls-client-management-server.cpp" - "${CLUSTER_DIR}/tls-client-management-server.h" + "${CLUSTER_DIR}/CodegenIntegration.cpp" + "${CLUSTER_DIR}/TLSClientManagementCluster.cpp" + "${CLUSTER_DIR}/TLSClientManagementCluster.h" ) \ No newline at end of file diff --git a/src/app/clusters/tls-client-management-server/app_config_dependent_sources.gni b/src/app/clusters/tls-client-management-server/app_config_dependent_sources.gni index 19d4e0d33ef..be7224f0bbc 100644 --- a/src/app/clusters/tls-client-management-server/app_config_dependent_sources.gni +++ b/src/app/clusters/tls-client-management-server/app_config_dependent_sources.gni @@ -11,9 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import("//build_overrides/chip.gni") - app_config_dependent_sources = [ - "tls-client-management-server.cpp", - "tls-client-management-server.h", + "CodegenIntegration.cpp", + "CodegenIntegration.h", ] diff --git a/src/app/clusters/tls-client-management-server/tests/BUILD.gn b/src/app/clusters/tls-client-management-server/tests/BUILD.gn new file mode 100644 index 00000000000..bc592be77ef --- /dev/null +++ b/src/app/clusters/tls-client-management-server/tests/BUILD.gn @@ -0,0 +1,34 @@ +# Copyright (c) 2025 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +import("${chip_root}/build/chip/chip_test_suite.gni") + +chip_test_suite("tests") { + output_name = "libTestTLSClientManagementCluster" + + test_sources = [ "TestTLSClientManagementCluster.cpp" ] + + cflags = [ "-Wconversion" ] + + public_deps = [ + "${chip_root}/src/app/clusters/tls-certificate-management-server", + "${chip_root}/src/app/clusters/tls-client-management-server", + "${chip_root}/src/app/data-model-provider/tests:encode-decode", + "${chip_root}/src/app/server-cluster/testing:testing", + "${chip_root}/src/lib/support", + ] +} diff --git a/src/app/clusters/tls-client-management-server/tests/TestTLSClientManagementCluster.cpp b/src/app/clusters/tls-client-management-server/tests/TestTLSClientManagementCluster.cpp new file mode 100644 index 00000000000..e8bd7f25c04 --- /dev/null +++ b/src/app/clusters/tls-client-management-server/tests/TestTLSClientManagementCluster.cpp @@ -0,0 +1,562 @@ +/* + * Copyright (c) 2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::Tls; +using namespace chip::app::Clusters::TlsClientManagement; +using namespace chip::Testing; + +namespace { + +constexpr EndpointId kTestEndpointId = 1; +constexpr uint8_t kMaxProvisioned = 10; + +// Mock implementations +class MockCertificateTable : public CertificateTable +{ +public: + struct MockRootCert + { + FabricIndex fabric; + TLSCAID caid; + }; + + struct MockClientCert + { + FabricIndex fabric; + TLSCCDID ccdid; + }; + + std::vector rootCerts; + std::vector clientCerts; + + CHIP_ERROR Init(PersistentStorageDelegate & storage) override { return CHIP_NO_ERROR; } + + void Finish() override {} + + CHIP_ERROR UpsertRootCertificateEntry(FabricIndex fabric_index, Optional & id, RootBuffer & buffer, + const ByteSpan & certificate) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetRootCertificateEntry(FabricIndex fabric_index, TLSCAID id, BufferedRootCert & entry) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR HasRootCertificateEntry(FabricIndex fabric_index, TLSCAID id) override + { + for (const auto & cert : rootCerts) + { + if (cert.fabric == fabric_index && cert.caid == id) + { + return CHIP_NO_ERROR; + } + } + return CHIP_ERROR_NOT_FOUND; + } + + CHIP_ERROR IterateRootCertificates(FabricIndex fabric, BufferedRootCert & store, IterateRootCertFnType iterateFn) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetClientCertificateEntry(FabricIndex fabric_index, TLSCCDID id, BufferedClientCert & entry) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR HasClientCertificateEntry(FabricIndex fabric_index, TLSCCDID id) override + { + for (const auto & cert : clientCerts) + { + if (cert.fabric == fabric_index && cert.ccdid == id) + { + return CHIP_NO_ERROR; + } + } + return CHIP_ERROR_NOT_FOUND; + } + + CHIP_ERROR IterateClientCertificates(FabricIndex fabric, BufferedClientCert & store, IterateClientCertFnType iterateFn) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR RemoveRootCertificate(FabricIndex fabric_index, TLSCAID id) override { return CHIP_NO_ERROR; } + + CHIP_ERROR GetRootCertificateCount(FabricIndex fabric, uint8_t & outCount) override + { + outCount = 0; + return CHIP_NO_ERROR; + } + + CHIP_ERROR PrepareClientCertificate(FabricIndex fabric, const ByteSpan & nonce, ClientBuffer & buffer, Optional & id, + MutableByteSpan & csr, MutableByteSpan & nonceSignature) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR UpdateClientCertificateEntry(FabricIndex fabric_index, TLSCCDID id, ClientBuffer & buffer, + const ClientCertStruct & entry) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR RemoveClientCertificate(FabricIndex fabric_index, TLSCCDID id) override { return CHIP_NO_ERROR; } + + CHIP_ERROR GetClientCertificateCount(FabricIndex fabric, uint8_t & outCount) override + { + outCount = 0; + return CHIP_NO_ERROR; + } + + CHIP_ERROR RemoveFabric(FabricIndex fabricIndex) override { return CHIP_NO_ERROR; } +}; + +class MockTLSClientManagementDelegate : public TLSClientManagementDelegate +{ +public: + struct MockEndpoint + { + EndpointId matterEndpoint; + FabricIndex fabric; + uint16_t endpointID; + std::string hostname; + TLSCAID caid; + DataModel::Nullable ccdid; + }; + + std::vector endpoints; + uint16_t nextEndpointID = 1; + + CHIP_ERROR provisionError = CHIP_NO_ERROR; + Protocols::InteractionModel::ClusterStatusCode provisionStatus = + Protocols::InteractionModel::ClusterStatusCode(Protocols::InteractionModel::Status::Success); + Protocols::InteractionModel::Status removeStatus = Protocols::InteractionModel::Status::Success; + CHIP_ERROR mutateReferenceCountError = CHIP_NO_ERROR; + + CHIP_ERROR Init(PersistentStorageDelegate & storage) override { return CHIP_NO_ERROR; } + + CHIP_ERROR ForEachEndpoint(EndpointId matterEndpoint, FabricIndex fabric, LoadedEndpointCallback callback) override + { + for (auto & endpoint : endpoints) + { + if (endpoint.matterEndpoint == matterEndpoint && endpoint.fabric == fabric) + { + Structs::TLSEndpointStruct::Type decodable; + decodable.endpointID = endpoint.endpointID; + decodable.hostname = + ByteSpan(reinterpret_cast(endpoint.hostname.c_str()), endpoint.hostname.size()); + decodable.caid = endpoint.caid; + decodable.ccdid = endpoint.ccdid; + ReturnErrorOnFailure(callback(decodable)); + } + } + return CHIP_NO_ERROR; + } + + CHIP_ERROR FindProvisionedEndpointByID(EndpointId matterEndpoint, FabricIndex fabric, uint16_t endpointID, + LoadedEndpointCallback callback) override + { + for (auto & endpoint : endpoints) + { + if (endpoint.matterEndpoint == matterEndpoint && endpoint.fabric == fabric && endpoint.endpointID == endpointID) + { + Structs::TLSEndpointStruct::Type decodable; + decodable.endpointID = endpoint.endpointID; + decodable.hostname = + ByteSpan(reinterpret_cast(endpoint.hostname.c_str()), endpoint.hostname.size()); + decodable.caid = endpoint.caid; + decodable.ccdid = endpoint.ccdid; + return callback(decodable); + } + } + return CHIP_ERROR_NOT_FOUND; + } + + Protocols::InteractionModel::ClusterStatusCode + ProvisionEndpoint(EndpointId matterEndpoint, FabricIndex fabric, + const Commands::ProvisionEndpoint::DecodableType & provisionReq, uint16_t & endpointID) override + { + if (provisionError != CHIP_NO_ERROR) + { + return Protocols::InteractionModel::ClusterStatusCode::ClusterSpecificFailure(StatusCodeEnum::kRootCertificateNotFound); + } + + if (!provisionStatus.IsSuccess()) + { + return provisionStatus; + } + + // Store hostname data + std::string hostname(reinterpret_cast(provisionReq.hostname.data()), provisionReq.hostname.size()); + + endpointID = nextEndpointID++; + endpoints.push_back({ matterEndpoint, fabric, endpointID, hostname, provisionReq.caid, provisionReq.ccdid }); + + return Protocols::InteractionModel::ClusterStatusCode(Protocols::InteractionModel::Status::Success); + } + + Protocols::InteractionModel::Status RemoveProvisionedEndpointByID(EndpointId matterEndpoint, FabricIndex fabric, + uint16_t endpointID) override + { + for (auto it = endpoints.begin(); it != endpoints.end(); ++it) + { + if (it->matterEndpoint == matterEndpoint && it->fabric == fabric && it->endpointID == endpointID) + { + endpoints.erase(it); + return removeStatus; + } + } + return Protocols::InteractionModel::Status::NotFound; + } + + void RemoveFabric(FabricIndex fabricIndex) override + { + endpoints.erase(std::remove_if(endpoints.begin(), endpoints.end(), + [fabricIndex](const MockEndpoint & ep) { return ep.fabric == fabricIndex; }), + endpoints.end()); + } + + CHIP_ERROR MutateEndpointReferenceCount(EndpointId matterEndpoint, FabricIndex fabric, uint16_t endpointID, + int8_t delta) override + { + if (mutateReferenceCountError != CHIP_NO_ERROR) + { + return mutateReferenceCountError; + } + + for (auto & endpoint : endpoints) + { + if (endpoint.matterEndpoint == matterEndpoint && endpoint.fabric == fabric && endpoint.endpointID == endpointID) + { + return CHIP_NO_ERROR; + } + } + return CHIP_ERROR_NOT_FOUND; + } + + CHIP_ERROR RootCertCanBeRemoved(EndpointId matterEndpoint, FabricIndex fabric, Tls::TLSCAID id) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR ClientCertCanBeRemoved(EndpointId matterEndpoint, FabricIndex fabric, Tls::TLSCCDID id) override + { + return CHIP_NO_ERROR; + } +}; + +struct TestTLSClientManagementCluster : public ::testing::Test +{ + static void SetUpTestSuite() { ASSERT_EQ(Platform::MemoryInit(), CHIP_NO_ERROR); } + static void TearDownTestSuite() { Platform::MemoryShutdown(); } + + void SetUp() override + { + VerifyOrDie(mPersistenceProvider.Init(&mClusterTester.GetServerClusterContext().storage) == CHIP_NO_ERROR); + app::SetSafeAttributePersistenceProvider(&mPersistenceProvider); + + // Add some test root certificates for the test fabric index (151) + constexpr FabricIndex kMockTestFabric = static_cast(151); + mMockCertTable.rootCerts.push_back({ kMockTestFabric, 1 }); + mMockCertTable.rootCerts.push_back({ kMockTestFabric, 2 }); + + EXPECT_EQ(mCluster.Startup(mClusterTester.GetServerClusterContext()), CHIP_NO_ERROR); + } + + void TearDown() override { app::SetSafeAttributePersistenceProvider(nullptr); } + + MockTLSClientManagementDelegate mMockDelegate; + MockCertificateTable mMockCertTable; + + TLSClientManagementCluster mCluster{ kTestEndpointId, mMockDelegate, mMockCertTable, kMaxProvisioned }; + + ClusterTester mClusterTester{ mCluster }; + + app::DefaultSafeAttributePersistenceProvider mPersistenceProvider; +}; + +TEST_F(TestTLSClientManagementCluster, TestAttributesList) +{ + ReadOnlyBufferBuilder listBuilder; + EXPECT_EQ(mCluster.Attributes(ConcreteClusterPath(kTestEndpointId, TlsClientManagement::Id), listBuilder), CHIP_NO_ERROR); + + ReadOnlyBufferBuilder expectedListBuilder; + AttributeListBuilder attributeListBuilder(expectedListBuilder); + EXPECT_EQ(attributeListBuilder.Append(Span(Attributes::kMandatoryMetadata), {}), CHIP_NO_ERROR); + + EXPECT_TRUE(EqualAttributeSets(listBuilder.TakeBuffer(), expectedListBuilder.TakeBuffer())); +} + +TEST_F(TestTLSClientManagementCluster, TestAcceptedCommands) +{ + ReadOnlyBufferBuilder listBuilder; + EXPECT_EQ(mCluster.AcceptedCommands(ConcreteClusterPath(kTestEndpointId, TlsClientManagement::Id), listBuilder), CHIP_NO_ERROR); + + static constexpr DataModel::AcceptedCommandEntry kExpectedCommands[] = { + Commands::ProvisionEndpoint::kMetadataEntry, + Commands::FindEndpoint::kMetadataEntry, + Commands::RemoveEndpoint::kMetadataEntry, + }; + + ReadOnlyBufferBuilder expectedListBuilder; + EXPECT_EQ(expectedListBuilder.ReferenceExisting(kExpectedCommands), CHIP_NO_ERROR); + + EXPECT_TRUE(EqualAcceptedCommandSets(listBuilder.TakeBuffer(), expectedListBuilder.TakeBuffer())); +} + +TEST_F(TestTLSClientManagementCluster, TestReadMaxProvisioned) +{ + uint8_t maxProvisioned = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::MaxProvisioned::Id, maxProvisioned), CHIP_NO_ERROR); + EXPECT_EQ(maxProvisioned, kMaxProvisioned); +} + +TEST_F(TestTLSClientManagementCluster, TestReadClusterRevision) +{ + uint16_t clusterRevision = 0; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::ClusterRevision::Id, clusterRevision), CHIP_NO_ERROR); + EXPECT_EQ(clusterRevision, kRevision); +} + +TEST_F(TestTLSClientManagementCluster, TestReadFeatureMap) +{ + uint32_t featureMap = 1; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::FeatureMap::Id, featureMap), CHIP_NO_ERROR); + EXPECT_EQ(featureMap, 0u); +} + +TEST_F(TestTLSClientManagementCluster, TestReadProvisionedEndpointsEmpty) +{ + Attributes::ProvisionedEndpoints::TypeInfo::DecodableType list; + EXPECT_EQ(mClusterTester.ReadAttribute(Attributes::ProvisionedEndpoints::Id, list), CHIP_NO_ERROR); + + auto it = list.begin(); + EXPECT_FALSE(it.Next()); +} + +TEST_F(TestTLSClientManagementCluster, TestProvisionEndpointSuccess) +{ + Commands::ProvisionEndpoint::Type request; + const char * hostnameStr = "example.com"; + request.hostname = ByteSpan(reinterpret_cast(hostnameStr), strlen(hostnameStr)); + request.caid = 1; + request.ccdid.SetNull(); + + auto result = mClusterTester.Invoke(request); + EXPECT_TRUE(result.IsSuccess()); + + if (result.response.has_value()) + { + EXPECT_EQ(result.response.value().endpointID, 1); + } + + // Verify endpoint was added + EXPECT_EQ(mMockDelegate.endpoints.size(), 1u); + EXPECT_EQ(mMockDelegate.endpoints[0].endpointID, 1); +} + +TEST_F(TestTLSClientManagementCluster, TestProvisionEndpointConstraintErrors) +{ + // Test hostname too short + Commands::ProvisionEndpoint::Type request; + const char * shortHostname = "abc"; + request.hostname = ByteSpan(reinterpret_cast(shortHostname), 3); + request.caid = 1; + request.ccdid.SetNull(); + + auto result = mClusterTester.Invoke(request); + EXPECT_FALSE(result.IsSuccess()); + if (result.status.has_value()) + { + EXPECT_EQ(result.status.value().GetStatusCode().GetStatus(), Protocols::InteractionModel::Status::ConstraintError); + } + + // Test invalid CAID + const char * validHostname = "example.com"; + request.hostname = ByteSpan(reinterpret_cast(validHostname), strlen(validHostname)); + request.caid = 256; // exceeds kMaxRootCertId + result = mClusterTester.Invoke(request); + EXPECT_FALSE(result.IsSuccess()); +} + +TEST_F(TestTLSClientManagementCluster, TestProvisionEndpointRootCertNotFound) +{ + Commands::ProvisionEndpoint::Type request; + const char * exampleHostname = "example.com"; + request.hostname = ByteSpan(reinterpret_cast(exampleHostname), strlen(exampleHostname)); + request.caid = 99; // Not in mock cert table + request.ccdid.SetNull(); + + auto result = mClusterTester.Invoke(request); + EXPECT_FALSE(result.IsSuccess()); + if (result.status.has_value()) + { + auto statusCode = result.status.value().GetStatusCode(); + EXPECT_TRUE(statusCode.GetClusterSpecificCode().has_value()); + } +} + +TEST_F(TestTLSClientManagementCluster, TestProvisionEndpointClientCertNotFound) +{ + Commands::ProvisionEndpoint::Type request; + const char * hostnameForClientTest = "example.com"; + request.hostname = ByteSpan(reinterpret_cast(hostnameForClientTest), strlen(hostnameForClientTest)); + request.caid = 1; + request.ccdid.SetNonNull(99); // Not in mock cert table + + auto result = mClusterTester.Invoke(request); + EXPECT_FALSE(result.IsSuccess()); +} + +TEST_F(TestTLSClientManagementCluster, TestFindEndpointSuccess) +{ + // First provision an endpoint + Commands::ProvisionEndpoint::Type provisionReq; + const char * hostnameForFind = "example.com"; + provisionReq.hostname = ByteSpan(reinterpret_cast(hostnameForFind), strlen(hostnameForFind)); + provisionReq.caid = 1; + provisionReq.ccdid.SetNull(); + + auto provisionResult = mClusterTester.Invoke(provisionReq); + EXPECT_TRUE(provisionResult.IsSuccess()); + ASSERT_TRUE(provisionResult.response.has_value()); + + uint16_t provisionedID = 0; + if (provisionResult.response.has_value()) + { + provisionedID = provisionResult.response.value().endpointID; + } + + // Now find it + Commands::FindEndpoint::Type findReq; + findReq.endpointID = provisionedID; + + auto findResult = mClusterTester.Invoke(findReq); + EXPECT_TRUE(findResult.IsSuccess()); + + if (findResult.response.has_value()) + { + EXPECT_EQ(findResult.response.value().endpoint.endpointID, provisionedID); + const char * expectedHostname = "example.com"; + EXPECT_TRUE(findResult.response.value().endpoint.hostname.data_equal( + ByteSpan(reinterpret_cast(expectedHostname), strlen(expectedHostname)))); + } +} + +TEST_F(TestTLSClientManagementCluster, TestFindEndpointNotFound) +{ + Commands::FindEndpoint::Type request; + request.endpointID = 999; // Non-existent endpoint + + auto result = mClusterTester.Invoke(request); + EXPECT_FALSE(result.IsSuccess()); + if (result.status.has_value()) + { + EXPECT_EQ(result.status.value().GetStatusCode().GetStatus(), Protocols::InteractionModel::Status::NotFound); + } +} + +TEST_F(TestTLSClientManagementCluster, TestFindEndpointConstraintError) +{ + Commands::FindEndpoint::Type request; + request.endpointID = 65535; // Exceeds kMaxTlsEndpointId + + auto result = mClusterTester.Invoke(request); + EXPECT_FALSE(result.IsSuccess()); + if (result.status.has_value()) + { + EXPECT_EQ(result.status.value().GetStatusCode().GetStatus(), Protocols::InteractionModel::Status::ConstraintError); + } +} + +TEST_F(TestTLSClientManagementCluster, TestRemoveEndpointSuccess) +{ + // First provision an endpoint + Commands::ProvisionEndpoint::Type provisionReq; + const char * hostnameForRemove = "example.com"; + provisionReq.hostname = ByteSpan(reinterpret_cast(hostnameForRemove), strlen(hostnameForRemove)); + provisionReq.caid = 1; + provisionReq.ccdid.SetNull(); + + auto provisionResult = mClusterTester.Invoke(provisionReq); + EXPECT_TRUE(provisionResult.IsSuccess()); + ASSERT_TRUE(provisionResult.response.has_value()); + + uint16_t provisionedID = 0; + if (provisionResult.response.has_value()) + { + provisionedID = provisionResult.response.value().endpointID; + } + + EXPECT_EQ(mMockDelegate.endpoints.size(), 1u); + + // Now remove it + Commands::RemoveEndpoint::Type removeReq; + removeReq.endpointID = provisionedID; + + auto removeResult = mClusterTester.Invoke(removeReq); + EXPECT_TRUE(removeResult.IsSuccess()); + + // Verify it was removed + EXPECT_EQ(mMockDelegate.endpoints.size(), 0u); +} + +TEST_F(TestTLSClientManagementCluster, TestRemoveEndpointNotFound) +{ + Commands::RemoveEndpoint::Type request; + request.endpointID = 999; // Non-existent endpoint + + auto result = mClusterTester.Invoke(request); + EXPECT_FALSE(result.IsSuccess()); + if (result.status.has_value()) + { + EXPECT_EQ(result.status.value().GetStatusCode().GetStatus(), Protocols::InteractionModel::Status::NotFound); + } +} + +TEST_F(TestTLSClientManagementCluster, TestRemoveEndpointConstraintError) +{ + Commands::RemoveEndpoint::Type request; + request.endpointID = 65535; // Exceeds kMaxTlsEndpointId + + auto result = mClusterTester.Invoke(request); + EXPECT_FALSE(result.IsSuccess()); + if (result.status.has_value()) + { + EXPECT_EQ(result.status.value().GetStatusCode().GetStatus(), Protocols::InteractionModel::Status::ConstraintError); + } +} + +} // namespace diff --git a/src/app/clusters/tls-client-management-server/tls-client-management-server.cpp b/src/app/clusters/tls-client-management-server/tls-client-management-server.cpp deleted file mode 100644 index 911723c1439..00000000000 --- a/src/app/clusters/tls-client-management-server/tls-client-management-server.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* - * - * Copyright (c) 2025 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/****************************************************************************' - * @file - * @brief Implementation for the TlsClientManagement Server Cluster - ***************************************************************************/ - -#include "tls-client-management-server.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace chip; -using namespace chip::app; -using namespace chip::app::Clusters; -using namespace chip::app::Clusters::Tls; -using namespace chip::app::Clusters::TlsClientManagement; -using namespace chip::app::Clusters::TlsClientManagement::Structs; -using namespace chip::app::Clusters::TlsClientManagement::Attributes; -using namespace Protocols::InteractionModel; - -static constexpr uint16_t kMaxTlsEndpointId = 65534; - -TlsClientManagementServer::TlsClientManagementServer(EndpointId endpointId, TlsClientManagementDelegate & delegate, - CertificateTable & certificateTable, uint8_t maxProvisioned) : - AttributeAccessInterface(MakeOptional(endpointId), TlsClientManagement::Id), - CommandHandlerInterface(MakeOptional(endpointId), TlsClientManagement::Id), mDelegate(delegate), - mCertificateTable(certificateTable), mMaxProvisioned(maxProvisioned) -{ - VerifyOrDieWithMsg(mMaxProvisioned >= 5, NotSpecified, "Spec requires MaxProvisioned be >= 5"); - VerifyOrDieWithMsg(mMaxProvisioned <= 254, NotSpecified, "Spec requires MaxProvisioned be <= 254"); - mDelegate.SetTlsClientManagementServer(this); -} - -TlsClientManagementServer::~TlsClientManagementServer() -{ - // null out the ref to us on the delegate - mDelegate.SetTlsClientManagementServer(nullptr); - - // unregister - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); - AttributeAccessInterfaceRegistry::Instance().Unregister(this); -} - -CHIP_ERROR TlsClientManagementServer::Init() -{ - mCertificateTable.Init(Server::GetInstance().GetPersistentStorage()); - mDelegate.Init(Server::GetInstance().GetPersistentStorage()); - - VerifyOrReturnError(AttributeAccessInterfaceRegistry::Instance().Register(this), CHIP_ERROR_INTERNAL); - ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(this)); - - return Server::GetInstance().GetFabricTable().AddFabricDelegate(this); -} - -CHIP_ERROR TlsClientManagementServer::Finish() -{ - mCertificateTable.Finish(); - - Server::GetInstance().GetFabricTable().RemoveFabricDelegate(this); - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); - AttributeAccessInterfaceRegistry::Instance().Unregister(this); - - return CHIP_NO_ERROR; -} - -// AttributeAccessInterface -CHIP_ERROR TlsClientManagementServer::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) -{ - VerifyOrDie(aPath.mClusterId == TlsClientManagement::Id); - - switch (aPath.mAttributeId) - { - case MaxProvisioned::Id: - return aEncoder.Encode(mMaxProvisioned); - case ProvisionedEndpoints::Id: { - TlsClientManagementServer * server = this; - auto matterEndpoint = aPath.mEndpointId; - auto fabric = aEncoder.AccessingFabricIndex(); - CHIP_ERROR err = aEncoder.EncodeList([server, matterEndpoint, fabric](const auto & encoder) -> CHIP_ERROR { - return server->EncodeProvisionedEndpoints(matterEndpoint, fabric, encoder); - }); - return err; - } - case ClusterRevision::Id: - return aEncoder.Encode(kRevision); - } - - return CHIP_NO_ERROR; -} - -uint8_t TlsClientManagementServer::GetMaxProvisioned() const -{ - return mMaxProvisioned; -} - -// helper method to get the TlsClientManagement provisioned endpoints encoded into a list -CHIP_ERROR -TlsClientManagementServer::EncodeProvisionedEndpoints(EndpointId matterEndpoint, FabricIndex fabric, - const AttributeValueEncoder::ListEncodeHelper & encoder) -{ - return mDelegate.ForEachEndpoint(matterEndpoint, fabric, - [&](auto & endpoint) -> CHIP_ERROR { return encoder.Encode(endpoint); }); -} - -void TlsClientManagementServer::InvokeCommand(HandlerContext & ctx) -{ - switch (ctx.mRequestPath.mCommandId) - { - case Commands::ProvisionEndpoint::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleProvisionEndpoint(innerCtx, req); }); - break; - case Commands::FindEndpoint::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleFindEndpoint(innerCtx, req); }); - break; - case Commands::RemoveEndpoint::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleRemoveEndpoint(innerCtx, req); }); - break; - } -} - -void TlsClientManagementServer::HandleProvisionEndpoint(HandlerContext & ctx, - const Commands::ProvisionEndpoint::DecodableType & req) -{ - ChipLogDetail(Zcl, "TlsClientManagement: ProvisionEndpoint"); - - VerifyOrReturn(req.hostname.size() >= 4 && req.hostname.size() <= kSpecMaxHostname, - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); - VerifyOrReturn(req.caid <= kMaxRootCertId, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); - - auto fabric = ctx.mCommandHandler.GetAccessingFabricIndex(); - - ReturnOnFailure(mCertificateTable.HasRootCertificateEntry(fabric, req.caid), - ctx.mCommandHandler.AddStatus( - ctx.mRequestPath, ClusterStatusCode::ClusterSpecificFailure(StatusCodeEnum::kRootCertificateNotFound))); - VerifyOrReturn(req.ccdid.IsNull() || mCertificateTable.HasClientCertificateEntry(fabric, req.ccdid.Value()) == CHIP_NO_ERROR, - ctx.mCommandHandler.AddStatus( - ctx.mRequestPath, ClusterStatusCode::ClusterSpecificFailure(StatusCodeEnum::kClientCertificateNotFound))); - - Commands::ProvisionEndpointResponse::Type response; - auto status = mDelegate.ProvisionEndpoint(ctx.mRequestPath.mEndpointId, fabric, req, response.endpointID); - - if (status.IsSuccess()) - { - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); - } - else - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); - } -} - -void TlsClientManagementServer::HandleFindEndpoint(HandlerContext & ctx, const Commands::FindEndpoint::DecodableType & req) -{ - ChipLogDetail(Zcl, "TlsClientManagement: FindEndpoint"); - - VerifyOrReturn(req.endpointID <= kMaxTlsEndpointId, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); - - CHIP_ERROR result = - mDelegate.FindProvisionedEndpointByID(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(), - req.endpointID, [&](auto & endpoint) -> CHIP_ERROR { - Commands::FindEndpointResponse::Type response; - response.endpoint = endpoint; - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); - return CHIP_NO_ERROR; - }); - - if (result == CHIP_ERROR_NOT_FOUND) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); - } - else if (result != CHIP_NO_ERROR) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); - } -} - -void TlsClientManagementServer::HandleRemoveEndpoint(HandlerContext & ctx, const Commands::RemoveEndpoint::DecodableType & req) -{ - ChipLogDetail(Zcl, "TlsClientManagement: RemoveEndpoint"); - - VerifyOrReturn(req.endpointID <= kMaxTlsEndpointId, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); - - auto status = mDelegate.RemoveProvisionedEndpointByID(ctx.mRequestPath.mEndpointId, - ctx.mCommandHandler.GetAccessingFabricIndex(), req.endpointID); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); -} - -void TlsClientManagementServer::OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) -{ - mDelegate.RemoveFabric(fabricIndex); -} - -/** @brief TlsClientManagement Cluster Server Init - * - * Server Init - * - */ -void MatterTlsClientManagementPluginServerInitCallback() {} diff --git a/src/app/clusters/unit-localization-server/unit-localization-server.cpp b/src/app/clusters/unit-localization-server/unit-localization-server.cpp index cf8dc68a3fa..9e75026789f 100644 --- a/src/app/clusters/unit-localization-server/unit-localization-server.cpp +++ b/src/app/clusters/unit-localization-server/unit-localization-server.cpp @@ -143,7 +143,7 @@ CHIP_ERROR UnitLocalizationServer::SetTemperatureUnit(TempUnitEnum newTempUnit) void MatterUnitLocalizationPluginServerInitCallback() { - UnitLocalizationServer::Instance().Init(); + TEMPORARY_RETURN_IGNORED UnitLocalizationServer::Instance().Init(); AttributeAccessInterfaceRegistry::Instance().Register(&UnitLocalizationServer::Instance()); } diff --git a/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-cluster.cpp b/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-cluster.cpp index 6f6cb12fdbe..dc5adff9df6 100644 --- a/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-cluster.cpp +++ b/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-cluster.cpp @@ -249,7 +249,7 @@ void startRemainingDurationTick(EndpointId ep) } else { - ValveConfigurationAndControl::CloseValve(ep); + TEMPORARY_RETURN_IGNORED ValveConfigurationAndControl::CloseValve(ep); (void) DeviceLayer::SystemLayer().CancelTimer(onValveConfigurationAndControlTick, item); } } @@ -300,7 +300,7 @@ CHIP_ERROR CloseValve(EndpointId ep) emitValveStateChangedEvent(ep, ValveConfigurationAndControl::ValveStateEnum::kTransitioning); if (!isDelegateNull(delegate)) { - delegate->HandleCloseValve(); + TEMPORARY_RETURN_IGNORED delegate->HandleCloseValve(); } return CHIP_NO_ERROR; @@ -361,7 +361,7 @@ CHIP_ERROR SetValveLevel(EndpointId ep, DataModel::Nullable level, Data DataModel::Nullable cLevel = delegate->HandleOpenValve(level); if (HasFeature(ep, ValveConfigurationAndControl::Feature::kLevel) && !cLevel.IsNull()) { - UpdateCurrentLevel(ep, cLevel.Value()); + TEMPORARY_RETURN_IGNORED UpdateCurrentLevel(ep, cLevel.Value()); } } // start countdown @@ -382,7 +382,7 @@ CHIP_ERROR UpdateCurrentLevel(EndpointId ep, Percent currentLevel) { targetLevel = DataModel::NullNullable; TargetLevel::Set(ep, targetLevel); - UpdateCurrentState(ep, currentLevel == 0 ? ValveStateEnum::kClosed : ValveStateEnum::kOpen); + TEMPORARY_RETURN_IGNORED UpdateCurrentState(ep, currentLevel == 0 ? ValveStateEnum::kClosed : ValveStateEnum::kOpen); } return CHIP_NO_ERROR; } @@ -442,8 +442,8 @@ bool emberAfValveConfigurationAndControlClusterOpenCallback( // if fault is registered return FailureDueToFault if (Status::Success == ValveFault::Get(ep, &fault) && fault.HasAny()) { - commandObj->AddClusterSpecificFailure(commandPath, - to_underlying(ValveConfigurationAndControl::StatusCodeEnum::kFailureDueToFault)); + TEMPORARY_RETURN_IGNORED commandObj->AddClusterSpecificFailure( + commandPath, to_underlying(ValveConfigurationAndControl::StatusCodeEnum::kFailureDueToFault)); return true; } @@ -487,7 +487,7 @@ bool emberAfValveConfigurationAndControlClusterOpenCallback( { BitMask gFault( ValveConfigurationAndControl::ValveFaultBitmap::kGeneralFault); - emitValveFaultEvent(ep, gFault); + TEMPORARY_RETURN_IGNORED emitValveFaultEvent(ep, gFault); commandObj->AddStatus(commandPath, status.Value()); } else @@ -508,8 +508,8 @@ bool emberAfValveConfigurationAndControlClusterCloseCallback( // if fault is registered return FailureDueToFault if (Status::Success == ValveFault::Get(ep, &fault) && fault.HasAny()) { - commandObj->AddClusterSpecificFailure(commandPath, - to_underlying(ValveConfigurationAndControl::StatusCodeEnum::kFailureDueToFault)); + TEMPORARY_RETURN_IGNORED commandObj->AddClusterSpecificFailure( + commandPath, to_underlying(ValveConfigurationAndControl::StatusCodeEnum::kFailureDueToFault)); return true; } diff --git a/src/app/clusters/water-heater-management-server/water-heater-management-server.cpp b/src/app/clusters/water-heater-management-server/water-heater-management-server.cpp index 165fc94fb31..902abd691dd 100644 --- a/src/app/clusters/water-heater-management-server/water-heater-management-server.cpp +++ b/src/app/clusters/water-heater-management-server/water-heater-management-server.cpp @@ -101,7 +101,7 @@ CHIP_ERROR Instance::Init() void Instance::Shutdown() { - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); + TEMPORARY_RETURN_IGNORED CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); chip::app::AttributeAccessInterfaceRegistry::Instance().Unregister(this); } diff --git a/src/app/clusters/webrtc-transport-provider-server/BUILD.gn b/src/app/clusters/webrtc-transport-provider-server/BUILD.gn index 1156f5434fd..04426a549af 100644 --- a/src/app/clusters/webrtc-transport-provider-server/BUILD.gn +++ b/src/app/clusters/webrtc-transport-provider-server/BUILD.gn @@ -11,5 +11,21 @@ # 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. -group("webrtc-transport-provider-server") { + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +source_set("webrtc-transport-provider-server") { + sources = [ + "WebRTCTransportProviderCluster.cpp", + "WebRTCTransportProviderCluster.h", + ] + + public_deps = [ + "${chip_root}/src/app:attribute-access", + "${chip_root}/src/app/data-model-provider:metadata", + "${chip_root}/src/app/server-cluster", + "${chip_root}/src/lib/core:error", + "${chip_root}/zzz_generated/app-common/clusters/WebRTCTransportProvider", + ] } diff --git a/src/platform/nxp/zephyr/KeyValueStoreManagerImpl.h b/src/app/clusters/webrtc-transport-provider-server/CodegenIntegration.cpp similarity index 54% rename from src/platform/nxp/zephyr/KeyValueStoreManagerImpl.h rename to src/app/clusters/webrtc-transport-provider-server/CodegenIntegration.cpp index c497842975c..449c404fcaa 100644 --- a/src/platform/nxp/zephyr/KeyValueStoreManagerImpl.h +++ b/src/app/clusters/webrtc-transport-provider-server/CodegenIntegration.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2024 Project CHIP Authors + * Copyright (c) 2025 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,12 +16,17 @@ * limitations under the License. */ -/** - * @file - * Platform-specific key value storage implementation for Zephyr. - * - */ +#include + +// These callbacks are required by the Ember/codegen integration but are not +// needed for the server cluster interface implementation. -#pragma once +void MatterWebRTCTransportProviderPluginServerInitCallback() +{ + ChipLogProgress(Zcl, "Initializing WebRTC Transport Provider cluster."); +} -#include +void MatterWebRTCTransportProviderPluginServerShutdownCallback() +{ + ChipLogProgress(Zcl, "Shutdown WebRTC Transport Provider cluster."); +} diff --git a/src/app/clusters/webrtc-transport-provider-server/webrtc-transport-provider-server.cpp b/src/app/clusters/webrtc-transport-provider-server/WebRTCTransportProviderCluster.cpp similarity index 60% rename from src/app/clusters/webrtc-transport-provider-server/webrtc-transport-provider-server.cpp rename to src/app/clusters/webrtc-transport-provider-server/WebRTCTransportProviderCluster.cpp index d90c4a18f67..916c8547892 100644 --- a/src/app/clusters/webrtc-transport-provider-server/webrtc-transport-provider-server.cpp +++ b/src/app/clusters/webrtc-transport-provider-server/WebRTCTransportProviderCluster.cpp @@ -15,38 +15,42 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "webrtc-transport-provider-server.h" - -#include +#include "WebRTCTransportProviderCluster.h" #include #include #include -#include -#include -#include -#include -#include +#include #include #include +#include #include #include +#include using namespace chip; using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::WebRTCTransportProvider; +using namespace chip::app::Clusters::WebRTCTransportProvider::Attributes; +using namespace chip::Protocols::InteractionModel; using chip::Protocols::InteractionModel::Status; -using ICEServerDecodableStruct = chip::app::Clusters::Globals::Structs::ICEServerStruct::DecodableType; -using WebRTCSessionStruct = chip::app::Clusters::Globals::Structs::WebRTCSessionStruct::Type; -using ICECandidateStruct = chip::app::Clusters::Globals::Structs::ICECandidateStruct::Type; -using StreamUsageEnum = chip::app::Clusters::Globals::StreamUsageEnum; -using WebRTCEndReasonEnum = chip::app::Clusters::Globals::WebRTCEndReasonEnum; - namespace { static constexpr uint16_t kMaxSessionId = 65534; +constexpr DataModel::AcceptedCommandEntry kAcceptedCommands[] = { + Commands::SolicitOffer::kMetadataEntry, Commands::ProvideOffer::kMetadataEntry, Commands::ProvideAnswer::kMetadataEntry, + Commands::ProvideICECandidates::kMetadataEntry, Commands::EndSession::kMetadataEntry, +}; + +constexpr CommandId kGeneratedCommands[] = { + Commands::SolicitOfferResponse::Id, + Commands::ProvideOfferResponse::Id, +}; + NodeId GetNodeIdFromCtx(const CommandHandler & commandHandler) { auto descriptor = commandHandler.GetSubjectDescriptor(); @@ -211,87 +215,84 @@ namespace app { namespace Clusters { namespace WebRTCTransportProvider { -WebRTCTransportProviderServer::WebRTCTransportProviderServer(Delegate & delegate, EndpointId endpointId) : - AttributeAccessInterface(MakeOptional(endpointId), WebRTCTransportProvider::Id), - CommandHandlerInterface(MakeOptional(endpointId), WebRTCTransportProvider::Id), mDelegate(delegate) +WebRTCTransportProviderCluster::WebRTCTransportProviderCluster(EndpointId endpointId, Delegate & delegate) : + DefaultServerCluster({ endpointId, Id }), mDelegate(delegate) {} -WebRTCTransportProviderServer::~WebRTCTransportProviderServer() -{ - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); - AttributeAccessInterfaceRegistry::Instance().Unregister(this); -} - -CHIP_ERROR WebRTCTransportProviderServer::Init() -{ - ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(this)); - VerifyOrReturnError(AttributeAccessInterfaceRegistry::Instance().Register(this), CHIP_ERROR_INCORRECT_STATE); - - return CHIP_NO_ERROR; -} - -// AttributeAccessInterface -CHIP_ERROR WebRTCTransportProviderServer::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) +DataModel::ActionReturnStatus WebRTCTransportProviderCluster::ReadAttribute(const DataModel::ReadAttributeRequest & request, + AttributeValueEncoder & encoder) { - // The only attribute from the spec is "CurrentSessions" (attribute ID 0x0000), - // which is a list[WebRTCSessionStruct]. - if (aPath.mClusterId == Id && aPath.mAttributeId == Attributes::CurrentSessions::Id) + switch (request.path.mAttributeId) { - // We encode mCurrentSessions as a list of WebRTCSessionStruct - return aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR { + case CurrentSessions::Id: + return encoder.EncodeList([this](const auto & listEncoder) -> CHIP_ERROR { for (auto & session : mCurrentSessions) { - ReturnErrorOnFailure(encoder.Encode(session)); + ReturnErrorOnFailure(listEncoder.Encode(session)); } return CHIP_NO_ERROR; }); + case ClusterRevision::Id: + return encoder.Encode(kRevision); + case FeatureMap::Id: + // TODO: Allow delegate to specify supported features + // Currently hardcoded to 0 (no features supported) + // METADATA feature (bit 0) should be configurable based on delegate capabilities + return encoder.Encode(0); + default: + return Status::UnsupportedAttribute; } - - // If not our attribute, let default logic handle - return CHIP_NO_ERROR; } -// CommandHandlerInterface -void WebRTCTransportProviderServer::InvokeCommand(HandlerContext & ctx) +std::optional WebRTCTransportProviderCluster::InvokeCommand(const DataModel::InvokeRequest & request, + TLV::TLVReader & input_arguments, + CommandHandler * handler) { - ChipLogDetail(Zcl, "WebRTCTransportProvider: InvokeCommand called with CommandId=0x%08" PRIx32, ctx.mRequestPath.mCommandId); + FabricIndex accessingFabricIndex = handler->GetAccessingFabricIndex(); - switch (ctx.mRequestPath.mCommandId) + switch (request.path.mCommandId) { case Commands::SolicitOffer::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & subCtx, const auto & req) { HandleSolicitOffer(subCtx, req); }); - break; - + return HandleCommand(input_arguments, accessingFabricIndex, *handler, + &WebRTCTransportProviderCluster::HandleSolicitOffer); case Commands::ProvideOffer::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & subCtx, const auto & req) { HandleProvideOffer(subCtx, req); }); - break; - + return HandleCommand(input_arguments, accessingFabricIndex, *handler, + &WebRTCTransportProviderCluster::HandleProvideOffer); case Commands::ProvideAnswer::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & subCtx, const auto & req) { HandleProvideAnswer(subCtx, req); }); - break; - + return HandleCommand(input_arguments, accessingFabricIndex, *handler, + &WebRTCTransportProviderCluster::HandleProvideAnswer); case Commands::ProvideICECandidates::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & subCtx, const auto & req) { HandleProvideICECandidates(subCtx, req); }); - break; - + return HandleCommand( + input_arguments, accessingFabricIndex, *handler, &WebRTCTransportProviderCluster::HandleProvideICECandidates); case Commands::EndSession::Id: - CommandHandlerInterface::HandleCommand( - ctx, [this](HandlerContext & subCtx, const auto & req) { HandleEndSession(subCtx, req); }); - break; - + return HandleCommand(input_arguments, accessingFabricIndex, *handler, + &WebRTCTransportProviderCluster::HandleEndSession); default: - // Mark unrecognized command as UnsupportedCommand - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::UnsupportedCommand); - break; + return Status::UnsupportedCommand; } } +CHIP_ERROR WebRTCTransportProviderCluster::AcceptedCommands(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) +{ + return builder.ReferenceExisting(kAcceptedCommands); +} + +CHIP_ERROR WebRTCTransportProviderCluster::GeneratedCommands(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) +{ + return builder.ReferenceExisting(kGeneratedCommands); +} + +CHIP_ERROR WebRTCTransportProviderCluster::Attributes(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) +{ + AttributeListBuilder listBuilder(builder); + return listBuilder.Append(Span(kMandatoryMetadata), {}); +} + // Helper functions -WebRTCSessionStruct * WebRTCTransportProviderServer::FindSession(uint16_t sessionId) +WebRTCSessionStruct * WebRTCTransportProviderCluster::FindSession(uint16_t sessionId) { for (auto & session : mCurrentSessions) { @@ -304,7 +305,7 @@ WebRTCSessionStruct * WebRTCTransportProviderServer::FindSession(uint16_t sessio return nullptr; } -WebRTCTransportProviderServer::UpsertResultEnum WebRTCTransportProviderServer::UpsertSession(const WebRTCSessionStruct & session) +WebRTCTransportProviderCluster::UpsertResultEnum WebRTCTransportProviderCluster::UpsertSession(const WebRTCSessionStruct & session) { assertChipStackLockedByCurrentThread(); @@ -323,13 +324,12 @@ WebRTCTransportProviderServer::UpsertResultEnum WebRTCTransportProviderServer::U result = UpsertResultEnum::kInserted; } - MatterReportingAttributeChangeCallback(AttributeAccessInterface::GetEndpointId().Value(), WebRTCTransportProvider::Id, - WebRTCTransportProvider::Attributes::CurrentSessions::Id); + NotifyAttributeChanged(Attributes::CurrentSessions::Id); return result; } -void WebRTCTransportProviderServer::RemoveSession(uint16_t sessionId) +void WebRTCTransportProviderCluster::RemoveSession(uint16_t sessionId) { assertChipStackLockedByCurrentThread(); @@ -343,13 +343,12 @@ void WebRTCTransportProviderServer::RemoveSession(uint16_t sessionId) // If a session was removed, the size will be smaller. if (mCurrentSessions.size() < originalSize) { - // Notify the stack that the CurrentSessions attribute has changed. - MatterReportingAttributeChangeCallback(AttributeAccessInterface::GetEndpointId().Value(), WebRTCTransportProvider::Id, - WebRTCTransportProvider::Attributes::CurrentSessions::Id); + NotifyAttributeChanged(Attributes::CurrentSessions::Id); } } -WebRTCSessionStruct * WebRTCTransportProviderServer::CheckForMatchingSession(HandlerContext & ctx, uint16_t sessionId) +WebRTCSessionStruct * WebRTCTransportProviderCluster::CheckForMatchingSession(const CommandHandler & commandHandler, + uint16_t sessionId) { WebRTCSessionStruct * session = FindSession(sessionId); if (session == nullptr) @@ -357,8 +356,8 @@ WebRTCSessionStruct * WebRTCTransportProviderServer::CheckForMatchingSession(Han return nullptr; } - NodeId peerNodeId = GetNodeIdFromCtx(ctx.mCommandHandler); - FabricIndex peerFabricIndex = ctx.mCommandHandler.GetAccessingFabricIndex(); + NodeId peerNodeId = GetNodeIdFromCtx(commandHandler); + FabricIndex peerFabricIndex = commandHandler.GetAccessingFabricIndex(); // Ensure the session’s peer matches the current command invoker if (peerNodeId != session->peerNodeID || peerFabricIndex != session->GetFabricIndex()) @@ -369,7 +368,7 @@ WebRTCSessionStruct * WebRTCTransportProviderServer::CheckForMatchingSession(Han return session; } -CHIP_ERROR WebRTCTransportProviderServer::GenerateSessionId(uint16_t & outSessionId) +CHIP_ERROR WebRTCTransportProviderCluster::GenerateSessionId(uint16_t & outSessionId) { static uint16_t nextSessionId = 0; uint16_t candidateId = 0; @@ -398,7 +397,7 @@ CHIP_ERROR WebRTCTransportProviderServer::GenerateSessionId(uint16_t & outSessio return CHIP_IM_GLOBAL_STATUS(ResourceExhausted); } -Status WebRTCTransportProviderServer::CheckPrivacyModes(const char * commandName, StreamUsageEnum streamUsage) +Status WebRTCTransportProviderCluster::CheckPrivacyModes(const char * commandName, StreamUsageEnum streamUsage) { bool hardPrivacyModeActive = false; CHIP_ERROR err = mDelegate.IsHardPrivacyModeActive(hardPrivacyModeActive); @@ -445,7 +444,7 @@ Status WebRTCTransportProviderServer::CheckPrivacyModes(const char * commandName return Status::Success; } -Status WebRTCTransportProviderServer::CheckTurnsOrStunsRequiresUTCTime( +Status WebRTCTransportProviderCluster::CheckTurnsOrStunsRequiresUTCTime( const char * commandName, const Optional> & iceServers) { if (!iceServers.HasValue()) @@ -495,28 +494,123 @@ Status WebRTCTransportProviderServer::CheckTurnsOrStunsRequiresUTCTime( return Status::Success; } -// Command Handlers -void WebRTCTransportProviderServer::HandleSolicitOffer(HandlerContext & ctx, const Commands::SolicitOffer::DecodableType & req) +Status WebRTCTransportProviderCluster::ValidateStreamID(const char * commandName, + const Optional> & streamID, + Optional> & outStreams, StreamType streamType) { - auto videoStreamID = req.videoStreamID; - auto audioStreamID = req.audioStreamID; + if (!streamID.HasValue()) + { + return Status::Success; + } + std::vector streams; + if (streamID.Value().IsNull()) + { + // Automatic stream assignment - check if there are any allocated streams + bool hasAllocatedStreams = + (streamType == StreamType::kVideo) ? mDelegate.HasAllocatedVideoStreams() : mDelegate.HasAllocatedAudioStreams(); + if (!hasAllocatedStreams) + { + ChipLogError(Zcl, "%s: %s requested when there are no Allocated%sStreams", commandName, + (streamType == StreamType::kVideo) ? "video" : "audio", + (streamType == StreamType::kVideo) ? "Video" : "Audio"); + return Status::InvalidInState; + } + // Empty vector implies auto-select + } + else + { + // Validate the specific stream ID against allocated streams + CHIP_ERROR err = (streamType == StreamType::kVideo) ? mDelegate.ValidateVideoStreamID(streamID.Value().Value()) + : mDelegate.ValidateAudioStreamID(streamID.Value().Value()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "%s: %sStreamID %u does not match Allocated%sStreams", commandName, + (streamType == StreamType::kVideo) ? "Video" : "Audio", streamID.Value().Value(), + (streamType == StreamType::kVideo) ? "Video" : "Audio"); + return Status::DynamicConstraintError; + } + streams.push_back(streamID.Value().Value()); + } + + outStreams.SetValue(std::move(streams)); + return Status::Success; +} + +Status WebRTCTransportProviderCluster::ValidateStreams(const char * commandName, + const Optional> & inStreams, + Optional> & outStreams, StreamType streamType) +{ + if (!inStreams.HasValue()) + { + return Status::Success; + } + + std::vector streams; + auto iter = inStreams.Value().begin(); + while (iter.Next()) + { + streams.push_back(iter.GetValue()); + } + + if (iter.GetStatus() != CHIP_NO_ERROR) + { + return Status::InvalidCommand; + } + + // Check if allocated streams is empty + bool hasAllocatedStreams = + (streamType == StreamType::kVideo) ? mDelegate.HasAllocatedVideoStreams() : mDelegate.HasAllocatedAudioStreams(); + if (!hasAllocatedStreams) + { + ChipLogError(Zcl, "%s: Allocated%sStreams is empty", commandName, (streamType == StreamType::kVideo) ? "Video" : "Audio"); + return Status::InvalidInState; + } + + // Check for duplicate entries + std::set uniqueStreams(streams.begin(), streams.end()); + if (uniqueStreams.size() != streams.size()) + { + ChipLogError(Zcl, "%s: Duplicate entries in %sStreams", commandName, + (streamType == StreamType::kVideo) ? "Video" : "Audio"); + return Status::AlreadyExists; + } + + // Validate each entry exists in allocated streams + CHIP_ERROR err = + (streamType == StreamType::kVideo) ? mDelegate.ValidateVideoStreams(streams) : mDelegate.ValidateAudioStreams(streams); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "%s: %sStreams entry not found in Allocated%sStreams", commandName, + (streamType == StreamType::kVideo) ? "Video" : "Audio", + (streamType == StreamType::kVideo) ? "Video" : "Audio"); + return Status::DynamicConstraintError; + } + + outStreams.SetValue(std::move(streams)); + return Status::Success; +} + +// Command Handlers +std::optional +WebRTCTransportProviderCluster::HandleSolicitOffer(CommandHandler & commandHandler, + const Commands::SolicitOffer::DecodableType & req) +{ // ===== Validate all conformance and constraint checks (data model validation) ===== // Validate the streamUsage field against the allowed enum values. if (req.streamUsage == StreamUsageEnum::kUnknownEnumValue) { ChipLogError(Zcl, "HandleSolicitOffer: Invalid streamUsage value %u.", to_underlying(req.streamUsage)); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; + return Status::ConstraintError; } - // At least one of Video Stream ID and Audio Stream ID has to be present - if (!req.videoStreamID.HasValue() && !req.audioStreamID.HasValue()) + // At least one of Video Stream ID, Audio Stream ID, AudioStreamID or VideoStreams has to be present + if (!req.videoStreamID.HasValue() && !req.audioStreamID.HasValue() && !req.videoStreams.HasValue() && + !req.audioStreams.HasValue()) { - ChipLogError(Zcl, "HandleSolicitOffer: one of VideoStreamID or AudioStreamID must be present"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - return; + ChipLogError(Zcl, "HandleSolicitOffer: one of VideoStreamID, AudioStreamID, VideoStreams, AudioStreams must be present"); + return Status::InvalidCommand; } if (req.SFrameConfig.HasValue()) @@ -524,8 +618,7 @@ void WebRTCTransportProviderServer::HandleSolicitOffer(HandlerContext & ctx, con if (!SFrameFollowsSpecConstraints(req.SFrameConfig.Value())) { ChipLogError(Zcl, "HandleSolicitOffer: SFrame spec constraint validation failed"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; + return Status::ConstraintError; } } @@ -537,8 +630,7 @@ void WebRTCTransportProviderServer::HandleSolicitOffer(HandlerContext & ctx, con Status validationStatus = ICEServersFollowsSpecConstraints(req.ICEServers.Value(), "HandleSolicitOffer"); if (validationStatus != Status::Success) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, validationStatus); - return; + return validationStatus; } } @@ -548,84 +640,77 @@ void WebRTCTransportProviderServer::HandleSolicitOffer(HandlerContext & ctx, con if (req.ICETransportPolicy.Value().size() > 16) { ChipLogError(Zcl, "HandleSolicitOffer: ICETransportPolicy exceeds maximum length of 16"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; + return Status::ConstraintError; } } - // ===== Cluster logic starts here ===== + // ===== Cluster logic starts here (Effect on Receipt) ===== Status status = CheckPrivacyModes("HandleSolicitOffer", req.streamUsage); if (status != Status::Success) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); - return; + return status; } // Validate that the StreamUsage is in the StreamUsagePriorities list if (mDelegate.IsStreamUsageSupported(req.streamUsage) != CHIP_NO_ERROR) { ChipLogError(Zcl, "HandleSolicitOffer: StreamUsage %u is not in StreamUsagePriorities", to_underlying(req.streamUsage)); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::DynamicConstraintError); - return; + return Status::DynamicConstraintError; } - // Validate VideoStreamID against AllocatedVideoStreams. - // If present and null then a stream has to have been allocated. - // If present and not null, then the stream ID has to exist - if (req.videoStreamID.HasValue()) + // If the VideoStreams or AudioStreams fields are present, and the VideoStreamID or AudioStreamID + // fields are present, fail the command with INVALID_COMMAND + if ((req.videoStreams.HasValue() || req.audioStreams.HasValue()) && + (req.videoStreamID.HasValue() || req.audioStreamID.HasValue())) { - if (req.videoStreamID.Value().IsNull()) - { - // Is there an allocated stream, delegate handles matching against an allocated stream in the HandleSolicitOffer method - if (!mDelegate.HasAllocatedVideoStreams()) - { - ChipLogError(Zcl, "HandleSolicitOffer: video requested when there are no AllocatedVideoStreams"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidInState); - return; - } - } - else - { - // Delegate should validate against AllocatedVideoStreams - if (mDelegate.ValidateVideoStreamID(req.videoStreamID.Value().Value()) != CHIP_NO_ERROR) - { - ChipLogError(Zcl, "HandleSolicitOffer: VideoStreamID %u does not match AllocatedVideoStreams", - req.videoStreamID.Value().Value()); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::DynamicConstraintError); - return; - } - } + ChipLogError(Zcl, "HandleSolicitOffer: Cannot have both VideoStreams/AudioStreams and VideoStreamID/AudioStreamID"); + return Status::InvalidCommand; } - // Validate AudioStreamID against AllocatedAudioStreams if present - // If present and null then a stream has to have been allocated. - // If present and not null, then the stream ID has to exist - if (req.audioStreamID.HasValue()) + // When deprecated VideoStreamID/AudioStreamID fields are not used (Rev>=2 clients), + // at least one of VideoStreams or AudioStreams must be present + if (!req.videoStreamID.HasValue() && !req.audioStreamID.HasValue()) { - if (req.audioStreamID.Value().IsNull()) + if (!req.videoStreams.HasValue() && !req.audioStreams.HasValue()) { - // Is there an allocated stream, delegate handles matching against an allocated stream in the HandleSolicitOffer method - if (!mDelegate.HasAllocatedAudioStreams()) - { - ChipLogError(Zcl, "HandleSolicitOffer: audio requested when there are no AllocatedAudioStreams"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidInState); - return; - } - } - else - { - // Delegate should validate against AllocatedVideoStreams - if (mDelegate.ValidateAudioStreamID(req.audioStreamID.Value().Value()) != CHIP_NO_ERROR) - { - ChipLogError(Zcl, "HandleSolicitOffer: AudioStreamID %u does not match AllocatedAudioStreams", - req.audioStreamID.Value().Value()); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::DynamicConstraintError); - return; - } + ChipLogError(Zcl, "HandleSolicitOffer: At least one of VideoStreams or AudioStreams must be present"); + return Status::InvalidCommand; } } + // Normalize inputs to vectors + Optional> videoStreams; + Optional> audioStreams; + + // Validate deprecated VideoStreamID field + status = ValidateStreamID("HandleSolicitOffer", req.videoStreamID, videoStreams, StreamType::kVideo); + if (status != Status::Success) + { + return status; + } + + // Validate deprecated AudioStreamID field + status = ValidateStreamID("HandleSolicitOffer", req.audioStreamID, audioStreams, StreamType::kAudio); + if (status != Status::Success) + { + return status; + } + + // Validate VideoStreams array if present + status = ValidateStreams("HandleSolicitOffer", req.videoStreams, videoStreams, StreamType::kVideo); + if (status != Status::Success) + { + return status; + } + + // Validate AudioStreams array if present + status = ValidateStreams("HandleSolicitOffer", req.audioStreams, audioStreams, StreamType::kAudio); + if (status != Status::Success) + { + return status; + } + if (req.SFrameConfig.HasValue()) { const auto & sframeConfig = req.SFrameConfig.Value(); @@ -633,8 +718,7 @@ void WebRTCTransportProviderServer::HandleSolicitOffer(HandlerContext & ctx, con if (err != CHIP_NO_ERROR) { ChipLogError(Zcl, "HandleSolicitOffer: SFrame configuration validation failed: %" CHIP_ERROR_FORMAT, err.Format()); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::DynamicConstraintError); - return; + return Status::DynamicConstraintError; } } @@ -643,18 +727,16 @@ void WebRTCTransportProviderServer::HandleSolicitOffer(HandlerContext & ctx, con status = CheckTurnsOrStunsRequiresUTCTime("HandleSolicitOffer", req.ICEServers); if (status != Status::Success) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); - return; + return status; } // Check resource management and stream priorities. If the IDs are null the delegate will populate with - // a stream that matches the stream usage - CHIP_ERROR err = mDelegate.ValidateStreamUsage(req.streamUsage, videoStreamID, audioStreamID); + // a stream that matches the stream usage. + CHIP_ERROR err = mDelegate.ValidateStreamUsage(req.streamUsage, videoStreams, audioStreams); if (err != CHIP_NO_ERROR) { ChipLogError(Zcl, "HandleSolicitOffer: Cannot provide the stream usage requested"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::DynamicConstraintError); - return; + return Status::DynamicConstraintError; } // Prepare the arguments for the delegate. @@ -664,15 +746,15 @@ void WebRTCTransportProviderServer::HandleSolicitOffer(HandlerContext & ctx, con if (err != CHIP_NO_ERROR) { ChipLogError(Zcl, "HandleSolicitOffer: Cannot generate session ID: %" CHIP_ERROR_FORMAT, err.Format()); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::ClusterStatusCode(err)); - return; + return err; } + args.sessionId = sessionId; args.streamUsage = req.streamUsage; - args.videoStreamId = videoStreamID; - args.audioStreamId = audioStreamID; - args.peerNodeId = GetNodeIdFromCtx(ctx.mCommandHandler); - args.fabricIndex = ctx.mCommandHandler.GetAccessingFabricIndex(); + args.videoStreams = videoStreams; + args.audioStreams = audioStreams; + args.peerNodeId = GetNodeIdFromCtx(commandHandler); + args.fabricIndex = commandHandler.GetAccessingFabricIndex(); args.originatingEndpointId = req.originatingEndpointID; if (req.SFrameConfig.HasValue()) @@ -692,6 +774,11 @@ void WebRTCTransportProviderServer::HandleSolicitOffer(HandlerContext & ctx, con localIceServers.push_back(std::move(iter.GetValue())); } + if (iter.GetStatus() != CHIP_NO_ERROR) + { + return Status::InvalidCommand; + } + args.iceServers.SetValue(std::move(localIceServers)); } @@ -706,7 +793,8 @@ void WebRTCTransportProviderServer::HandleSolicitOffer(HandlerContext & ctx, con // The delegate implementation SHALL: // - Populate a new WebRTCSessionStruct with the requested values. // - If in standby mode, set deferredOffer to true (and perform steps to exit standby within 30 seconds). - // - If not in standby mode, ensure that VideoStreamID and AudioStreamID are valid (or allocate/select new streams if null). + // - If not in standby mode, ensure that VideoStreamID and AudioStreamID or videoStreams and audioStreams are valid (or + // allocate/select new streams if null). // - Internally increment the ReferenceCount on any used video/audio streams. // - If resources cannot be allocated, invoke End with Reason OutOfResources. WebRTCSessionStruct outSession; @@ -716,8 +804,7 @@ void WebRTCTransportProviderServer::HandleSolicitOffer(HandlerContext & ctx, con Protocols::InteractionModel::ClusterStatusCode(mDelegate.HandleSolicitOffer(args, outSession, deferredOffer)); if (!delegateStatus.IsSuccess()) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, delegateStatus); - return; + return delegateStatus; } // Store or update the session. @@ -747,17 +834,20 @@ void WebRTCTransportProviderServer::HandleSolicitOffer(HandlerContext & ctx, con resp.audioStreamID.SetValue(outSession.audioStreamID); } - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, resp); + ConcreteCommandPath requestPath(mPath.mEndpointId, Id, Commands::SolicitOffer::Id); + commandHandler.AddResponse(requestPath, resp); + + return std::nullopt; } -void WebRTCTransportProviderServer::HandleProvideOffer(HandlerContext & ctx, const Commands::ProvideOffer::DecodableType & req) +std::optional +WebRTCTransportProviderCluster::HandleProvideOffer(CommandHandler & commandHandler, + const Commands::ProvideOffer::DecodableType & req) { auto webRTCSessionID = req.webRTCSessionID; - auto videoStreamID = req.videoStreamID; - auto audioStreamID = req.audioStreamID; - NodeId peerNodeId = GetNodeIdFromCtx(ctx.mCommandHandler); - FabricIndex peerFabricIndex = ctx.mCommandHandler.GetAccessingFabricIndex(); + NodeId peerNodeId = GetNodeIdFromCtx(commandHandler); + FabricIndex peerFabricIndex = commandHandler.GetAccessingFabricIndex(); WebRTCSessionStruct outSession; @@ -770,16 +860,15 @@ void WebRTCTransportProviderServer::HandleProvideOffer(HandlerContext & ctx, con if (req.streamUsage == StreamUsageEnum::kUnknownEnumValue) { ChipLogError(Zcl, "HandleProvideOffer: Invalid streamUsage value %u.", to_underlying(req.streamUsage)); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; + return Status::ConstraintError; } - // At least one of Video Stream ID and Audio Stream ID must be present - if (!req.videoStreamID.HasValue() && !req.audioStreamID.HasValue()) + // At least one of Video Stream ID, Audio Stream ID, AudioStreamID or VideoStreams has to be present + if (!req.videoStreamID.HasValue() && !req.audioStreamID.HasValue() && !req.videoStreams.HasValue() && + !req.audioStreams.HasValue()) { - ChipLogError(Zcl, "HandleProvideOffer: one of VideoStreamID or AudioStreamID must be present"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - return; + ChipLogError(Zcl, "HandleProvideOffer: one of VideoStreamID, AudioStreamID, VideoStreams, AudioStreams must be present"); + return Status::InvalidCommand; } if (req.SFrameConfig.HasValue()) @@ -787,8 +876,7 @@ void WebRTCTransportProviderServer::HandleProvideOffer(HandlerContext & ctx, con if (!SFrameFollowsSpecConstraints(req.SFrameConfig.Value())) { ChipLogError(Zcl, "HandleProvideOffer: SFrame spec constraint validation failed"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; + return Status::ConstraintError; } } @@ -800,8 +888,7 @@ void WebRTCTransportProviderServer::HandleProvideOffer(HandlerContext & ctx, con Status validationStatus = ICEServersFollowsSpecConstraints(req.ICEServers.Value(), "HandleProvideOffer"); if (validationStatus != Status::Success) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, validationStatus); - return; + return validationStatus; } } @@ -811,12 +898,15 @@ void WebRTCTransportProviderServer::HandleProvideOffer(HandlerContext & ctx, con if (req.ICETransportPolicy.Value().size() > 16) { ChipLogError(Zcl, "HandleProvideOffer: ICETransportPolicy exceeds maximum length of 16"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; + return Status::ConstraintError; } } - // ===== Cluster logic starts here ===== + // ===== Cluster logic starts here (Effect on Receipt) ===== + + // Declare stream variables at function scope for use throughout the function + Optional> videoStreams; + Optional> audioStreams; // If WebRTCSessionID is not null: // - If it does not match a value in CurrentSessions: Respond with NOT_FOUND @@ -826,11 +916,10 @@ void WebRTCTransportProviderServer::HandleProvideOffer(HandlerContext & ctx, con if (!webRTCSessionID.IsNull()) { uint16_t sessionId = webRTCSessionID.Value(); - WebRTCSessionStruct * existingSession = CheckForMatchingSession(ctx, sessionId); + WebRTCSessionStruct * existingSession = CheckForMatchingSession(commandHandler, sessionId); if (existingSession == nullptr) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); - return; + return Status::NotFound; } // Use the existing session for further processing (re-offer case). @@ -838,6 +927,28 @@ void WebRTCTransportProviderServer::HandleProvideOffer(HandlerContext & ctx, con // re-use the same session id for offer processing in delegate args.sessionId = sessionId; + + // For re-offers, populate videoStreams/audioStreams from the deprecated fields if provided. + // This allows the re-offer to keep or change the stream assignments. + if (req.videoStreamID.HasValue()) + { + std::vector streams; + if (!req.videoStreamID.Value().IsNull()) + { + streams.push_back(req.videoStreamID.Value().Value()); + } + videoStreams.SetValue(std::move(streams)); + } + + if (req.audioStreamID.HasValue()) + { + std::vector streams; + if (!req.audioStreamID.Value().IsNull()) + { + streams.push_back(req.audioStreamID.Value().Value()); + } + audioStreams.SetValue(std::move(streams)); + } } else { @@ -847,80 +958,71 @@ void WebRTCTransportProviderServer::HandleProvideOffer(HandlerContext & ctx, con Status status = CheckPrivacyModes("HandleProvideOffer", req.streamUsage); if (status != Status::Success) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); - return; + return status; } // Validate that the StreamUsage is in the StreamUsagePriorities list if (mDelegate.IsStreamUsageSupported(req.streamUsage) != CHIP_NO_ERROR) { ChipLogError(Zcl, "HandleProvideOffer: StreamUsage %u is not in StreamUsagePriorities", to_underlying(req.streamUsage)); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::DynamicConstraintError); - return; + return Status::DynamicConstraintError; } - // If VideoStreamID is present and is not null and does not match a value in AllocatedVideoStreams: - // Fail the command with the status code DYNAMIC_CONSTRAINT_ERROR - if (videoStreamID.HasValue() && !videoStreamID.Value().IsNull()) + // If the VideoStreams or AudioStreams fields are present, and the VideoStreamID or AudioStreamID + // fields are present, fail the command with INVALID_COMMAND + if ((req.videoStreams.HasValue() || req.audioStreams.HasValue()) && + (req.videoStreamID.HasValue() || req.audioStreamID.HasValue())) { - if (mDelegate.ValidateVideoStreamID(videoStreamID.Value().Value()) != CHIP_NO_ERROR) - { - ChipLogError(Zcl, "HandleProvideOffer: VideoStreamID %u does not match AllocatedVideoStreams", - videoStreamID.Value().Value()); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::DynamicConstraintError); - return; - } + ChipLogError(Zcl, "HandleProvideOffer: Cannot have both VideoStreams/AudioStreams and VideoStreamID/AudioStreamID"); + return Status::InvalidCommand; } - // If VideoStreamID is present and is null: - // If AllocatedVideoStreams is empty: Fail the command with the status code INVALID_IN_STATE - // Automatically select an existing video stream per the Resource Management and Stream Priorities. - if (videoStreamID.HasValue() && videoStreamID.Value().IsNull()) + // When deprecated VideoStreamID/AudioStreamID fields are not used (Rev>=2 clients), + // at least one of VideoStreams or AudioStreams must be present + if (!req.videoStreamID.HasValue() && !req.audioStreamID.HasValue()) { - if (!mDelegate.HasAllocatedVideoStreams()) + if (!req.videoStreams.HasValue() && !req.audioStreams.HasValue()) { - ChipLogError(Zcl, "HandleProvideOffer: AllocatedVideoStreams is empty"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidInState); - return; + ChipLogError(Zcl, "HandleProvideOffer: At least one of VideoStreams or AudioStreams must be present"); + return Status::InvalidCommand; } - // Automatic selection will be handled by the delegate in HandleProvideOffer. } - // If AudioStreamID is present and is not null and does not match a value in AllocatedAudioStreams: - // Fail the command with the status code DYNAMIC_CONSTRAINT_ERROR - if (audioStreamID.HasValue() && !audioStreamID.Value().IsNull()) + // Validate deprecated VideoStreamID field + status = ValidateStreamID("HandleProvideOffer", req.videoStreamID, videoStreams, StreamType::kVideo); + if (status != Status::Success) { - if (mDelegate.ValidateAudioStreamID(audioStreamID.Value().Value()) != CHIP_NO_ERROR) - { - ChipLogError(Zcl, "HandleProvideOffer: AudioStreamID %u does not match AllocatedAudioStreams", - audioStreamID.Value().Value()); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::DynamicConstraintError); - return; - } + return status; } - // If AudioStreamID is present and is null: - // If AllocatedAudioStreams is empty: Fail the command with the status code INVALID_IN_STATE - // Automatically select an existing audio stream per the Resource Management and Stream Priorities. - if (audioStreamID.HasValue() && audioStreamID.Value().IsNull()) + // Validate deprecated AudioStreamID field + status = ValidateStreamID("HandleProvideOffer", req.audioStreamID, audioStreams, StreamType::kAudio); + if (status != Status::Success) { - if (!mDelegate.HasAllocatedAudioStreams()) - { - ChipLogError(Zcl, "HandleProvideOffer: AllocatedAudioStreams is empty"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidInState); - return; - } - // Automatic selection will be handled by the delegate in HandleProvideOffer. + return status; + } + + // Validate VideoStreams array if present + status = ValidateStreams("HandleProvideOffer", req.videoStreams, videoStreams, StreamType::kVideo); + if (status != Status::Success) + { + return status; + } + + // Validate AudioStreams array if present + status = ValidateStreams("HandleProvideOffer", req.audioStreams, audioStreams, StreamType::kAudio); + if (status != Status::Success) + { + return status; } // If not able to meet the Resource Management and Stream Priorities conditions or unable to provide another WebRTC session: // Respond with a response status of RESOURCE_EXHAUSTED - CHIP_ERROR err = mDelegate.ValidateStreamUsage(req.streamUsage, videoStreamID, audioStreamID); + CHIP_ERROR err = mDelegate.ValidateStreamUsage(req.streamUsage, videoStreams, audioStreams); if (err != CHIP_NO_ERROR) { ChipLogError(Zcl, "HandleProvideOffer: Cannot provide stream usage requested"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ResourceExhausted); - return; + return Status::ResourceExhausted; } // If SFrameConfig is present: @@ -935,8 +1037,7 @@ void WebRTCTransportProviderServer::HandleProvideOffer(HandlerContext & ctx, con if (err != CHIP_NO_ERROR) { ChipLogError(Zcl, "HandleProvideOffer: SFrame configuration validation failed: %" CHIP_ERROR_FORMAT, err.Format()); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::DynamicConstraintError); - return; + return Status::DynamicConstraintError; } } @@ -946,8 +1047,7 @@ void WebRTCTransportProviderServer::HandleProvideOffer(HandlerContext & ctx, con status = CheckTurnsOrStunsRequiresUTCTime("HandleProvideOffer", req.ICEServers); if (status != Status::Success) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); - return; + return status; } // Generate new session id @@ -956,15 +1056,14 @@ void WebRTCTransportProviderServer::HandleProvideOffer(HandlerContext & ctx, con if (err != CHIP_NO_ERROR) { ChipLogError(Zcl, "HandleProvideOffer: Cannot generate session ID: %" CHIP_ERROR_FORMAT, err.Format()); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::ClusterStatusCode(err)); - return; + return err; } args.sessionId = sessionId; } args.streamUsage = req.streamUsage; - args.videoStreamId = videoStreamID; - args.audioStreamId = audioStreamID; + args.videoStreams = videoStreams; + args.audioStreams = audioStreams; args.peerNodeId = peerNodeId; args.fabricIndex = peerFabricIndex; args.sdp = std::string(req.sdp.data(), req.sdp.size()); @@ -986,6 +1085,11 @@ void WebRTCTransportProviderServer::HandleProvideOffer(HandlerContext & ctx, con localIceServers.push_back(std::move(iter.GetValue())); } + if (iter.GetStatus() != CHIP_NO_ERROR) + { + return Status::InvalidCommand; + } + args.iceServers.SetValue(std::move(localIceServers)); } @@ -1000,8 +1104,7 @@ void WebRTCTransportProviderServer::HandleProvideOffer(HandlerContext & ctx, con auto delegateStatus = Protocols::InteractionModel::ClusterStatusCode(mDelegate.HandleProvideOffer(args, outSession)); if (!delegateStatus.IsSuccess()) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, delegateStatus); - return; + return delegateStatus; } // Update/Insert the WebRTCSessionStruct in CurrentSessions. @@ -1023,29 +1126,32 @@ void WebRTCTransportProviderServer::HandleProvideOffer(HandlerContext & ctx, con resp.audioStreamID.SetValue(outSession.audioStreamID); } - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, resp); + ConcreteCommandPath requestPath(mPath.mEndpointId, Id, Commands::ProvideOffer::Id); + commandHandler.AddResponse(requestPath, resp); + + return std::nullopt; } -void WebRTCTransportProviderServer::HandleProvideAnswer(HandlerContext & ctx, const Commands::ProvideAnswer::DecodableType & req) +std::optional +WebRTCTransportProviderCluster::HandleProvideAnswer(CommandHandler & commandHandler, + const Commands::ProvideAnswer::DecodableType & req) { - // Extract command fields from the request. uint16_t sessionId = req.webRTCSessionID; auto sdpSpan = req.sdp; - WebRTCSessionStruct * existingSession = CheckForMatchingSession(ctx, sessionId); + WebRTCSessionStruct * existingSession = CheckForMatchingSession(commandHandler, sessionId); if (existingSession == nullptr) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); - return; + return Status::NotFound; } std::string sdpAnswer(sdpSpan.data(), sdpSpan.size()); - ctx.mCommandHandler.AddStatus( - ctx.mRequestPath, Protocols::InteractionModel::ClusterStatusCode(mDelegate.HandleProvideAnswer(sessionId, sdpAnswer))); + return mDelegate.HandleProvideAnswer(sessionId, sdpAnswer); } -void WebRTCTransportProviderServer::HandleProvideICECandidates(HandlerContext & ctx, - const Commands::ProvideICECandidates::DecodableType & req) +std::optional +WebRTCTransportProviderCluster::HandleProvideICECandidates(CommandHandler & commandHandler, + const Commands::ProvideICECandidates::DecodableType & req) { // Extract command fields from the request. uint16_t sessionId = req.webRTCSessionID; @@ -1061,8 +1167,7 @@ void WebRTCTransportProviderServer::HandleProvideICECandidates(HandlerContext & if (!candidate.SDPMid.IsNull() && candidate.SDPMid.Value().empty()) { ChipLogError(Zcl, "HandleProvideICECandidates: SDPMid must have minimum length of 1 when present"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; + return Status::ConstraintError; } candidates.push_back(candidate); @@ -1073,24 +1178,21 @@ void WebRTCTransportProviderServer::HandleProvideICECandidates(HandlerContext & if (listErr != CHIP_NO_ERROR) { ChipLogError(Zcl, "HandleProvideICECandidates: ICECandidates list error: %" CHIP_ERROR_FORMAT, listErr.Format()); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - return; + return Status::InvalidCommand; } - WebRTCSessionStruct * existingSession = CheckForMatchingSession(ctx, sessionId); + WebRTCSessionStruct * existingSession = CheckForMatchingSession(commandHandler, sessionId); if (existingSession == nullptr) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); - return; + return Status::NotFound; } // Delegate the handling of ICE candidates. - ctx.mCommandHandler.AddStatus( - ctx.mRequestPath, - Protocols::InteractionModel::ClusterStatusCode(mDelegate.HandleProvideICECandidates(sessionId, candidates))); + return mDelegate.HandleProvideICECandidates(sessionId, candidates); } -void WebRTCTransportProviderServer::HandleEndSession(HandlerContext & ctx, const Commands::EndSession::DecodableType & req) +std::optional +WebRTCTransportProviderCluster::HandleEndSession(CommandHandler & commandHandler, const Commands::EndSession::DecodableType & req) { // Extract command fields from the request. uint16_t sessionId = req.webRTCSessionID; @@ -1100,37 +1202,25 @@ void WebRTCTransportProviderServer::HandleEndSession(HandlerContext & ctx, const if (reason == WebRTCEndReasonEnum::kUnknownEnumValue) { ChipLogError(Zcl, "HandleEndSession: Invalid reason value %u.", to_underlying(reason)); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); - return; + return Status::ConstraintError; } - WebRTCSessionStruct * existingSession = CheckForMatchingSession(ctx, sessionId); + WebRTCSessionStruct * existingSession = CheckForMatchingSession(commandHandler, sessionId); if (existingSession == nullptr) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); - return; + return Status::NotFound; } // Delegate handles decrementing reference counts on video/audio streams if applicable. - CHIP_ERROR err = mDelegate.HandleEndSession(sessionId, reason, existingSession->videoStreamID, existingSession->audioStreamID); - - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::ClusterStatusCode(err)); + CHIP_ERROR err = mDelegate.HandleEndSession(sessionId, reason); // Remove the session entry from CurrentSessions. RemoveSession(sessionId); + + return err; } } // namespace WebRTCTransportProvider } // namespace Clusters } // namespace app } // namespace chip - -void MatterWebRTCTransportProviderPluginServerInitCallback() -{ - ChipLogProgress(Zcl, "Initializing WebRTC Transport Provider cluster."); -} - -void MatterWebRTCTransportProviderPluginServerShutdownCallback() -{ - ChipLogProgress(Zcl, "Shutdown WebRTC Transport Provider cluster."); -} diff --git a/src/app/clusters/webrtc-transport-provider-server/webrtc-transport-provider-server.h b/src/app/clusters/webrtc-transport-provider-server/WebRTCTransportProviderCluster.h similarity index 73% rename from src/app/clusters/webrtc-transport-provider-server/webrtc-transport-provider-server.h rename to src/app/clusters/webrtc-transport-provider-server/WebRTCTransportProviderCluster.h index c8c8c406ccd..9863b40a46b 100644 --- a/src/app/clusters/webrtc-transport-provider-server/webrtc-transport-provider-server.h +++ b/src/app/clusters/webrtc-transport-provider-server/WebRTCTransportProviderCluster.h @@ -17,10 +17,11 @@ */ #pragma once -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include @@ -50,8 +51,8 @@ class Delegate { uint16_t sessionId; StreamUsageEnum streamUsage; - Optional> videoStreamId; - Optional> audioStreamId; + Optional> videoStreams; + Optional> audioStreams; Optional sFrameConfig; Optional> iceServers; Optional iceTransportPolicy; @@ -119,8 +120,8 @@ class Delegate * * @param[in] args * Contains all input arguments for the command, including the SDP Offer, session usage, etc. - * If the video stream ID is missing, the delegate MUST automatically select a matching video stream. - * If the audio stream ID is missing, the delegate MUST automatically select a matching audio stream. + * If the video streams are missing, the delegate MUST automatically select matching video streams. + * If the audio streams are missing, the delegate MUST automatically select matching audio streams. * In either case, upon successful selection, the delegate is responsible for internally incrementing * the reference count on any used video and audio streams. * @@ -181,16 +182,12 @@ class Delegate * * @param[in] sessionId The ID of the session to end. * @param[in] reasonCode Reason for ending the session (e.g. normal closure, resource limit). - * @param[in] videoStreamID The nullable ID of the video stream associated with the session. - * @param[in] audioStreamID The nullable ID of the audio stream associated with the session. * * @return CHIP_ERROR * - CHIP_NO_ERROR on success * - Error if no matching session is found or some cleanup error occurs */ - virtual CHIP_ERROR HandleEndSession(uint16_t sessionId, WebRTCEndReasonEnum reasonCode, - DataModel::Nullable videoStreamID, - DataModel::Nullable audioStreamID) = 0; + virtual CHIP_ERROR HandleEndSession(uint16_t sessionId, WebRTCEndReasonEnum reasonCode) = 0; /** * @brief Validates the requested stream usage against the camera's resource management @@ -202,14 +199,14 @@ class Delegate * - If the provided IDs are null, it matches against an allocated stream with the same stream usage * and updates the IDs to those for the matching stream * - * @param[in] streamUsage The desired usage type for the stream (e.g. live view, recording, etc.). - * @param[in,out] videoStreamId Optional identifier for the requested video stream. - * @param[in,out] audioStreamId Optional identifier for the requested audio stream. + * @param[in] streamUsage The desired usage type for the stream (e.g. live view, recording, etc.). + * @param[in,out] videoStreams Optional array of video stream IDs. + * @param[in,out] audioStreams Optional array of audio stream IDs. * * @return CHIP_ERROR CHIP_NO_ERROR if the stream usage is valid; an appropriate error code otherwise. */ - virtual CHIP_ERROR ValidateStreamUsage(StreamUsageEnum streamUsage, Optional> & videoStreamId, - Optional> & audioStreamId) = 0; + virtual CHIP_ERROR ValidateStreamUsage(StreamUsageEnum streamUsage, Optional> & videoStreams, + Optional> & audioStreams) = 0; /** * @brief @@ -243,6 +240,38 @@ class Delegate */ virtual CHIP_ERROR ValidateAudioStreamID(uint16_t audioStreamId) = 0; + /** + * @brief + * Validates that the given VideoStreams match values in AllocatedVideoStreams. + * + * This method is called during SolicitOffer command processing when VideoStreams + * is present and not null. The implementation must check if each provided IDs exist + * in the AllocatedVideoStreams list from the CameraAvStreamManagement cluster. + * + * @param[in] videoStreams The video streams to validate. + * + * @return CHIP_ERROR + * - CHIP_NO_ERROR if the VideoStreams are valid and match AllocatedVideoStreams. + * - CHIP_ERROR_NOT_FOUND or other appropriate error if validation fails or a match can't be found + */ + virtual CHIP_ERROR ValidateVideoStreams(const std::vector & videoStreams) = 0; + + /** + * @brief + * Validates that the given AudioStreams match values in AllocatedAudioStreams. + * + * This method is called during SolicitOffer command processing when AudioStreams + * is present and not null. The implementation must check if each provided IDs exist + * in the AllocatedAudioStreams list from the CameraAvStreamManagement cluster. + * + * @param[in] audioStreams The audio streams to validate. + * + * @return CHIP_ERROR + * - CHIP_NO_ERROR if the AudioStreams are valid and match AllocatedAudioStreams. + * - CHIP_ERROR_NOT_FOUND or other appropriate error if validation fails. + */ + virtual CHIP_ERROR ValidateAudioStreams(const std::vector & audioStreams) = 0; + /** * @brief * Checks if the given StreamUsage is in the StreamUsagePriorities list. @@ -347,40 +376,31 @@ class Delegate virtual CHIP_ERROR IsUTCTimeNull(bool & isNull) = 0; }; -class WebRTCTransportProviderServer : public AttributeAccessInterface, public CommandHandlerInterface +class WebRTCTransportProviderCluster : public DefaultServerCluster { public: /** * @brief - * Constructs the WebRTCTransportProviderServer with the specified delegate and endpoint. + * Constructs the WebRTCTransportProviderCluster with the specified delegate and endpoint. * + * @param[in] endpointId The Endpoint where the WebRTC Transport Provider cluster is published. * @param[in] delegate A reference to an implementation of the Delegate interface. Must remain * valid for the lifetime of this object. - * @param[in] endpointId The Endpoint where the WebRTC Transport Provider cluster is published. */ - WebRTCTransportProviderServer(Delegate & delegate, EndpointId endpointId); + WebRTCTransportProviderCluster(EndpointId endpointId, Delegate & delegate); - /** - * @brief - * Destructor. Cleans up any internal data, including unregistering the command handler and attribute interface, - * but does not destroy the delegate. - */ - ~WebRTCTransportProviderServer() override; + DataModel::ActionReturnStatus ReadAttribute(const DataModel::ReadAttributeRequest & request, + AttributeValueEncoder & encoder) override; - /** - * @brief - * Registers the command handler and attribute interface with the Matter Stack. - * @return CHIP_ERROR - * - CHIP_NO_ERROR on successful registration. - * - Other CHIP_ERROR codes if registration fails. - */ - CHIP_ERROR Init(); + std::optional InvokeCommand(const DataModel::InvokeRequest & request, + TLV::TLVReader & input_arguments, CommandHandler * handler) override; - /** - * @brief - * Handles any cleanup required on the instance or app/delegate prior to the destructor being called. - */ - void Shutdown(){}; + CHIP_ERROR AcceptedCommands(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) override; + + CHIP_ERROR GeneratedCommands(const ConcreteClusterPath & path, ReadOnlyBufferBuilder & builder) override; + + CHIP_ERROR Attributes(const ConcreteClusterPath & path, ReadOnlyBufferBuilder & builder) override; /** * @brief Get a reference to the current WebRTC sessions. @@ -405,12 +425,18 @@ class WebRTCTransportProviderServer : public AttributeAccessInterface, public Co kUpdated = 0x01, }; - CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; - void InvokeCommand(HandlerContext & ctx) override; + enum class StreamType : uint8_t + { + kVideo = 0, + kAudio = 1, + }; + + Delegate & mDelegate; + std::vector mCurrentSessions; // Helper functions WebRTCSessionStruct * FindSession(uint16_t sessionId); - WebRTCSessionStruct * CheckForMatchingSession(HandlerContext & ctx, uint16_t sessionId); + WebRTCSessionStruct * CheckForMatchingSession(const CommandHandler & commandHandler, uint16_t sessionId); UpsertResultEnum UpsertSession(const WebRTCSessionStruct & session); CHIP_ERROR GenerateSessionId(uint16_t & outSessionId); Protocols::InteractionModel::Status CheckPrivacyModes(const char * commandName, StreamUsageEnum streamUsage); @@ -418,15 +444,36 @@ class WebRTCTransportProviderServer : public AttributeAccessInterface, public Co CheckTurnsOrStunsRequiresUTCTime(const char * commandName, const Optional> & iceServers); - // Command Handlers - void HandleSolicitOffer(HandlerContext & ctx, const Commands::SolicitOffer::DecodableType & req); - void HandleProvideOffer(HandlerContext & ctx, const Commands::ProvideOffer::DecodableType & req); - void HandleProvideAnswer(HandlerContext & ctx, const Commands::ProvideAnswer::DecodableType & req); - void HandleProvideICECandidates(HandlerContext & ctx, const Commands::ProvideICECandidates::DecodableType & req); - void HandleEndSession(HandlerContext & ctx, const Commands::EndSession::DecodableType & req); + // Stream validation helpers + Protocols::InteractionModel::Status ValidateStreamID(const char * commandName, + const Optional> & streamID, + Optional> & outStreams, StreamType streamType); - Delegate & mDelegate; - std::vector mCurrentSessions; + Protocols::InteractionModel::Status ValidateStreams(const char * commandName, + const Optional> & inStreams, + Optional> & outStreams, StreamType streamType); + + // Templated helper to decode and dispatch commands + template + __attribute__((always_inline)) std::optional + HandleCommand(TLV::TLVReader & input_arguments, FabricIndex fabricIndex, CommandHandler & handler, HandlerFunc handlerFunc) + { + DecodableType req; + ReturnErrorOnFailure(req.Decode(input_arguments, fabricIndex)); + return (this->*handlerFunc)(handler, req); + } + + // Command Handlers + std::optional HandleSolicitOffer(CommandHandler & commandHandler, + const Commands::SolicitOffer::DecodableType & req); + std::optional HandleProvideOffer(CommandHandler & commandHandler, + const Commands::ProvideOffer::DecodableType & req); + std::optional HandleProvideAnswer(CommandHandler & commandHandler, + const Commands::ProvideAnswer::DecodableType & req); + std::optional + HandleProvideICECandidates(CommandHandler & commandHandler, const Commands::ProvideICECandidates::DecodableType & req); + std::optional HandleEndSession(CommandHandler & commandHandler, + const Commands::EndSession::DecodableType & req); }; } // namespace WebRTCTransportProvider diff --git a/src/app/clusters/webrtc-transport-provider-server/app_config_dependent_sources.cmake b/src/app/clusters/webrtc-transport-provider-server/app_config_dependent_sources.cmake index f909053d5f1..4900a0d1268 100644 --- a/src/app/clusters/webrtc-transport-provider-server/app_config_dependent_sources.cmake +++ b/src/app/clusters/webrtc-transport-provider-server/app_config_dependent_sources.cmake @@ -12,10 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This is the equivalent to app_config_dependent_sources.gni +# These are the things that BUILD.gn dependencies would pull TARGET_SOURCES( ${APP_TARGET} PRIVATE - "${CLUSTER_DIR}/webrtc-transport-provider-server.cpp" - "${CLUSTER_DIR}/webrtc-transport-provider-server.h" + "${CLUSTER_DIR}/CodegenIntegration.cpp" + "${CLUSTER_DIR}/WebRTCTransportProviderCluster.cpp" + "${CLUSTER_DIR}/WebRTCTransportProviderCluster.h" ) \ No newline at end of file diff --git a/src/app/clusters/webrtc-transport-provider-server/app_config_dependent_sources.gni b/src/app/clusters/webrtc-transport-provider-server/app_config_dependent_sources.gni index c2e0719af65..cecea744d24 100644 --- a/src/app/clusters/webrtc-transport-provider-server/app_config_dependent_sources.gni +++ b/src/app/clusters/webrtc-transport-provider-server/app_config_dependent_sources.gni @@ -11,7 +11,5 @@ # 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. -app_config_dependent_sources = [ - "webrtc-transport-provider-server.cpp", - "webrtc-transport-provider-server.h", -] + +app_config_dependent_sources = [ "CodegenIntegration.cpp" ] diff --git a/examples/all-clusters-app/nxp/rt/rt1060/.gn b/src/app/clusters/webrtc-transport-provider-server/tests/BUILD.gn similarity index 55% rename from examples/all-clusters-app/nxp/rt/rt1060/.gn rename to src/app/clusters/webrtc-transport-provider-server/tests/BUILD.gn index 0985ed955a4..8f12e637006 100644 --- a/examples/all-clusters-app/nxp/rt/rt1060/.gn +++ b/src/app/clusters/webrtc-transport-provider-server/tests/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Project CHIP Authors +# Copyright (c) 2025 Project CHIP Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,21 +15,19 @@ import("//build_overrides/build.gni") import("//build_overrides/chip.gni") -# The location of the build configuration file. -buildconfig = "${build_root}/config/BUILDCONFIG.gn" +import("${chip_root}/build/chip/chip_test_suite.gni") -# CHIP uses angle bracket includes. -check_system_includes = true +chip_test_suite("tests") { + output_name = "libTestWebRTCTransportProviderCluster" -default_args = { - target_cpu = "arm" - target_os = "freertos" + test_sources = [ "TestWebRTCTransportProviderCluster.cpp" ] - import("//args.gni") + cflags = [ "-Wconversion" ] - # Import common example GN args - import("${chip_root}/examples/platform/nxp/common/gn/args.gni") - - # Import default platform configs - import("${chip_root}/src/platform/nxp/rt/rt1060/args.gni") + public_deps = [ + "${chip_root}/src/app/clusters/testing", + "${chip_root}/src/app/clusters/webrtc-transport-provider-server", + "${chip_root}/src/lib/core:string-builder-adapters", + "${chip_root}/src/lib/support", + ] } diff --git a/src/app/clusters/webrtc-transport-provider-server/tests/TestWebRTCTransportProviderCluster.cpp b/src/app/clusters/webrtc-transport-provider-server/tests/TestWebRTCTransportProviderCluster.cpp new file mode 100644 index 00000000000..893a9e56399 --- /dev/null +++ b/src/app/clusters/webrtc-transport-provider-server/tests/TestWebRTCTransportProviderCluster.cpp @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::WebRTCTransportProvider; + +using ICEServerDecodableStruct = chip::app::Clusters::Globals::Structs::ICEServerStruct::DecodableType; +using WebRTCSessionStruct = chip::app::Clusters::Globals::Structs::WebRTCSessionStruct::Type; +using ICECandidateStruct = chip::app::Clusters::Globals::Structs::ICECandidateStruct::Type; +using StreamUsageEnum = chip::app::Clusters::Globals::StreamUsageEnum; +using WebRTCEndReasonEnum = chip::app::Clusters::Globals::WebRTCEndReasonEnum; + +static constexpr chip::EndpointId kTestEndpointId = 1; + +// Mock delegate for testing WebRTCTransportProvider +class MockWebRTCTransportProviderDelegate : public Delegate +{ +public: + MockWebRTCTransportProviderDelegate() = default; + + CHIP_ERROR HandleSolicitOffer(const OfferRequestArgs & args, WebRTCSessionStruct & outSession, bool & outDeferredOffer) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR HandleProvideOffer(const ProvideOfferRequestArgs & args, WebRTCSessionStruct & outSession) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR HandleProvideAnswer(uint16_t sessionId, const std::string & sdpAnswer) override { return CHIP_NO_ERROR; } + + CHIP_ERROR HandleProvideICECandidates(uint16_t sessionId, const std::vector & candidates) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR HandleEndSession(uint16_t sessionId, WebRTCEndReasonEnum reasonCode) override { return CHIP_NO_ERROR; } + + CHIP_ERROR ValidateStreamUsage(StreamUsageEnum streamUsage, Optional> & videoStreams, + Optional> & audioStreams) override + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR ValidateVideoStreamID(uint16_t videoStreamId) override { return CHIP_NO_ERROR; } + + CHIP_ERROR ValidateAudioStreamID(uint16_t audioStreamId) override { return CHIP_NO_ERROR; } + + CHIP_ERROR ValidateVideoStreams(const std::vector & videoStreams) override { return CHIP_NO_ERROR; } + + CHIP_ERROR ValidateAudioStreams(const std::vector & audioStreams) override { return CHIP_NO_ERROR; } + + CHIP_ERROR IsStreamUsageSupported(Globals::StreamUsageEnum streamUsage) override { return CHIP_NO_ERROR; } + + CHIP_ERROR IsHardPrivacyModeActive(bool & isActive) override + { + isActive = false; + return CHIP_NO_ERROR; + } + + CHIP_ERROR IsSoftRecordingPrivacyModeActive(bool & isActive) override + { + isActive = false; + return CHIP_NO_ERROR; + } + + CHIP_ERROR IsSoftLivestreamPrivacyModeActive(bool & isActive) override + { + isActive = false; + return CHIP_NO_ERROR; + } + + bool HasAllocatedVideoStreams() override { return true; } + + bool HasAllocatedAudioStreams() override { return true; } + + CHIP_ERROR ValidateSFrameConfig(uint16_t cipherSuite, size_t baseKeyLength) override { return CHIP_NO_ERROR; } + + CHIP_ERROR IsUTCTimeNull(bool & isNull) override + { + isNull = false; + return CHIP_NO_ERROR; + } +}; + +// initialize memory as ReadOnlyBufferBuilder may allocate +struct TestWebRTCTransportProviderCluster : public ::testing::Test +{ + static void SetUpTestSuite() { ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR); } + static void TearDownTestSuite() { chip::Platform::MemoryShutdown(); } +}; + +TEST_F(TestWebRTCTransportProviderCluster, TestAttributes) +{ + MockWebRTCTransportProviderDelegate mockDelegate; + WebRTCTransportProviderCluster server(kTestEndpointId, mockDelegate); + + auto globals = chip::app::DefaultServerCluster::GlobalAttributes(); + std::vector expected; + expected.reserve(1 + globals.size()); + expected.push_back(WebRTCTransportProvider::Attributes::CurrentSessions::kMetadataEntry); + for (const auto & entry : globals) + { + expected.push_back(entry); + } + + ASSERT_TRUE(Testing::IsAttributesListEqualTo( + server, chip::Span(expected.data(), expected.size()))); +} + +TEST_F(TestWebRTCTransportProviderCluster, TestCommands) +{ + MockWebRTCTransportProviderDelegate mockDelegate; + WebRTCTransportProviderCluster server(kTestEndpointId, mockDelegate); + + std::vector expected = { + WebRTCTransportProvider::Commands::SolicitOffer::kMetadataEntry, + WebRTCTransportProvider::Commands::ProvideOffer::kMetadataEntry, + WebRTCTransportProvider::Commands::ProvideAnswer::kMetadataEntry, + WebRTCTransportProvider::Commands::ProvideICECandidates::kMetadataEntry, + WebRTCTransportProvider::Commands::EndSession::kMetadataEntry, + }; + ASSERT_TRUE(Testing::IsAcceptedCommandsListEqualTo( + server, chip::Span(expected.data(), expected.size()))); +} + +TEST_F(TestWebRTCTransportProviderCluster, TestCurrentSessionsAttribute) +{ + MockWebRTCTransportProviderDelegate mockDelegate; + WebRTCTransportProviderCluster server(kTestEndpointId, mockDelegate); + + // Initially, no sessions should exist + auto sessions = server.GetCurrentSessions(); + EXPECT_TRUE(sessions.empty()); +} + +TEST_F(TestWebRTCTransportProviderCluster, TestSessionManagement) +{ + MockWebRTCTransportProviderDelegate mockDelegate; + WebRTCTransportProviderCluster server(kTestEndpointId, mockDelegate); + + // Verify initial state + auto sessions = server.GetCurrentSessions(); + EXPECT_TRUE(sessions.empty()); + + // Test that RemoveSession on non-existent session is safe + server.RemoveSession(999); + sessions = server.GetCurrentSessions(); + EXPECT_TRUE(sessions.empty()); +} + +TEST_F(TestWebRTCTransportProviderCluster, TestReadCurrentSessionsAttribute) +{ + MockWebRTCTransportProviderDelegate mockDelegate; + WebRTCTransportProviderCluster server(kTestEndpointId, mockDelegate); + + // Create a mock attribute request for CurrentSessions + chip::app::DataModel::ReadAttributeRequest request; + request.path.mEndpointId = kTestEndpointId; + request.path.mClusterId = WebRTCTransportProvider::Id; + request.path.mAttributeId = WebRTCTransportProvider::Attributes::CurrentSessions::Id; + + // Create a buffer for encoding + chip::Platform::ScopedMemoryBufferWithSize buffer; + ASSERT_TRUE(buffer.Alloc(1024)); + chip::TLV::TLVWriter writer; + writer.Init(buffer.Get(), buffer.AllocatedSize()); + + // Create AttributeReportIBs::Builder for the encoder + chip::app::AttributeReportIBs::Builder attributeReportIBsBuilder; + chip::TLV::TLVWriter reportWriter; + reportWriter.Init(buffer.Get(), buffer.AllocatedSize()); + CHIP_ERROR err = attributeReportIBsBuilder.Init(&reportWriter); + ASSERT_EQ(err, CHIP_NO_ERROR); + + chip::app::AttributeValueEncoder encoder(attributeReportIBsBuilder, chip::Access::SubjectDescriptor{}, request.path, + 0 /* dataVersion */); + + // Test reading empty sessions + auto status = server.ReadAttribute(request, encoder); + EXPECT_TRUE(status.IsSuccess()); +} + +TEST_F(TestWebRTCTransportProviderCluster, TestReadClusterRevisionAttribute) +{ + MockWebRTCTransportProviderDelegate mockDelegate; + WebRTCTransportProviderCluster server(kTestEndpointId, mockDelegate); + + // Create a mock attribute request for ClusterRevision + chip::app::DataModel::ReadAttributeRequest request; + request.path.mEndpointId = kTestEndpointId; + request.path.mClusterId = WebRTCTransportProvider::Id; + request.path.mAttributeId = chip::app::Clusters::Globals::Attributes::ClusterRevision::Id; + + // Create a buffer for encoding + chip::Platform::ScopedMemoryBufferWithSize buffer; + ASSERT_TRUE(buffer.Alloc(1024)); + + // Create AttributeReportIBs::Builder for the encoder + chip::app::AttributeReportIBs::Builder attributeReportIBsBuilder; + chip::TLV::TLVWriter reportWriter; + reportWriter.Init(buffer.Get(), buffer.AllocatedSize()); + CHIP_ERROR err = attributeReportIBsBuilder.Init(&reportWriter); + ASSERT_EQ(err, CHIP_NO_ERROR); + + chip::app::AttributeValueEncoder encoder(attributeReportIBsBuilder, chip::Access::SubjectDescriptor{}, request.path, + 0 /* dataVersion */); + + // Test reading cluster revision + auto status = server.ReadAttribute(request, encoder); + EXPECT_TRUE(status.IsSuccess()); +} + +TEST_F(TestWebRTCTransportProviderCluster, TestReadUnsupportedAttribute) +{ + MockWebRTCTransportProviderDelegate mockDelegate; + WebRTCTransportProviderCluster server(kTestEndpointId, mockDelegate); + + // Create a mock attribute request for an unsupported attribute + chip::app::DataModel::ReadAttributeRequest request; + request.path.mEndpointId = kTestEndpointId; + request.path.mClusterId = WebRTCTransportProvider::Id; + request.path.mAttributeId = 0xFFFF; // Invalid attribute ID + + // Create a buffer for encoding + chip::Platform::ScopedMemoryBufferWithSize buffer; + ASSERT_TRUE(buffer.Alloc(1024)); + + // Create AttributeReportIBs::Builder for the encoder + chip::app::AttributeReportIBs::Builder attributeReportIBsBuilder; + chip::TLV::TLVWriter reportWriter; + reportWriter.Init(buffer.Get(), buffer.AllocatedSize()); + CHIP_ERROR err = attributeReportIBsBuilder.Init(&reportWriter); + ASSERT_EQ(err, CHIP_NO_ERROR); + + chip::app::AttributeValueEncoder encoder(attributeReportIBsBuilder, chip::Access::SubjectDescriptor{}, request.path, + 0 /* dataVersion */); + + // Test reading unsupported attribute + auto status = server.ReadAttribute(request, encoder); + EXPECT_EQ(status, chip::Protocols::InteractionModel::Status::UnsupportedAttribute); +} + +} // namespace diff --git a/src/app/clusters/webrtc-transport-requestor-server/BUILD.gn b/src/app/clusters/webrtc-transport-requestor-server/BUILD.gn index 769ac903b81..15ea17d7d81 100644 --- a/src/app/clusters/webrtc-transport-requestor-server/BUILD.gn +++ b/src/app/clusters/webrtc-transport-requestor-server/BUILD.gn @@ -16,8 +16,8 @@ import("//build_overrides/chip.gni") source_set("webrtc-transport-requestor-server") { sources = [ - "webrtc-transport-requestor-cluster.cpp", - "webrtc-transport-requestor-cluster.h", + "WebRTCTransportRequestorCluster.cpp", + "WebRTCTransportRequestorCluster.h", ] public_deps = [ diff --git a/src/app/clusters/webrtc-transport-requestor-server/webrtc-transport-requestor-cluster.cpp b/src/app/clusters/webrtc-transport-requestor-server/WebRTCTransportRequestorCluster.cpp similarity index 62% rename from src/app/clusters/webrtc-transport-requestor-server/webrtc-transport-requestor-cluster.cpp rename to src/app/clusters/webrtc-transport-requestor-server/WebRTCTransportRequestorCluster.cpp index 9a94263aed7..a28f795df07 100644 --- a/src/app/clusters/webrtc-transport-requestor-server/webrtc-transport-requestor-cluster.cpp +++ b/src/app/clusters/webrtc-transport-requestor-server/WebRTCTransportRequestorCluster.cpp @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "webrtc-transport-requestor-cluster.h" +#include "WebRTCTransportRequestorCluster.h" #include #include @@ -30,8 +30,6 @@ using chip::Protocols::InteractionModel::Status; namespace { -constexpr uint16_t kMaxSessionId = 65534; - constexpr DataModel::AcceptedCommandEntry kAcceptedCommands[] = { Commands::Offer::kMetadataEntry, Commands::Answer::kMetadataEntry, @@ -57,12 +55,12 @@ namespace app { namespace Clusters { namespace WebRTCTransportRequestor { -WebRTCTransportRequestorServer::WebRTCTransportRequestorServer(EndpointId endpointId, Delegate & delegate) : +WebRTCTransportRequestorCluster::WebRTCTransportRequestorCluster(EndpointId endpointId, Delegate & delegate) : DefaultServerCluster({ endpointId, Id }), mDelegate(delegate) {} -DataModel::ActionReturnStatus WebRTCTransportRequestorServer::ReadAttribute(const DataModel::ReadAttributeRequest & request, - AttributeValueEncoder & encoder) +DataModel::ActionReturnStatus WebRTCTransportRequestorCluster::ReadAttribute(const DataModel::ReadAttributeRequest & request, + AttributeValueEncoder & encoder) { switch (request.path.mAttributeId) { @@ -86,9 +84,9 @@ DataModel::ActionReturnStatus WebRTCTransportRequestorServer::ReadAttribute(cons } } -std::optional WebRTCTransportRequestorServer::InvokeCommand(const DataModel::InvokeRequest & request, - TLV::TLVReader & input_arguments, - CommandHandler * handler) +std::optional +WebRTCTransportRequestorCluster::InvokeCommand(const DataModel::InvokeRequest & request, TLV::TLVReader & input_arguments, + CommandHandler * handler) { switch (request.path.mCommandId) { @@ -129,75 +127,30 @@ std::optional WebRTCTransportRequestorServer::Inv } } -CHIP_ERROR WebRTCTransportRequestorServer::AcceptedCommands(const ConcreteClusterPath & path, - ReadOnlyBufferBuilder & builder) +CHIP_ERROR WebRTCTransportRequestorCluster::AcceptedCommands(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) { return builder.ReferenceExisting(kAcceptedCommands); } -CHIP_ERROR WebRTCTransportRequestorServer::Attributes(const ConcreteClusterPath & path, - ReadOnlyBufferBuilder & builder) +CHIP_ERROR WebRTCTransportRequestorCluster::Attributes(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) { AttributeListBuilder listBuilder(builder); return listBuilder.Append(Span(kMandatoryMetadata), {}, {}); } -uint16_t WebRTCTransportRequestorServer::GenerateSessionId() +DataModel::ActionReturnStatus WebRTCTransportRequestorCluster::HandleOffer(const CommandHandler & commandHandler, + const Commands::Offer::DecodableType & req) { - static uint16_t lastSessionId = 0; - uint16_t candidateId = 0; - - // Try at most kMaxSessionId+1 attempts to find a free ID - // This ensures we never loop infinitely even if all IDs are somehow in use - for (uint16_t attempts = 0; attempts <= kMaxSessionId; attempts++) - { - candidateId = lastSessionId++; - - // Handle wrap-around per spec - if (lastSessionId > kMaxSessionId) - { - lastSessionId = 0; - } - - if (FindSession(candidateId) == nullptr) - { - return candidateId; - } - } - - // This should never happen in practice since we support 65534 sessions - // and typical applications will have far fewer active sessions - ChipLogError(Zcl, "All session IDs are in use!"); - chipDie(); -} + uint16_t sessionId = req.webRTCSessionID; -bool WebRTCTransportRequestorServer::IsPeerNodeSessionValid(uint16_t sessionId, const CommandHandler & commandHandler) -{ + // Get the session struct to pass to delegate NodeId peerNodeId = GetNodeIdFromCtx(commandHandler); FabricIndex peerFabricIndex = commandHandler.GetAccessingFabricIndex(); - // Check if the session ID is in the existing sessions list - WebRTCSessionStruct * existingSession = FindSession(sessionId); - - if (!existingSession) - { - return false; - } - - // Also check that the existing session belongs to the same PeerNodeID / Fabric - // If it doesn't match, return false - return (peerNodeId == existingSession->peerNodeID) && (peerFabricIndex == existingSession->GetFabricIndex()); -} - -DataModel::ActionReturnStatus WebRTCTransportRequestorServer::HandleOffer(const CommandHandler & commandHandler, - const Commands::Offer::DecodableType & req) -{ - uint16_t sessionId = req.webRTCSessionID; - - if (!IsPeerNodeSessionValid(sessionId, commandHandler)) - { - return Status::NotFound; - } + WebRTCSessionStruct * session = FindSession(sessionId, peerNodeId, peerFabricIndex); + VerifyOrReturnValue(session != nullptr, Status::NotFound); // Create arguments for Delegate. Delegate::OfferArgs args; @@ -228,29 +181,31 @@ DataModel::ActionReturnStatus WebRTCTransportRequestorServer::HandleOffer(const } // Delegate processing: handle the SDP offer, gather ICE candidates, SDP answer, etc. - return mDelegate.HandleOffer(sessionId, args); + return mDelegate.HandleOffer(*session, args); } -DataModel::ActionReturnStatus WebRTCTransportRequestorServer::HandleAnswer(const CommandHandler & commandHandler, - const Commands::Answer::DecodableType & req) +DataModel::ActionReturnStatus WebRTCTransportRequestorCluster::HandleAnswer(const CommandHandler & commandHandler, + const Commands::Answer::DecodableType & req) { uint16_t sessionId = req.webRTCSessionID; auto sdpSpan = req.sdp; - if (!IsPeerNodeSessionValid(sessionId, commandHandler)) - { - return Status::NotFound; - } + // Get the session struct to pass to delegate + NodeId peerNodeId = GetNodeIdFromCtx(commandHandler); + FabricIndex peerFabricIndex = commandHandler.GetAccessingFabricIndex(); + + WebRTCSessionStruct * session = FindSession(sessionId, peerNodeId, peerFabricIndex); + VerifyOrReturnValue(session != nullptr, Status::NotFound); std::string sdpAnswer(sdpSpan.data(), sdpSpan.size()); // Delegate handles Answer command received. - return mDelegate.HandleAnswer(sessionId, sdpAnswer); + return mDelegate.HandleAnswer(*session, sdpAnswer); } DataModel::ActionReturnStatus -WebRTCTransportRequestorServer::HandleICECandidates(const CommandHandler & commandHandler, - const Commands::ICECandidates::DecodableType & req) +WebRTCTransportRequestorCluster::HandleICECandidates(const CommandHandler & commandHandler, + const Commands::ICECandidates::DecodableType & req) { uint16_t sessionId = req.webRTCSessionID; @@ -286,17 +241,19 @@ WebRTCTransportRequestorServer::HandleICECandidates(const CommandHandler & comma return Status::ConstraintError; } - // Check if the session, NodeID are valid - if (!IsPeerNodeSessionValid(sessionId, commandHandler)) - { - return Status::NotFound; - } + // Get the session struct to pass to delegate + NodeId peerNodeId = GetNodeIdFromCtx(commandHandler); + FabricIndex peerFabricIndex = commandHandler.GetAccessingFabricIndex(); + + WebRTCSessionStruct * session = FindSession(sessionId, peerNodeId, peerFabricIndex); + VerifyOrReturnValue(session != nullptr, Status::NotFound); - return mDelegate.HandleICECandidates(sessionId, candidates); + // Pass the full session struct so delegate can identify which camera this is for + return mDelegate.HandleICECandidates(*session, candidates); } -DataModel::ActionReturnStatus WebRTCTransportRequestorServer::HandleEnd(const CommandHandler & commandHandler, - const Commands::End::DecodableType & req) +DataModel::ActionReturnStatus WebRTCTransportRequestorCluster::HandleEnd(const CommandHandler & commandHandler, + const Commands::End::DecodableType & req) { uint16_t sessionId = req.webRTCSessionID; auto reason = req.reason; @@ -308,24 +265,26 @@ DataModel::ActionReturnStatus WebRTCTransportRequestorServer::HandleEnd(const Co return Status::ConstraintError; } - if (!IsPeerNodeSessionValid(sessionId, commandHandler)) - { - return Status::NotFound; - } + // Get the session struct to pass to delegate + NodeId peerNodeId = GetNodeIdFromCtx(commandHandler); + FabricIndex peerFabricIndex = commandHandler.GetAccessingFabricIndex(); - CHIP_ERROR delegateResult = mDelegate.HandleEnd(sessionId, reason); + WebRTCSessionStruct * session = FindSession(sessionId, peerNodeId, peerFabricIndex); + VerifyOrReturnValue(session != nullptr, Status::NotFound); - RemoveSession(sessionId); + // Pass the full session struct so delegate can identify which camera this is for + CHIP_ERROR delegateResult = mDelegate.HandleEnd(*session, reason); + RemoveSession(sessionId, peerNodeId, peerFabricIndex); return delegateResult; } // Helper functions -WebRTCSessionStruct * WebRTCTransportRequestorServer::FindSession(uint16_t sessionId) +WebRTCSessionStruct * WebRTCTransportRequestorCluster::FindSession(uint16_t sessionId, NodeId peerNodeId, FabricIndex fabricIndex) { for (auto & session : mCurrentSessions) { - if (session.id == sessionId) + if (session.id == sessionId && session.peerNodeID == peerNodeId && session.GetFabricIndex() == fabricIndex) { return &session; } @@ -334,12 +293,16 @@ WebRTCSessionStruct * WebRTCTransportRequestorServer::FindSession(uint16_t sessi return nullptr; } -WebRTCTransportRequestorServer::UpsertResultEnum WebRTCTransportRequestorServer::UpsertSession(const WebRTCSessionStruct & session) +WebRTCTransportRequestorCluster::UpsertResultEnum +WebRTCTransportRequestorCluster::UpsertSession(const WebRTCSessionStruct & session) { - // Search for a session in the current sessions + // Search for a session in the current sessions using the full tuple + // This is critical because different cameras can allocate the same sessionId UpsertResultEnum result; - auto it = std::find_if(mCurrentSessions.begin(), mCurrentSessions.end(), - [id = session.id](const auto & existing) { return existing.id == id; }); + auto it = std::find_if(mCurrentSessions.begin(), mCurrentSessions.end(), [&session](const auto & existing) { + return existing.id == session.id && existing.peerNodeID == session.peerNodeID && + existing.GetFabricIndex() == session.GetFabricIndex(); + }); if (it != mCurrentSessions.end()) { @@ -357,12 +320,16 @@ WebRTCTransportRequestorServer::UpsertResultEnum WebRTCTransportRequestorServer: return result; } -void WebRTCTransportRequestorServer::RemoveSession(uint16_t sessionId) +void WebRTCTransportRequestorCluster::RemoveSession(uint16_t sessionId, NodeId peerNodeId, FabricIndex fabricIndex) { size_t originalSize = mCurrentSessions.size(); - // Remove the session if sessionId is matching + // Remove the session if the full tuple matches + // This is critical: different cameras can have the same sessionId, so we must match all three fields mCurrentSessions.erase(std::remove_if(mCurrentSessions.begin(), mCurrentSessions.end(), - [sessionId](const WebRTCSessionStruct & s) { return s.id == sessionId; }), + [sessionId, peerNodeId, fabricIndex](const WebRTCSessionStruct & s) { + return s.id == sessionId && s.peerNodeID == peerNodeId && + s.GetFabricIndex() == fabricIndex; + }), mCurrentSessions.end()); // Check whether session was removed diff --git a/src/app/clusters/webrtc-transport-requestor-server/webrtc-transport-requestor-cluster.h b/src/app/clusters/webrtc-transport-requestor-server/WebRTCTransportRequestorCluster.h similarity index 76% rename from src/app/clusters/webrtc-transport-requestor-server/webrtc-transport-requestor-cluster.h rename to src/app/clusters/webrtc-transport-requestor-server/WebRTCTransportRequestorCluster.h index f95382222d3..a3cd554596e 100644 --- a/src/app/clusters/webrtc-transport-requestor-server/webrtc-transport-requestor-cluster.h +++ b/src/app/clusters/webrtc-transport-requestor-server/WebRTCTransportRequestorCluster.h @@ -61,51 +61,52 @@ class Delegate * @brief * Handles the Offer command received by the server. * - * @param[in] args - * Structure containing all input arguments for the command. + * @param[in] session The WebRTC session for this offer. + * @param[in] args Structure containing all input arguments for the command. * * @return CHIP_ERROR * - Returns error if the session is invalid or the candidates cannot be processed */ - virtual CHIP_ERROR HandleOffer(uint16_t sessionId, const OfferArgs & args) = 0; + virtual CHIP_ERROR HandleOffer(const WebRTCSessionStruct & session, const OfferArgs & args) = 0; /** * @brief * Handles the Answer command received by the server. * - * @param[in] sessionId Current session ID. - * @param[in] sdpAnswer SDP answer received. + * @param[in] session The WebRTC session for this answer. + * @param[in] sdpAnswer SDP answer received. * * @return CHIP_ERROR * - Returns error if the session is invalid or the candidates cannot be processed */ - virtual CHIP_ERROR HandleAnswer(uint16_t sessionId, const std::string & sdpAnswer) = 0; + virtual CHIP_ERROR HandleAnswer(const WebRTCSessionStruct & session, const std::string & sdpAnswer) = 0; /** * @brief * Called when the server receives the ICECandidates command. * - * @param[in] sessionId Current session ID. - * @param[in] candidates List of ICE candidate structs. + * @param[in] session The WebRTC session for these candidates. + * @param[in] candidates List of ICE candidate structs. * Note: The callee cannot reference the `candidates` vector after this call * returns, and must copy the contents over for later use, if required. * * @return CHIP_ERROR * - Returns error if the session is invalid or the candidates cannot be processed */ - virtual CHIP_ERROR HandleICECandidates(uint16_t sessionId, const std::vector & candidates) = 0; + virtual CHIP_ERROR HandleICECandidates(const WebRTCSessionStruct & session, + const std::vector & candidates) = 0; /** * @brief * Called when the server receives the End command. * - * @param[in] sessionId Current session ID to end. - * @param[in] reasonCode Reason to end the session. + * @param[in] session The WebRTC session to end. + * @param[in] reasonCode Reason to end the session. * * @return CHIP_ERROR * - Returns error if the session is invalid or the candidates cannot be processed */ - virtual CHIP_ERROR HandleEnd(uint16_t sessionId, WebRTCEndReasonEnum reasonCode) = 0; + virtual CHIP_ERROR HandleEnd(const WebRTCSessionStruct & session, WebRTCEndReasonEnum reasonCode) = 0; }; -class WebRTCTransportRequestorServer : public DefaultServerCluster +class WebRTCTransportRequestorCluster : public DefaultServerCluster { public: enum class UpsertResultEnum : uint8_t @@ -116,13 +117,13 @@ class WebRTCTransportRequestorServer : public DefaultServerCluster /** * @brief - * Creates a WebRTCTransportRequestorServer instance with a given endpoint and delegate. + * Creates a WebRTCTransportRequestorCluster instance with a given endpoint and delegate. * * @param endpointId The endpoint on which this cluster exists. This must match the zap configuration. * @param delegate A reference to the delegate to be used by this server. * The caller must ensure that the delegate lives throughout the instance's lifetime. */ - WebRTCTransportRequestorServer(EndpointId endpointId, Delegate & delegate); + WebRTCTransportRequestorCluster(EndpointId endpointId, Delegate & delegate); DataModel::ActionReturnStatus ReadAttribute(const DataModel::ReadAttributeRequest & request, AttributeValueEncoder & encoder) override; @@ -152,21 +153,21 @@ class WebRTCTransportRequestorServer : public DefaultServerCluster /** * @brief - * Removes a session identified by its session ID from the internal list of current sessions. + * Removes a session identified by its session ID, peer node ID, and fabric index from the internal list of current sessions. * * @param sessionId The session ID of the session to remove. - * If the ID is not found, the call is a no‑op. + * @param peerNodeId The peer node ID of the session to remove. + * @param fabricIndex The fabric index of the session to remove. + * If the session is not found, the call is a no‑op. */ - void RemoveSession(uint16_t sessionId); + void RemoveSession(uint16_t sessionId, NodeId peerNodeId, FabricIndex fabricIndex); private: Delegate & mDelegate; std::vector mCurrentSessions; // Helper functions - WebRTCSessionStruct * FindSession(uint16_t sessionId); - uint16_t GenerateSessionId(); - bool IsPeerNodeSessionValid(uint16_t sessionId, const CommandHandler & commandHandler); + WebRTCSessionStruct * FindSession(uint16_t sessionId, NodeId peerNodeId, FabricIndex fabricIndex); // Command handlers DataModel::ActionReturnStatus HandleOffer(const CommandHandler & commandHandler, const Commands::Offer::DecodableType & req); diff --git a/src/app/clusters/webrtc-transport-requestor-server/app_config_dependent_sources.cmake b/src/app/clusters/webrtc-transport-requestor-server/app_config_dependent_sources.cmake index ceb69081a6a..c1bb0310ea1 100644 --- a/src/app/clusters/webrtc-transport-requestor-server/app_config_dependent_sources.cmake +++ b/src/app/clusters/webrtc-transport-requestor-server/app_config_dependent_sources.cmake @@ -16,6 +16,6 @@ TARGET_SOURCES( ${APP_TARGET} PRIVATE - "${CLUSTER_DIR}/webrtc-transport-requestor-cluster.h" - "${CLUSTER_DIR}/webrtc-transport-requestor-cluster.cpp" + "${CLUSTER_DIR}/WebRTCTransportRequestorCluster.h" + "${CLUSTER_DIR}/WebRTCTransportRequestorCluster.cpp" ) diff --git a/src/app/clusters/webrtc-transport-requestor-server/tests/TestWebRTCTransportRequestorCluster.cpp b/src/app/clusters/webrtc-transport-requestor-server/tests/TestWebRTCTransportRequestorCluster.cpp index 37e485da608..8d7d4ede2ed 100644 --- a/src/app/clusters/webrtc-transport-requestor-server/tests/TestWebRTCTransportRequestorCluster.cpp +++ b/src/app/clusters/webrtc-transport-requestor-server/tests/TestWebRTCTransportRequestorCluster.cpp @@ -17,7 +17,8 @@ #include #include -#include +#include +#include #include #include #include @@ -25,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +38,8 @@ using namespace chip; using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::app::Clusters::WebRTCTransportRequestor; +using chip::Testing::IsAcceptedCommandsListEqualTo; +using chip::Testing::IsAttributesListEqualTo; using ICEServerDecodableStruct = chip::app::Clusters::Globals::Structs::ICEServerStruct::DecodableType; using WebRTCSessionStruct = chip::app::Clusters::Globals::Structs::WebRTCSessionStruct::Type; @@ -45,64 +49,20 @@ using WebRTCEndReasonEnum = chip::app::Clusters::Globals::WebRTCEndReasonEn static constexpr chip::EndpointId kTestEndpointId = 1; -// Mock delegate for testing +// Minimal mock delegate for testing class MockWebRTCTransportRequestorDelegate : public Delegate { public: - MockWebRTCTransportRequestorDelegate() : mLastSessionId(0), mLastEndReason(WebRTCEndReasonEnum::kUnknownEnumValue) {} + CHIP_ERROR HandleOffer(const WebRTCSessionStruct & session, const OfferArgs & args) override { return CHIP_NO_ERROR; } - CHIP_ERROR HandleOffer(uint16_t sessionId, const OfferArgs & args) override - { - mLastSessionId = sessionId; - mLastOfferArgs = args; - return mOfferResult; - } - - CHIP_ERROR HandleAnswer(uint16_t sessionId, const std::string & sdpAnswer) override - { - mLastSessionId = sessionId; - mLastSdpAnswer = sdpAnswer; - return mAnswerResult; - } + CHIP_ERROR HandleAnswer(const WebRTCSessionStruct & session, const std::string & sdpAnswer) override { return CHIP_NO_ERROR; } - CHIP_ERROR HandleICECandidates(uint16_t sessionId, const std::vector & candidates) override + CHIP_ERROR HandleICECandidates(const WebRTCSessionStruct & session, const std::vector & candidates) override { - mLastSessionId = sessionId; - mLastCandidates = candidates; - return mICECandidatesResult; + return CHIP_NO_ERROR; } - CHIP_ERROR HandleEnd(uint16_t sessionId, WebRTCEndReasonEnum reasonCode) override - { - mLastSessionId = sessionId; - mLastEndReason = reasonCode; - return mEndResult; - } - - // Test setup methods - void SetOfferResult(CHIP_ERROR result) { mOfferResult = result; } - void SetAnswerResult(CHIP_ERROR result) { mAnswerResult = result; } - void SetICECandidatesResult(CHIP_ERROR result) { mICECandidatesResult = result; } - void SetEndResult(CHIP_ERROR result) { mEndResult = result; } - - // Getters for verification - uint16_t GetLastSessionId() const { return mLastSessionId; } - const OfferArgs & GetLastOfferArgs() const { return mLastOfferArgs; } - const std::string & GetLastSdpAnswer() const { return mLastSdpAnswer; } - const std::vector & GetLastCandidates() const { return mLastCandidates; } - WebRTCEndReasonEnum GetLastEndReason() const { return mLastEndReason; } - -private: - uint16_t mLastSessionId; - OfferArgs mLastOfferArgs; - std::string mLastSdpAnswer; - std::vector mLastCandidates; - WebRTCEndReasonEnum mLastEndReason; - - CHIP_ERROR mOfferResult = CHIP_NO_ERROR; - CHIP_ERROR mAnswerResult = CHIP_NO_ERROR; - CHIP_ERROR mICECandidatesResult = CHIP_NO_ERROR; - CHIP_ERROR mEndResult = CHIP_NO_ERROR; + CHIP_ERROR HandleEnd(const WebRTCSessionStruct & session, WebRTCEndReasonEnum reasonCode) override { return CHIP_NO_ERROR; } }; // initialize memory as ReadOnlyBufferBuilder may allocate @@ -115,43 +75,48 @@ struct TestWebRTCTransportRequestorCluster : public ::testing::Test TEST_F(TestWebRTCTransportRequestorCluster, TestAttributes) { MockWebRTCTransportRequestorDelegate mockDelegate; - WebRTCTransportRequestorServer server(kTestEndpointId, mockDelegate); - - ReadOnlyBufferBuilder builder; - ASSERT_EQ(server.Attributes({ kTestEndpointId, WebRTCTransportRequestor::Id }, builder), CHIP_NO_ERROR); - - ReadOnlyBufferBuilder expectedBuilder; - ASSERT_EQ(expectedBuilder.AppendElements({ - WebRTCTransportRequestor::Attributes::CurrentSessions::kMetadataEntry, - }), - CHIP_NO_ERROR); - ASSERT_EQ(expectedBuilder.ReferenceExisting(chip::app::DefaultServerCluster::GlobalAttributes()), CHIP_NO_ERROR); + WebRTCTransportRequestorCluster server(kTestEndpointId, mockDelegate); + + std::array expectedAttributes = { + WebRTCTransportRequestor::Attributes::CurrentSessions::kMetadataEntry, + chip::app::DataModel::AttributeEntry( + Globals::Attributes::GeneratedCommandList::Id, + BitFlags(DataModel::AttributeQualityFlags::kListAttribute), Access::Privilege::kView, + std::nullopt), + chip::app::DataModel::AttributeEntry( + Globals::Attributes::AcceptedCommandList::Id, + BitFlags(DataModel::AttributeQualityFlags::kListAttribute), Access::Privilege::kView, + std::nullopt), + chip::app::DataModel::AttributeEntry( + Globals::Attributes::AttributeList::Id, + BitFlags(DataModel::AttributeQualityFlags::kListAttribute), Access::Privilege::kView, + std::nullopt), + chip::app::DataModel::AttributeEntry(Globals::Attributes::FeatureMap::Id, BitFlags(), + Access::Privilege::kView, std::nullopt), + chip::app::DataModel::AttributeEntry(Globals::Attributes::ClusterRevision::Id, BitFlags(), + Access::Privilege::kView, std::nullopt), + }; + ASSERT_TRUE(IsAttributesListEqualTo(server, expectedAttributes)); } TEST_F(TestWebRTCTransportRequestorCluster, TestCommands) { MockWebRTCTransportRequestorDelegate mockDelegate; - WebRTCTransportRequestorServer server(kTestEndpointId, mockDelegate); - - ReadOnlyBufferBuilder builder; - ASSERT_EQ(server.AcceptedCommands({ kTestEndpointId, WebRTCTransportRequestor::Id }, builder), CHIP_NO_ERROR); - - ReadOnlyBufferBuilder expectedBuilder; - ASSERT_EQ(expectedBuilder.AppendElements({ - WebRTCTransportRequestor::Commands::Offer::kMetadataEntry, - WebRTCTransportRequestor::Commands::Answer::kMetadataEntry, - WebRTCTransportRequestor::Commands::ICECandidates::kMetadataEntry, - WebRTCTransportRequestor::Commands::End::kMetadataEntry, - }), - CHIP_NO_ERROR); - - EXPECT_TRUE(Testing::EqualAcceptedCommandSets(builder.TakeBuffer(), expectedBuilder.TakeBuffer())); + WebRTCTransportRequestorCluster server(kTestEndpointId, mockDelegate); + + std::array expectedCommands = { + WebRTCTransportRequestor::Commands::Offer::kMetadataEntry, + WebRTCTransportRequestor::Commands::Answer::kMetadataEntry, + WebRTCTransportRequestor::Commands::ICECandidates::kMetadataEntry, + WebRTCTransportRequestor::Commands::End::kMetadataEntry, + }; + ASSERT_TRUE(IsAcceptedCommandsListEqualTo(server, expectedCommands)); } TEST_F(TestWebRTCTransportRequestorCluster, TestCurrentSessionsAttribute) { MockWebRTCTransportRequestorDelegate mockDelegate; - WebRTCTransportRequestorServer server(kTestEndpointId, mockDelegate); + WebRTCTransportRequestorCluster server(kTestEndpointId, mockDelegate); // Initially, no sessions should exist auto sessions = server.GetCurrentSessions(); @@ -160,11 +125,12 @@ TEST_F(TestWebRTCTransportRequestorCluster, TestCurrentSessionsAttribute) // Add a test session WebRTCSessionStruct testSession; testSession.id = 1; - testSession.peerNodeID = chip::kUndefinedNodeId; + testSession.peerNodeID = 1; + testSession.fabricIndex = 1; testSession.streamUsage = StreamUsageEnum::kLiveView; auto result = server.UpsertSession(testSession); - EXPECT_EQ(result, WebRTCTransportRequestorServer::UpsertResultEnum::kInserted); + EXPECT_EQ(result, WebRTCTransportRequestorCluster::UpsertResultEnum::kInserted); // Verify session was added sessions = server.GetCurrentSessions(); @@ -174,7 +140,7 @@ TEST_F(TestWebRTCTransportRequestorCluster, TestCurrentSessionsAttribute) // Update the same session testSession.streamUsage = StreamUsageEnum::kRecording; result = server.UpsertSession(testSession); - EXPECT_EQ(result, WebRTCTransportRequestorServer::UpsertResultEnum::kUpdated); + EXPECT_EQ(result, WebRTCTransportRequestorCluster::UpsertResultEnum::kUpdated); // Verify session was updated, not duplicated sessions = server.GetCurrentSessions(); @@ -182,7 +148,7 @@ TEST_F(TestWebRTCTransportRequestorCluster, TestCurrentSessionsAttribute) EXPECT_EQ(sessions[0].streamUsage, StreamUsageEnum::kRecording); // Remove the session - server.RemoveSession(1); + server.RemoveSession(1, testSession.peerNodeID, testSession.fabricIndex); sessions = server.GetCurrentSessions(); EXPECT_TRUE(sessions.empty()); } @@ -190,16 +156,18 @@ TEST_F(TestWebRTCTransportRequestorCluster, TestCurrentSessionsAttribute) TEST_F(TestWebRTCTransportRequestorCluster, TestSessionManagement) { MockWebRTCTransportRequestorDelegate mockDelegate; - WebRTCTransportRequestorServer server(kTestEndpointId, mockDelegate); + WebRTCTransportRequestorCluster server(kTestEndpointId, mockDelegate); // Test adding multiple sessions WebRTCSessionStruct session1; - session1.id = 1; - session1.peerNodeID = 0x1234ULL; + session1.id = 1; + session1.peerNodeID = 0x1234ULL; + session1.fabricIndex = 1; WebRTCSessionStruct session2; - session2.id = 2; - session2.peerNodeID = 0x5678ULL; + session2.id = 2; + session2.peerNodeID = 0x5678ULL; + session2.fabricIndex = 1; server.UpsertSession(session1); server.UpsertSession(session2); @@ -208,132 +176,21 @@ TEST_F(TestWebRTCTransportRequestorCluster, TestSessionManagement) EXPECT_EQ(sessions.size(), 2u); // Remove specific session - server.RemoveSession(1); + server.RemoveSession(1, session1.peerNodeID, session1.fabricIndex); sessions = server.GetCurrentSessions(); EXPECT_EQ(sessions.size(), 1u); EXPECT_EQ(sessions[0].id, 2); // Remove non-existent session (should be no-op) - server.RemoveSession(999); + server.RemoveSession(999, 0, 0); sessions = server.GetCurrentSessions(); EXPECT_EQ(sessions.size(), 1u); } -TEST_F(TestWebRTCTransportRequestorCluster, TestDelegateHandleOffer) -{ - MockWebRTCTransportRequestorDelegate mockDelegate; - WebRTCTransportRequestorServer server(kTestEndpointId, mockDelegate); - - // Setup test data - uint16_t testSessionId = 123; - std::string testSdp = "test_sdp_offer"; - - // Test successful offer handling - mockDelegate.SetOfferResult(CHIP_NO_ERROR); - - Delegate::OfferArgs offerArgs; - offerArgs.sdp = testSdp; - offerArgs.peerNodeId = 0x1234ULL; // Use ULL suffix for uint64_t/NodeId - - CHIP_ERROR result = mockDelegate.HandleOffer(testSessionId, offerArgs); - EXPECT_EQ(result, CHIP_NO_ERROR); - EXPECT_EQ(mockDelegate.GetLastSessionId(), testSessionId); - EXPECT_EQ(mockDelegate.GetLastOfferArgs().sdp, testSdp); - EXPECT_EQ(mockDelegate.GetLastOfferArgs().peerNodeId, 0x1234ULL); - - // Test error case - mockDelegate.SetOfferResult(CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); - result = mockDelegate.HandleOffer(testSessionId, offerArgs); - EXPECT_EQ(result, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); -} - -TEST_F(TestWebRTCTransportRequestorCluster, TestDelegateHandleAnswer) -{ - MockWebRTCTransportRequestorDelegate mockDelegate; - WebRTCTransportRequestorServer server(kTestEndpointId, mockDelegate); - - // Setup test data - uint16_t testSessionId = 456; - std::string testSdpAnswer = "test_sdp_answer"; - - // Test successful answer handling - mockDelegate.SetAnswerResult(CHIP_NO_ERROR); - - CHIP_ERROR result = mockDelegate.HandleAnswer(testSessionId, testSdpAnswer); - EXPECT_EQ(result, CHIP_NO_ERROR); - EXPECT_EQ(mockDelegate.GetLastSessionId(), testSessionId); - EXPECT_EQ(mockDelegate.GetLastSdpAnswer(), testSdpAnswer); - - // Test error case - mockDelegate.SetAnswerResult(CHIP_ERROR_INTERNAL); - result = mockDelegate.HandleAnswer(testSessionId, testSdpAnswer); - EXPECT_EQ(result, CHIP_ERROR_INTERNAL); -} - -TEST_F(TestWebRTCTransportRequestorCluster, TestDelegateHandleICECandidates) -{ - MockWebRTCTransportRequestorDelegate mockDelegate; - WebRTCTransportRequestorServer server(kTestEndpointId, mockDelegate); - - // Setup test data - uint16_t testSessionId = 789; - std::vector testCandidates; - - ICECandidateStruct candidate1; - candidate1.candidate = chip::CharSpan("candidate1", 10); - testCandidates.push_back(candidate1); - - ICECandidateStruct candidate2; - candidate2.candidate = chip::CharSpan("candidate2", 10); - testCandidates.push_back(candidate2); - - // Test successful ICE candidates handling - mockDelegate.SetICECandidatesResult(CHIP_NO_ERROR); - - CHIP_ERROR result = mockDelegate.HandleICECandidates(testSessionId, testCandidates); - EXPECT_EQ(result, CHIP_NO_ERROR); - EXPECT_EQ(mockDelegate.GetLastSessionId(), testSessionId); - EXPECT_EQ(mockDelegate.GetLastCandidates().size(), 2u); - - // Test error case - mockDelegate.SetICECandidatesResult(CHIP_ERROR_INVALID_ARGUMENT); - result = mockDelegate.HandleICECandidates(testSessionId, testCandidates); - EXPECT_EQ(result, CHIP_ERROR_INVALID_ARGUMENT); -} - -TEST_F(TestWebRTCTransportRequestorCluster, TestDelegateHandleEnd) -{ - MockWebRTCTransportRequestorDelegate mockDelegate; - WebRTCTransportRequestorServer server(kTestEndpointId, mockDelegate); - - // Setup test data - uint16_t testSessionId = 999; - WebRTCEndReasonEnum testReason = WebRTCEndReasonEnum::kInviteTimeout; - - // Test successful end handling - mockDelegate.SetEndResult(CHIP_NO_ERROR); - - CHIP_ERROR result = mockDelegate.HandleEnd(testSessionId, testReason); - EXPECT_EQ(result, CHIP_NO_ERROR); - EXPECT_EQ(mockDelegate.GetLastSessionId(), testSessionId); - EXPECT_EQ(mockDelegate.GetLastEndReason(), testReason); - - // Test different reason codes - WebRTCEndReasonEnum testReason2 = WebRTCEndReasonEnum::kUserBusy; - result = mockDelegate.HandleEnd(testSessionId, testReason2); - EXPECT_EQ(result, CHIP_NO_ERROR); - EXPECT_EQ(mockDelegate.GetLastEndReason(), testReason2); - - // Test error case - mockDelegate.SetEndResult(CHIP_ERROR_TIMEOUT); - result = mockDelegate.HandleEnd(testSessionId, testReason); - EXPECT_EQ(result, CHIP_ERROR_TIMEOUT); -} - TEST_F(TestWebRTCTransportRequestorCluster, TestReadCurrentSessionsAttribute) { MockWebRTCTransportRequestorDelegate mockDelegate; - WebRTCTransportRequestorServer server(kTestEndpointId, mockDelegate); + WebRTCTransportRequestorCluster server(kTestEndpointId, mockDelegate); // Create a mock attribute request for CurrentSessions chip::app::DataModel::ReadAttributeRequest request; @@ -365,7 +222,7 @@ TEST_F(TestWebRTCTransportRequestorCluster, TestReadCurrentSessionsAttribute) TEST_F(TestWebRTCTransportRequestorCluster, TestReadClusterRevisionAttribute) { MockWebRTCTransportRequestorDelegate mockDelegate; - WebRTCTransportRequestorServer server(kTestEndpointId, mockDelegate); + WebRTCTransportRequestorCluster server(kTestEndpointId, mockDelegate); // Create a mock attribute request for ClusterRevision chip::app::DataModel::ReadAttributeRequest request; @@ -395,7 +252,7 @@ TEST_F(TestWebRTCTransportRequestorCluster, TestReadClusterRevisionAttribute) TEST_F(TestWebRTCTransportRequestorCluster, TestReadUnsupportedAttribute) { MockWebRTCTransportRequestorDelegate mockDelegate; - WebRTCTransportRequestorServer server(kTestEndpointId, mockDelegate); + WebRTCTransportRequestorCluster server(kTestEndpointId, mockDelegate); // Create a mock attribute request for an unsupported attribute chip::app::DataModel::ReadAttributeRequest request; diff --git a/src/app/clusters/wifi-network-diagnostics-server/wifi-network-diagnostics-cluster.cpp b/src/app/clusters/wifi-network-diagnostics-server/wifi-network-diagnostics-cluster.cpp index d48202f3e18..d665a318330 100644 --- a/src/app/clusters/wifi-network-diagnostics-server/wifi-network-diagnostics-cluster.cpp +++ b/src/app/clusters/wifi-network-diagnostics-server/wifi-network-diagnostics-cluster.cpp @@ -243,7 +243,7 @@ std::optional WiFiDiagnosticsServerCluster::Invok // Note that ResetWiFiNetworkDiagnosticsCounts() does return a CHIP_ERROR; however, for backwards compatibility, // we completely ignore that return value. It would probably be more correct to return the result // of the reset, but that seems to potentially cause backwards compatibility issues. - mDiagnosticProvider.ResetWiFiNetworkDiagnosticsCounts(); + TEMPORARY_RETURN_IGNORED mDiagnosticProvider.ResetWiFiNetworkDiagnosticsCounts(); return Protocols::InteractionModel::Status::Success; } default: diff --git a/src/app/clusters/wifi-network-management-server/wifi-network-management-server.cpp b/src/app/clusters/wifi-network-management-server/wifi-network-management-server.cpp index 5e226c3a8a0..d144a4c4cd5 100644 --- a/src/app/clusters/wifi-network-management-server/wifi-network-management-server.cpp +++ b/src/app/clusters/wifi-network-management-server/wifi-network-management-server.cpp @@ -65,7 +65,7 @@ WiFiNetworkManagementServer::WiFiNetworkManagementServer(EndpointId endpoint) : WiFiNetworkManagementServer::~WiFiNetworkManagementServer() { AttributeAccessInterfaceRegistry::Instance().Unregister(this); - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); + TEMPORARY_RETURN_IGNORED CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); } CHIP_ERROR WiFiNetworkManagementServer::Init() @@ -80,7 +80,7 @@ CHIP_ERROR WiFiNetworkManagementServer::ClearNetworkCredentials() VerifyOrReturnError(HaveNetworkCredentials(), CHIP_NO_ERROR); mSsidLen = 0; - mPassphrase.SetLength(0); + TEMPORARY_RETURN_IGNORED mPassphrase.SetLength(0); MatterReportingAttributeChangeCallback(GetEndpointId(), WiFiNetworkManagement::Id, Ssid::Id); return CHIP_NO_ERROR; } @@ -97,7 +97,7 @@ CHIP_ERROR WiFiNetworkManagementServer::SetNetworkCredentials(ByteSpan ssid, Byt memcpy(mSsid, ssid.data(), ssid.size()); mSsidLen = static_cast(ssid.size()); - VerifyOrDie(mPassphrase.SetLength(passphrase.size()) == CHIP_NO_ERROR); + TEMPORARY_RETURN_IGNORED mPassphrase.SetLength(passphrase.size()); memcpy(mPassphrase.Bytes(), passphrase.data(), passphrase.size()); if (ssidChanged) diff --git a/src/app/clusters/zone-management-server/zone-management-server.cpp b/src/app/clusters/zone-management-server/zone-management-server.cpp index 0e72a75dd12..c6651b7724b 100644 --- a/src/app/clusters/zone-management-server/zone-management-server.cpp +++ b/src/app/clusters/zone-management-server/zone-management-server.cpp @@ -64,7 +64,7 @@ ZoneMgmtServer::~ZoneMgmtServer() mDelegate.SetZoneMgmtServer(nullptr); // Unregister command handler and attribute access interfaces - CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); + TEMPORARY_RETURN_IGNORED CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); AttributeAccessInterfaceRegistry::Instance().Unregister(this); } @@ -134,7 +134,7 @@ void ZoneMgmtServer::LoadPersistentAttributes() } // Signal delegate that all persistent configuration attributes have been loaded. - mDelegate.PersistentAttributesLoadedCallback(); + TEMPORARY_RETURN_IGNORED mDelegate.PersistentAttributesLoadedCallback(); } CHIP_ERROR ZoneMgmtServer::ReadAndEncodeZones(const AttributeValueEncoder::ListEncodeHelper & encoder) @@ -520,7 +520,7 @@ void ZoneMgmtServer::HandleCreateTwoDCartesianZone(HandlerContext & ctx, ZoneInformationStorage zoneInfo; zoneInfo.Set(zoneID, ZoneTypeEnum::kTwoDCARTZone, ZoneSourceEnum::kUser, MakeOptional(twoDCartZoneStorage)); - AddZone(zoneInfo); + TEMPORARY_RETURN_IGNORED AddZone(zoneInfo); mUserDefinedZonesCount++; response.zoneID = zoneID; @@ -613,7 +613,7 @@ void ZoneMgmtServer::HandleUpdateTwoDCartesianZone(HandlerContext & ctx, ZoneInformationStorage zoneInfo; zoneInfo.Set(zoneID, ZoneTypeEnum::kTwoDCARTZone, ZoneSourceEnum::kUser, MakeOptional(twoDCartZoneStorage)); - UpdateZone(zoneID, zoneInfo); + TEMPORARY_RETURN_IGNORED UpdateZone(zoneID, zoneInfo); ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Success); } @@ -651,7 +651,7 @@ void ZoneMgmtServer::HandleRemoveZone(HandlerContext & ctx, const Commands::Remo if (status == Status::Success) { - RemoveZone(zoneID); + TEMPORARY_RETURN_IGNORED RemoveZone(zoneID); mUserDefinedZonesCount--; } diff --git a/src/app/common/templates/config-data.yaml b/src/app/common/templates/config-data.yaml index fa86c7c3e8e..16891f7c308 100644 --- a/src/app/common/templates/config-data.yaml +++ b/src/app/common/templates/config-data.yaml @@ -148,6 +148,8 @@ CodeDrivenClusters: - Basic Information - Binding - Boolean State + - Camera AV Stream Management + - Chime - Descriptor - Diagnostic Logs - Ethernet Network Diagnostics @@ -162,6 +164,8 @@ CodeDrivenClusters: - Operational Credentials - Push AV Stream Transport - Software Diagnostics + - TLS Certificate Management + - TLS Client Management - Time Format Localization - User Label - Wi-Fi Network Diagnostics diff --git a/src/app/icd/server/ICDMonitoringTable.h b/src/app/icd/server/ICDMonitoringTable.h index e58745c7357..a3b4d36c368 100644 --- a/src/app/icd/server/ICDMonitoringTable.h +++ b/src/app/icd/server/ICDMonitoringTable.h @@ -50,7 +50,7 @@ static constexpr size_t MaxICDMonitoringEntrySize() inline constexpr size_t kICDMonitoringBufferSize = MaxICDMonitoringEntrySize(); -struct ICDMonitoringEntry : public PersistentData +struct ICDMonitoringEntry : public PersistableData { ICDMonitoringEntry(FabricIndex fabric = kUndefinedFabricIndex, NodeId nodeId = kUndefinedNodeId) { diff --git a/src/app/storage/FabricTableImpl.h b/src/app/storage/FabricTableImpl.h index 1e7c40c23a9..d1d416ae769 100644 --- a/src/app/storage/FabricTableImpl.h +++ b/src/app/storage/FabricTableImpl.h @@ -123,7 +123,7 @@ class FabricTableImpl */ template CHIP_ERROR SetTableEntry(FabricIndex fabric_index, const StorageId & entry_id, const StorageData & data, - PersistentStore & writeBuffer); + PersistenceBuffer & writeBuffer); /** * @brief Loads the entry from persistent storage. @@ -136,7 +136,7 @@ class FabricTableImpl */ template CHIP_ERROR GetTableEntry(FabricIndex fabric_index, StorageId & entry_id, StorageData & data, - PersistentStore & buffer); + PersistenceBuffer & buffer); CHIP_ERROR FindTableEntry(FabricIndex fabric_index, const StorageId & entry_id, EntryIndex & idx); CHIP_ERROR RemoveTableEntry(FabricIndex fabric_index, const StorageId & entry_id); CHIP_ERROR RemoveTableEntryAtPosition(EndpointId endpoint, FabricIndex fabric_index, EntryIndex entry_idx); @@ -164,7 +164,7 @@ class FabricTableImpl * and IterateEntries returns that same error result. */ template - CHIP_ERROR IterateEntries(FabricIndex fabric, PersistentStore & store, UnaryFunc iterateFn); + CHIP_ERROR IterateEntries(FabricIndex fabric, PersistenceBuffer & buffer, UnaryFunc iterateFn); protected: // This constructor is meant for test purposes, it allows to change the defined max for entries per fabric and global, which @@ -188,14 +188,14 @@ class FabricTableImpl { public: EntryIteratorImpl(FabricTableImpl & provider, FabricIndex fabricIdx, EndpointId endpoint, uint16_t maxEntriesPerFabric, - uint16_t maxEntriesPerEndpoint, PersistentStore & store); + uint16_t maxEntriesPerEndpoint, PersistenceBuffer & buffer); size_t Count() override; bool Next(TableEntry & output) override; void Release() override; protected: FabricTableImpl & mProvider; - PersistentStore & mStore; + PersistenceBuffer & mBuffer; FabricIndex mFabric = kUndefinedFabricIndex; EndpointId mEndpoint = kInvalidEndpointId; EntryIndex mNextEntryIdx; diff --git a/src/app/storage/FabricTableImpl.ipp b/src/app/storage/FabricTableImpl.ipp index 15522bb6d5a..0201c3cf7e7 100644 --- a/src/app/storage/FabricTableImpl.ipp +++ b/src/app/storage/FabricTableImpl.ipp @@ -48,11 +48,13 @@ enum class TagEntry : uint8_t // byte value, 1 byte end struct. 8 Bytes leaves space for potential increase in count_value size. static constexpr size_t kPersistentBufferEntryCountBytes = 8; -struct BaseEntryCount : public PersistentData +struct BaseEntryCount : public PersistableData { uint8_t count_value = 0; BaseEntryCount(uint8_t count = 0) : count_value(count) {} + void Clear() override { count_value = 0; } + CHIP_ERROR Serialize(TLV::TLVWriter & writer) const override { TLV::TLVType container; @@ -72,16 +74,10 @@ struct BaseEntryCount : public PersistentData return reader.ExitContainer(container); } - CHIP_ERROR Load(PersistentStorageDelegate * storage) override + CHIP_ERROR Load(PersistentStorageDelegate * storage) // NOLINT(bugprone-derived-method-shadowing-base-method) { - CHIP_ERROR err = PersistentData::Load(storage); - VerifyOrReturnError(CHIP_NO_ERROR == err || CHIP_ERROR_NOT_FOUND == err, err); - if (CHIP_ERROR_NOT_FOUND == err) - { - count_value = 0; - } - - return CHIP_NO_ERROR; + CHIP_ERROR err = PersistableData::Load(storage); + return err.NoErrorIf(CHIP_ERROR_NOT_FOUND); // NOT_FOUND is OK; DataAccessor::Load already called Clear() } }; @@ -95,8 +91,6 @@ struct EndpointEntryCount : public BaseEntryCount EndpointEntryCount(EndpointId endpoint, uint8_t count = 0) : BaseEntryCount(count), endpoint_id(endpoint) {} ~EndpointEntryCount() {} - void Clear() override { count_value = 0; } - CHIP_ERROR UpdateKey(StorageKeyName & key) const override { VerifyOrReturnError(kInvalidEndpointId != endpoint_id, CHIP_ERROR_INVALID_ARGUMENT); @@ -190,11 +184,11 @@ struct TableEntryData : DataAccessor * FabricEntryData is an access to a linked list of entries */ template -struct FabricEntryData : public PersistentData +struct FabricEntryData : public PersistableData { using Serializer = DefaultSerializer; using TypedTableEntryData = TableEntryData; - using Store = PersistentStore; + using Buffer = PersistenceBuffer; using TypedEndpointEntryCount = EndpointEntryCount; EndpointId endpoint_id; @@ -357,8 +351,7 @@ struct FabricEntryData : public PersistentData return CHIP_ERROR_NO_MEMORY; } - CHIP_ERROR SaveEntry(PersistentStorageDelegate & storage, const StorageId & id, const StorageData & data, - Store & persistentStore) + CHIP_ERROR SaveEntry(PersistentStorageDelegate & storage, const StorageId & id, const StorageData & data, Buffer & buffer) { CHIP_ERROR err = CHIP_NO_ERROR; // Look for empty storage space @@ -372,7 +365,7 @@ struct FabricEntryData : public PersistentData if (CHIP_NO_ERROR == err) { - return persistentStore.Save(entry, &storage); + return entry.Save(&storage, buffer.BufferSpan()); } if (CHIP_ERROR_NOT_FOUND == err) // If not found, entry.index should be the first free index @@ -395,7 +388,7 @@ struct FabricEntryData : public PersistentData return err; } - err = persistentStore.Save(entry, &storage); + err = entry.Save(&storage, buffer.BufferSpan()); // on failure to save the entry, undoes the changes to Fabric Entry Data if (CHIP_NO_ERROR != err) @@ -465,7 +458,7 @@ struct FabricEntryData : public PersistentData return err; } - CHIP_ERROR Load(PersistentStorageDelegate * storage) override + CHIP_ERROR Load(PersistentStorageDelegate * storage) // NOLINT(bugprone-derived-method-shadowing-base-method) { VerifyOrReturnError(nullptr != storage, CHIP_ERROR_INVALID_ARGUMENT); uint8_t deleted_entries_count = 0; @@ -611,7 +604,7 @@ template template CHIP_ERROR FabricTableImpl::SetTableEntry(FabricIndex fabric_index, const StorageId & id, const StorageData & data, - PersistentStore & writeBuffer) + PersistenceBuffer & writeBuffer) { using TypedFabricEntryData = FabricEntryData; @@ -631,7 +624,7 @@ CHIP_ERROR FabricTableImpl::SetTableEntry(FabricIndex fa template template CHIP_ERROR FabricTableImpl::GetTableEntry(FabricIndex fabric_index, StorageId & entry_id, - StorageData & data, PersistentStore & buffer) + StorageData & data, PersistenceBuffer & buffer) { using TypedFabricEntryData = FabricEntryData; @@ -643,7 +636,7 @@ CHIP_ERROR FabricTableImpl::GetTableEntry(FabricIndex fa ReturnErrorOnFailure(fabric.Load(mStorage)); VerifyOrReturnError(fabric.Find(entry_id, table_entry.index) == CHIP_NO_ERROR, CHIP_ERROR_NOT_FOUND); - CHIP_ERROR err = buffer.Load(table_entry, mStorage); + CHIP_ERROR err = table_entry.Load(mStorage, buffer.BufferSpan()); // If entry.Load returns "buffer too small", the entry in memory is too big to be retrieved (this could happen if the // kEntryMaxBytes was reduced by OTA) and therefore must be deleted as is is no longer considered accessible. @@ -800,12 +793,12 @@ void FabricTableImpl::SetTableSize(uint16_t endpointTabl template template -CHIP_ERROR FabricTableImpl::IterateEntries(FabricIndex fabric, PersistentStore & store, +CHIP_ERROR FabricTableImpl::IterateEntries(FabricIndex fabric, PersistenceBuffer & buffer, UnaryFunc iterateFn) { VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL); - EntryIteratorImpl iterator(*this, fabric, mEndpointId, mMaxPerFabric, mMaxPerEndpoint, store); + EntryIteratorImpl iterator(*this, fabric, mEndpointId, mMaxPerFabric, mMaxPerEndpoint, buffer); return iterateFn(iterator); } @@ -813,9 +806,9 @@ template template FabricTableImpl::EntryIteratorImpl::EntryIteratorImpl( FabricTableImpl & provider, FabricIndex fabricIdx, EndpointId endpoint, uint16_t maxPerFabric, uint16_t maxPerEndpoint, - PersistentStore & store) : + PersistenceBuffer & buffer) : mProvider(provider), - mStore(store), mFabric(fabricIdx), mEndpoint(endpoint), mMaxPerFabric(maxPerFabric), mMaxPerEndpoint(maxPerEndpoint) + mBuffer(buffer), mFabric(fabricIdx), mEndpoint(endpoint), mMaxPerFabric(maxPerFabric), mMaxPerEndpoint(maxPerEndpoint) { using TypedFabricEntryData = FabricEntryData; @@ -850,7 +843,7 @@ bool FabricTableImpl::EntryIteratorImpl: if (fabric.entry_map[mEntryIndex].IsValid()) { TableEntryData entry(mEndpoint, mFabric, output.mStorageId, output.mStorageData, mEntryIndex); - VerifyOrReturnError(mStore.Load(entry, mProvider.mStorage) == CHIP_NO_ERROR, false); + VerifyOrReturnError(entry.Load(mProvider.mStorage, mBuffer.BufferSpan()) == CHIP_NO_ERROR, false); mEntryIndex++; return true; diff --git a/src/app/tests/TestCertificateTableImpl.cpp b/src/app/tests/TestCertificateTableImpl.cpp index 90de2c53699..39a6de30ecc 100644 --- a/src/app/tests/TestCertificateTableImpl.cpp +++ b/src/app/tests/TestCertificateTableImpl.cpp @@ -42,13 +42,13 @@ static constexpr uint16_t kSpecMaxCertBytes = 3000; struct InlineBufferedRootCert : CertificateTable::BufferedRootCert { - PersistentStore buffer; + PersistenceBuffer buffer; InlineBufferedRootCert() : CertificateTable::BufferedRootCert(buffer) {} }; struct InlineBufferedClientCert : CertificateTable::BufferedClientCert { - PersistentStore buffer; + PersistenceBuffer buffer; InlineBufferedClientCert() : CertificateTable::BufferedClientCert(buffer) {} }; diff --git a/src/app/tests/suites/TestBasicInformation.yaml b/src/app/tests/suites/TestBasicInformation.yaml index 9ff65b70506..60360b18363 100644 --- a/src/app/tests/suites/TestBasicInformation.yaml +++ b/src/app/tests/suites/TestBasicInformation.yaml @@ -173,7 +173,7 @@ tests: minRevision: 3 response: # For now all-clusters-app has a version 1.5 - value: 0x01050000 + value: 0x01050100 - label: "Read the Max Paths Per Invoke value" command: "readAttribute" diff --git a/src/app/tests/suites/certification/PICS.yaml b/src/app/tests/suites/certification/PICS.yaml index 8db9c4a626f..b3b0d10b189 100644 --- a/src/app/tests/suites/certification/PICS.yaml +++ b/src/app/tests/suites/certification/PICS.yaml @@ -310,6 +310,9 @@ PICS: - label: "Does Device support LwIP stack?" id: MCORE.SC.LWIP + - label: "Does Device support TCP transport?" + id: MCORE.SC.TCP + - label: "Does Commissioner notify user that Commissionee is not a fully trusted device on device attestation failure?" diff --git a/src/app/tests/suites/certification/Test_TC_BINFO_2_1.yaml b/src/app/tests/suites/certification/Test_TC_BINFO_2_1.yaml index 047018bfbc5..31efcb2f27a 100644 --- a/src/app/tests/suites/certification/Test_TC_BINFO_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_BINFO_2_1.yaml @@ -724,7 +724,8 @@ tests: response: saveAs: SpecificationVersionValue constraints: - anyOf: [0x01040000, 0x01040100, 0x01040200, 0x01050000] + anyOf: + [0x01040000, 0x01040100, 0x01040200, 0x01050000, 0x01050100] hasMasksClear: [0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80] - label: diff --git a/src/app/tests/suites/certification/Test_TC_DD_2_1.yaml b/src/app/tests/suites/certification/Test_TC_DD_2_1.yaml index e00fa814a58..eb9ff460fe5 100644 --- a/src/app/tests/suites/certification/Test_TC_DD_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_DD_2_1.yaml @@ -457,6 +457,8 @@ tests: DNS-SD." PICS: MCORE.DD.TXT_KEY_PH verification: | + Bits 8, 10, 12, 15, 17, 19, 20, 21, 22: If the following bits are set to 1 in the PH, verify that the PI key is set with a value N representing a value the PH key needs to indicate action for the user to take (i.e. PH Bit 8: hold reset button for N seconds, PH Bit 12: press reset button N times) + $ ./chip-tool discover commissionables Verify in TH as commissioner side: diff --git a/src/app/tests/suites/certification/Test_TC_SC_4_1.yaml b/src/app/tests/suites/certification/Test_TC_SC_4_1.yaml deleted file mode 100644 index c7869727195..00000000000 --- a/src/app/tests/suites/certification/Test_TC_SC_4_1.yaml +++ /dev/null @@ -1,1422 +0,0 @@ -# Copyright (c) 2023 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -name: 22.4.1. [TC-SC-4.1] Commissionable Node Discovery [DUT as Commissionee] - -PICS: - - MCORE.ROLE.COMMISSIONEE - -config: - nodeId: 0x12344321 - endpoint: 0 - discriminator: - type: int16u - defaultValue: 3840 - shortDiscriminator: - type: int16u - defaultValue: 15 - vendorId: - type: int16u - defaultValue: 65521 - productId: - type: int16u - defaultValue: 32769 - deviceType: - type: int16u - defaultValue: 65535 - PakeVerifier: - type: octet_string - defaultValue: "hex:b96170aae803346884724fe9a3b287c30330c2a660375d17bb205a8cf1aecb350457f8ab79ee253ab6a8e46bb09e543ae422736de501e3db37d441fe344920d09548e4c18240630c4ff4913c53513839b7c07fcc0627a1b8573a149fcd1fa466cf" - timeout: 900 - waitAfterCommissioning: - type: int16u - defaultValue: 5000 - -tests: - - label: - "Step 1: If (CADMIN.S.C01.Rsp) present, wait for the commissioned - device to be retrieved" - cluster: "DelayCommands" - command: "WaitForCommissionee" - PICS: CADMIN.S.C01.Rsp - arguments: - values: - - name: "nodeId" - value: nodeId - - - label: - "Step 1a: If (CADMIN.S.C01.Rsp) present, DUT is put in Commissioning - Mode using Open Basic Commissioning Window command " - cluster: "Administrator Commissioning" - command: "OpenBasicCommissioningWindow" - PICS: CADMIN.S.C01.Rsp - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "CommissioningTimeout" - value: 180 - - - label: - "If (CADMIN.S.C01.Rsp) present, waiting after opening commissioning - window" - cluster: "DelayCommands" - command: "WaitForMs" - PICS: CADMIN.S.C01.Rsp - arguments: - values: - - name: "ms" - value: waitAfterCommissioning - - - label: - "Step 2a: Check DNS-SD instance name must be 64-bit randomly selected - ID expressed as a sixteen-char hex string with capital letters" - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "instanceName" - saveAs: deviceInstanceNameBeforeReboot - constraints: - minLength: 16 - maxLength: 16 - isUpperCase: true - isHexString: true - - - label: - "Step 2aa: If (ICDM.S.A0002) TH reads from the DUT the - ActiveModeThreshold attribute" - PICS: ICDM.S.A0002 - cluster: "ICDManagement" - command: "readAttribute" - attribute: "ActiveModeThreshold" - response: - saveAs: ActiveModeThresholdValue - - - label: "Step 2b: Service type must be _matterc._udp" - verification: | - Run the below commands within the mentioned time interval used in open-commissioning-window in step-1. - Run the below avahi browse command in the TH terminal - - avahi-browse -rt _matterc._udp - - - ubuntu@ubuntu:~$ avahi-browse -rt _matterc._udp - - Verify the device is advertising _matterc._udp service like below output in TH terminal Log: (Verify for the DUT's actual values (like vendor ID, PID ..etc) as mentioned in the expected outcome of the test plan, The below log contains the data from the reference raspi accessory) - - - + wlan0 IPv6 5A4E867284D08B13 _matterc._udp local - + eth0 IPv6 5A4E867284D08B13 _matterc._udp local - = eth0 IPv6 5A4E867284D08B13 _matterc._udp local - hostname = [E45F010F1A010000.local] - address = [fe80::e65f:1ff:fe0f:1a01] - port = [5540] - txt = ["PI=" "PH=36" "CM=1" "D=3840" "T=1" "VP=65521+32769"] - = wlan0 IPv6 5A4E867284D08B13 _matterc._udp local - hostname = [E45F010F1A010000.local] - address = [fe80::e65f:1ff:fe0f:1a01] - port = [5540] - txt = ["PI=" "PH=36" "CM=1" "D=3840" "T=1" "VP=65521+32769"] - - If "ICDM.S.A0002" check "SAT=ActiveModeThreshold Value" - - If we use Thread setup, then the Service Domain will be 422F10CDC290A406.local - verify CM flag is 1 - - to look for subtypes, on the raspi run $ avahi-browse -p _services._dns-sd._udp | grep _matterc - - +;eth0;IPv6;_matterc;_udp;local - +;eth0;IPv6;_V65521;_sub._matterc._udp;local - +;eth0;IPv6;_S15;_sub._matterc._udp;local - +;eth0;IPv6;_L3840;_sub._matterc._udp;local - +;eth0;IPv6;_CM;_sub._matterc._udp;local - cluster: "LogCommands" - command: "UserPrompt" - PICS: PICS_SKIP_SAMPLE_APP - arguments: - values: - - name: "message" - value: "Enter 'y' after success" - - name: "expectedValue" - value: "y" - - #validate the service type and the service domain not implemented in CI - - - label: - "Step 2c: Check target hostname is derived from the 48bit or 64bit MAC - address expressed as a twelve or sixteen capital letter hex string" - PICS: "( MCORE.COM.WIFI || MCORE.COM.ETH) && !MCORE.COM.THR" - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "hostName" - constraints: - minLength: 12 - maxLength: 16 - isUpperCase: true - isHexString: true - - - label: - "Step 2c: Check target hostname is derived from the 48bit or 64bit MAC - address expressed as a twelve or sixteen capital letter hex string" - PICS: "(!MCORE.COM.WIFI && !MCORE.COM.WIFI) && MCORE.COM.THR" - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "hostName" - constraints: - minLength: 12 - maxLength: 16 - isUpperCase: true - isHexString: true - - #subtype - - label: "Step 2d: Check Long Discriminator _L" - cluster: "DiscoveryCommands" - command: "FindCommissionableByLongDiscriminator" - arguments: - values: - - name: "value" - value: discriminator - - - label: "Step 2d: Check Short Discriminator (_S)" - cluster: "DiscoveryCommands" - command: "FindCommissionableByShortDiscriminator" - arguments: - values: - - name: "value" - value: shortDiscriminator - - - label: - "Step 2e: If (MCORE.SC.VENDOR_SUBTYPE) present, subtype _V is - present must be 16-bit vendor id, encoded as a variable-length decimal - number in ASCII text, omitting any leading zeros" - PICS: MCORE.SC.VENDOR_SUBTYPE - cluster: "DiscoveryCommands" - command: "FindCommissionableByVendorId" - arguments: - values: - - name: "value" - value: vendorId - - - label: - "Step 2f: If (MCORE.SC.DEVTYPE_SUBTYPE) present, subtype _T is - present, represents device type from Data Model and must be - represented as a variable length decimal number in ASCII without - leading zeros" - PICS: MCORE.SC.DEVTYPE_SUBTYPE - cluster: "DiscoveryCommands" - command: "FindCommissionableByDeviceType" - arguments: - values: - - name: "value" - value: deviceType - - - label: - "Step 2g: If (CADMIN.S.C01.Rsp) present, check Commissioning Mode - (_CM) subtype _CM must be present" - cluster: "DiscoveryCommands" - command: "FindCommissionableByCommissioningMode" - PICS: CADMIN.S.C01.Rsp - - label: - "Step 2h: key D must be present and represents the discriminator which - must be encoded as a variable-length decimal value with up to 4 digits - omitting any leading zeros" - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "longDiscriminator" - value: discriminator - constraints: - minValue: 0 - maxValue: 4096 - - - label: - "Step 2i: If (MCORE.SC.VP_KEY) present, VP key must contain at least - Vendor ID is present" - PICS: MCORE.SC.VP_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "vendorId" - value: vendorId - - - label: - "Step 2j: If (MCORE.SC.VP_KEY) present, VP key must contain at least - Product ID is present" - PICS: MCORE.SC.VP_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "productId" - value: productId - - - label: - "Step 2k: If (MCORE.SC.SII_OP_DISCOVERY_KEY) present, SII key must be - an unsigned integer with units of milliseconds and shall be encoded as - a variable length decimal number in ASCII, omitting leading zeros. - Shall not exceed 3600000" - PICS: MCORE.SC.SII_OP_DISCOVERY_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "mrpRetryIntervalIdle" - constraints: - maxValue: 3600000 - - - label: - "Step 2l: If (MCORE.SC.SAI_OP_DISCOVERY_KEY ) present, SAI key must be - an unsigned integer with units of milliseconds and shall be encoded as - a variable length decimal number in ASCII, omitting leading zeros. - Shall not exceed 3600000." - PICS: MCORE.SC.SAI_OP_DISCOVERY_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "mrpRetryIntervalActive" - constraints: - maxValue: 3600000 - - - label: - "Step 2m: If (MCORE.SC.SAT_OP_DISCOVERY_KEY) present, SAT key must be - an unsigned integer with units of milliseconds and shall be encoded as - a variable length decimal number in ASCII, omitting leading zeros. - Shall not exceed 65535." - PICS: MCORE.SC.SAI_OP_DISCOVERY_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "mrpRetryActiveThreshold" - constraints: - maxValue: 65535 - - - label: - "Step 2n: If (CADMIN.S.C01.Rsp) present, TXT key for commissioning - mode (CM) CM=1 must be present" - cluster: "DiscoveryCommands" - command: "FindCommissionable" - PICS: CADMIN.S.C01.Rsp - response: - values: - - name: "commissioningMode" - value: 1 - - - label: - "Step 2o: If (MCORE.SC.DT_KEY) present, DT key must contain the device - type identifier from Data Model Device Types and must be encoded as a - variable length decimal ASCII number without leading zeros" - PICS: MCORE.SC.DT_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "deviceType" - value: deviceType - - - label: - "Step 2p: If (MCORE.SC.DN_KEY) present, DN key must be a UTF-8 encoded - string with a maximum length of 32B" - PICS: MCORE.SC.DN_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "deviceName" - constraints: - maxLength: 32 - - - label: - "Step 2q: If (MCORE.SC.RI_KEY ) present, key RI must include the - Rotating Device Identifier encoded as a uppercase string with a - maximum length of 100 chars" - PICS: MCORE.SC.RI_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "rotatingIdLen" - constraints: - maxValue: 100 - - - label: - "Step 2r: If (MCORE.SC.PH_KEY) present, key PH must be encoded as a - variable-length decimal number in ASCII text, omitting any leading - zeros. If present value must be different of 0" - PICS: MCORE.SC.PH_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "pairingHint" - constraints: - notValue: 0 - - - label: - "Step 2s: If (MCORE.SC.PI_KEY) present, key PI must be encoded as a - valid UTF-8 string with a maximum length of 128 bytes" - PICS: MCORE.SC.PI_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "pairingInstruction" - constraints: - maxLength: 128 - - - label: - "Step 2t: DUT must publish AAAA records for each IPv6 address upon - which they are willing to accept Matter messages." - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "numIPs" - constraints: - minValue: 1 - - ### DUT TurnOff - - label: "Step 3: Reboot/restart the DUT" - PICS: PICS_SDK_CI_ONLY - cluster: "SystemCommands" - endpoint: 0 - command: "Reboot" - - - label: "Step 3: Reboot target device(DUT)" - verification: | - Did the DUT successfully reboot? - cluster: "LogCommands" - command: "UserPrompt" - PICS: PICS_SKIP_SAMPLE_APP - arguments: - values: - - name: "message" - value: "Please reboot the DUT and enter 'y' after DUT starts" - - name: "expectedValue" - value: "y" - - - label: "Wait for the commissioned device to be retrieved" - cluster: "DelayCommands" - command: "WaitForCommissionee" - arguments: - values: - - name: "nodeId" - value: nodeId - - - label: - "Step 3a: If (CADMIN.S.C01.Rsp) present, DUT put in Commissioning Mode - using Open Basic Commissioning Window command, starting advertising - Commissionable Node Discovery service using DNS-SD" - PICS: CADMIN.S.C01.Rsp - cluster: "Administrator Commissioning" - command: "OpenBasicCommissioningWindow" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "CommissioningTimeout" - value: 180 - - - label: - "If (CADMIN.S.C01.Rsp) present, waiting after opening commissioning - window" - cluster: "DelayCommands" - command: "WaitForMs" - PICS: CADMIN.S.C01.Rsp - arguments: - values: - - name: "ms" - value: waitAfterCommissioning - - - label: - "Step 4a: Check DNS-SD instance name must be 64-bit randomly selected - ID expressed as a sixteen-char hex string with capital letters and - must be different from the one at step 2" - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "instanceName" - constraints: - minLength: 16 - maxLength: 16 - isUpperCase: true - isHexString: true - notValue: deviceInstanceNameBeforeReboot - - - label: - "Step 4aa: If (ICDM.S.A0002) TH reads from the DUT the - ActiveModeThreshold attribute" - PICS: ICDM.S.A0002 - cluster: "ICDManagement" - command: "readAttribute" - attribute: "ActiveModeThreshold" - response: - saveAs: ActiveModeThresholdValue - - - label: "Step 4b: service type must be _matterc._udp" - verification: | - Run the below avahi browse command in TH terminal - - avahi-browse -rt _matterc._udp - - Verify the device is advertising _matterc._udp service like below output in TH terminal Log: (Verify for the DUT's actual values (like vendor ID, PID ..etc) as mentioned in the expected outcome of the test plan, The below log contains the data from the reference raspi accessory) - - + wlan0 IPv6 F6385CBB29F7CE93 _matterc._udp local - + eth0 IPv6 F6385CBB29F7CE93 _matterc._udp local - = eth0 IPv6 F6385CBB29F7CE93 _matterc._udp local - hostname = [E45F010F1A010000.local] - address = [fe80::e65f:1ff:fe0f:1a01] - port = [5540] - txt = ["PI=" "PH=36" "CM=1" "D=3840" "T=1" "VP=65521+32769"] - = wlan0 IPv6 F6385CBB29F7CE93 _matterc._udp local - hostname = [E45F010F1A010000.local] - address = [fe80::e65f:1ff:fe0f:1a01] - port = [5540] - txt = ["PI=" "PH=36" "CM=1" "D=3840" "T=1" "VP=65521+32769"] - - If "ICDM.S.A0002" check "SAT=ActiveModeThreshold Value" - - Service Domain 422F10CDC290A406.local - verify CM flag is 1 - - to look for subtypes, on the raspi run $ avahi-browse -p _services._dns-sd._udp | grep _matterc - - +;eth0;IPv6;_matterc;_udp;local - +;eth0;IPv6;_V65521;_sub._matterc._udp;local - +;eth0;IPv6;_S15;_sub._matterc._udp;local - +;eth0;IPv6;_L3840;_sub._matterc._udp;local - +;eth0;IPv6;_CM;_sub._matterc._udp;local - cluster: "LogCommands" - command: "UserPrompt" - PICS: PICS_SKIP_SAMPLE_APP - arguments: - values: - - name: "message" - value: "Enter 'y' after success" - - name: "expectedValue" - value: "y" - - #validate the service type and the service domain not implemented in CI - - label: - "Step 4c: Check Hostname. If (MCORE.COM.WIFI) OR (MCORE.COM.ETH) - target hostname is derived from the 48bit or 64bit MAC address - expressed as a twelve or sixteen capital letter hex string" - PICS: "(MCORE.COM.WIFI || MCORE.COM.ETH) && !MCORE.COM.THR" - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "hostName" - constraints: - minLength: 12 - maxLength: 16 - isUpperCase: true - isHexString: true - - - label: - "Step 4c: Check Hostname. If (MCORE.COM.THR) target hostname is - derived from the 48bit or 64bit MAC address expressed as a twelve or - sixteen capital letter hex string" - PICS: "(!MCORE.COM.WIFI && !MCORE.COM.ETH) && MCORE.COM.THR" - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "hostName" - constraints: - minLength: 12 - maxLength: 16 - isUpperCase: true - isHexString: true - - - label: "Step 4d: Check Long Discriminator _L" - cluster: "DiscoveryCommands" - command: "FindCommissionableByLongDiscriminator" - arguments: - values: - - name: "value" - value: discriminator - - - label: "Step 4e: Check Short Discriminator (_S)" - cluster: "DiscoveryCommands" - command: "FindCommissionableByShortDiscriminator" - arguments: - values: - - name: "value" - value: shortDiscriminator - - - label: - "Step 4f: If (MCORE.SC.VENDOR_SUBTYPE ) present, subtype _V is - present must be 16-bit vendor id, encoded as a variable-length decimal - number in ASCII text, omitting any leading zeros" - PICS: MCORE.SC.VENDOR_SUBTYPE - cluster: "DiscoveryCommands" - command: "FindCommissionableByVendorId" - arguments: - values: - - name: "value" - value: vendorId - - - label: - "Step 4g: If (MCORE.SC.DEVTYPE_SUBTYPE) present, subtype _T is - present, represents device type from Data Model and must be - represented as a variable length decimal number in ASCII without - leading zeros" - # The device type is not broadcasted by the accessory under CI. - PICS: MCORE.SC.DEVTYPE_SUBTYPE - cluster: "DiscoveryCommands" - command: "FindCommissionableByDeviceType" - arguments: - values: - - name: "value" - value: deviceType - - - label: - "Step 4h: If (CADMIN.S.C01.Rsp) present, check Commissioning Mode - (_CM) subtype _CM is present" - cluster: "DiscoveryCommands" - command: "FindCommissionableByCommissioningMode" - PICS: CADMIN.S.C01.Rsp - - - label: - "Step 4i: key D must be present and represents the discriminator which - must be encoded as a variable-length decimal value with up to 4 digits - omitting any leading zeros" - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "longDiscriminator" - value: discriminator - constraints: - minValue: 0 - maxValue: 4096 - - - label: - "Step 4j: If (MCORE.SC.VP_KEY) present, VP key must contain at least - Vendor ID is present." - PICS: MCORE.SC.VP_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "vendorId" - value: vendorId - - - label: - "Step 4k: If (MCORE.SC.VP_KEY) present, VP key must contain at least - Product ID is present." - PICS: MCORE.SC.VP_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "productId" - value: productId - - - label: - "Step 4l: If (MCORE.SC.SII_OP_DISCOVERY_KEY ) present, SII key must be - an unsigned integer with units of milliseconds and shall be encoded as - a variable length decimal number in ASCII, omitting leading zeros. - Shall not exceed 3600000" - PICS: MCORE.SC.SII_OP_DISCOVERY_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "mrpRetryIntervalIdle" - constraints: - maxValue: 3600000 - - - label: - "Step 4m: If (MCORE.SC.SAI_OP_DISCOVERY_KEY) present, SAI key must be - an unsigned integer with units of milliseconds and shall be encoded as - a variable length decimal number in ASCII, omitting leading zeros. - Shall not exceed 3600000." - PICS: MCORE.SC.SAI_OP_DISCOVERY_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "mrpRetryIntervalActive" - constraints: - maxValue: 3600000 - - - label: - "Step 4n: If (MCORE.SC.SAT_OP_DISCOVERY_KEY) present, SAT key must be - an unsigned integer with units of milliseconds and shall be encoded as - a variable length decimal number in ASCII, omitting leading zeros. - Shall not exceed 65535." - PICS: MCORE.SC.SAI_OP_DISCOVERY_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "mrpRetryActiveThreshold" - constraints: - maxValue: 65535 - - - label: - "Step 4o: If (CADMIN.S.C01.Rsp) present, TXT key for commissioning - mode (CM) key CM=1 must be present" - cluster: "DiscoveryCommands" - command: "FindCommissionable" - PICS: CADMIN.S.C01.Rsp - response: - values: - - name: "commissioningMode" - value: 1 - - - label: - "Step 4p: If (MCORE.SC.DT_KEY) present, DT key must contain the device - type identifier from Data Model Device Types and must be encoded as a - variable length decimal ASCII number without leading zeros" - PICS: MCORE.SC.DT_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "deviceType" - value: deviceType - - - label: - "Step 4q: If (MCORE.SC.DN_KEY) present, DN key must be a UTF-8 encoded - string with a maximum length of 32B" - PICS: MCORE.SC.DN_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "deviceName" - constraints: - maxLength: 32 - - - label: - "Step 4r: If (MCORE.SC.RI_KEY) present, key RI must include the - Rotating Device Identifier encoded as a uppercase string with a - maximum length of 100 chars" - PICS: MCORE.SC.RI_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "rotatingIdLen" - constraints: - maxValue: 100 - - - label: - "Step 4s: If (MCORE.SC.PH_KEY) present, key PH must be encoded as a - variable-length decimal number in ASCII text, omitting any leading - zeros. If present value must be different of 0" - PICS: MCORE.SC.PH_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "pairingHint" - constraints: - notValue: 0 - - - label: - "Step 4t: If (MCORE.SC.PI_KEY) present, key PI must be encoded as a - valid UTF-8 string with a maximum length of 128 bytes" - PICS: MCORE.SC.PI_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "pairingInstruction" - constraints: - maxLength: 128 - - - label: - "Step 4u: DUT must publish AAAA records for each IPv6 address upon - which they are willing to accept Matter messages." - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "numIPs" - constraints: - minValue: 1 - - - label: "Step 5: Wait for OpenBasicCommissioningWindow timeout to expire" - cluster: "DelayCommands" - command: "WaitForMs" - arguments: - values: - - name: "ms" - value: 180000 - - - label: - "Step 6: DUT is Commissioned and instructed to enter in commissioning - mode using Open Commissioning Window command" - cluster: "Administrator Commissioning" - command: "OpenCommissioningWindow" - timedInteractionTimeoutMs: 10000 - PICS: CADMIN.S.C00.Rsp && PICS_SDK_CI_ONLY - arguments: - values: - - name: "CommissioningTimeout" - value: 180 - - name: "PAKEPasscodeVerifier" - value: PakeVerifier - - name: "Discriminator" - value: discriminator - - name: "Iterations" - value: 1000 - - name: "Salt" - value: "SPAKE2P Key Salt" - - #Issue https://github.com/project-chip/connectedhomeip/issues/26127 - - label: - "Step 6: DUT is Commissioned and instructed to enter in commissioning - mode using Open Commissioning Window command" - verification: | - Run the below open-commissioning-window in TH Terminal - - The user needs to change this command to match the longDiscriminator override. - use the same discriminator as the longDiscriminator of the DUT. - - ./chip-tool pairing open-commissioning-window 1 1 200 2000 - - verify success on TH (Chip-tool) logs: - - [1652341411.383669][2929:2934] CHIP:DMG: InvokeResponseMessage = - [1652341411.383720][2929:2934] CHIP:DMG: { - [1652341411.383769][2929:2934] CHIP:DMG: suppressResponse = false, - [1652341411.383821][2929:2934] CHIP:DMG: InvokeResponseIBs = - [1652341411.383886][2929:2934] CHIP:DMG: [ - [1652341411.383936][2929:2934] CHIP:DMG: InvokeResponseIB = - [1652341411.384009][2929:2934] CHIP:DMG: { - [1652341411.384068][2929:2934] CHIP:DMG: CommandStatusIB = - [1652341411.384139][2929:2934] CHIP:DMG: { - [1652341411.384203][2929:2934] CHIP:DMG: CommandPathIB = - [1652341411.384278][2929:2934] CHIP:DMG: { - [1652341411.384349][2929:2934] CHIP:DMG: EndpointId = 0x0, - [1652341411.384427][2929:2934] CHIP:DMG: ClusterId = 0x3c, - [1652341411.384501][2929:2934] CHIP:DMG: CommandId = 0x0, - [1652341411.384624][2929:2934] CHIP:DMG: }, - [1652341411.384722][2929:2934] CHIP:DMG: - [1652341411.384795][2929:2934] CHIP:DMG: StatusIB = - [1652341411.384877][2929:2934] CHIP:DMG: { - [1652341411.384958][2929:2934] CHIP:DMG: status = 0x00 (SUCCESS), - [1652341411.385035][2929:2934] CHIP:DMG: }, - [1652341411.385116][2929:2934] CHIP:DMG: - [1652341411.385188][2929:2934] CHIP:DMG: }, - [1652341411.385271][2929:2934] CHIP:DMG: - [1652341411.385337][2929:2934] CHIP:DMG: }, - [1652341411.385416][2929:2934] CHIP:DMG: - [1652341411.385474][2929:2934] CHIP:DMG: ], - [1652341411.385547][2929:2934] CHIP:DMG: - [1652341411.385605][2929:2934] CHIP:DMG: InteractionModelRevision = 1 - [1652341411.385662][2929:2934] CHIP:DMG: }, - [1652341411.385794][2929:2934] CHIP:DMG: Received Command Response Status for Endpoint=0 Cluster=0x0000_003C Command=0x0000_0000 Status=0x0 - [1652341411.385860][2929:2934] CHIP:CTL: Successfully opened pairing window on the device - cluster: "LogCommands" - command: "UserPrompt" - PICS: PICS_SKIP_SAMPLE_APP && CADMIN.S.C00.Rsp - arguments: - values: - - name: "message" - value: "Enter 'y' after success" - - name: "expectedValue" - value: "y" - - - label: "Waiting after opening commissioning window" - cluster: "DelayCommands" - command: "WaitForMs" - arguments: - values: - - name: "ms" - value: waitAfterCommissioning - - - label: - "Step 7a: DNS-SD instance name must be 64-bit randomly selected ID - expressed as a sixteen-char hex string with capital letters" - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "instanceName" - constraints: - minLength: 16 - maxLength: 16 - isUpperCase: true - isHexString: true - - #validate the service type and the service domain not implemented in CI - - - label: - "Step 7b: Check Hostname.If (MCORE.COM.WIFI) OR (MCORE.COM.ETH) target - hostname is derived from the 48bit or 64bit MAC address expressed as a - twelve or sixteen capital letter hex string." - # On macOS the hostname is the device name and because of it this test is disabled for now. - PICS: "(MCORE.COM.WIFI || MCORE.COM.ETH) && !MCORE.COM.THR" - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "hostName" - constraints: - minLength: 12 - maxLength: 16 - isUpperCase: true - isHexString: true - - - label: - "Step 7b: Check Hostname. If (MCORE.COM.THR) target hostname is - derived from the 48bit or 64bit MAC extended address expressed as a - twelve or sixteen capital letter hex string." - # On macOS the hostname is the device name and because of it this test is disabled for now. - PICS: "(!MCORE.COM.WIFI && !MCORE.COM.ETH) && MCORE.COM.THR" - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "hostName" - constraints: - minLength: 12 - maxLength: 16 - isUpperCase: true - isHexString: true - - - label: "Step 7c: Check Long Discriminator _L" - cluster: "DiscoveryCommands" - command: "FindCommissionableByLongDiscriminator" - arguments: - values: - - name: "value" - value: discriminator - - - label: "Step 7d: Check Short Discriminator (_S)" - cluster: "DiscoveryCommands" - command: "FindCommissionableByShortDiscriminator" - arguments: - values: - - name: "value" - value: shortDiscriminator - - - label: - "Step 7e: If (MCORE.SC.VENDOR_SUBTYPE) present, subtype _V is - present must be 16-bit vendor id, encoded as a variable-length decimal - number in ASCII text, omitting any leading zeros" - PICS: MCORE.SC.VENDOR_SUBTYPE - cluster: "DiscoveryCommands" - command: "FindCommissionableByVendorId" - arguments: - values: - - name: "value" - value: vendorId - - - label: - "Step 7f: If (MCORE.SC.DEVTYPE_SUBTYPE) present, subtype _T is - present, represents device type from Data Model and must be - represented as a variable length decimal number in ASCII without - leading zeros" - # The device type is not broadcasted by the accessory under CI. - PICS: MCORE.SC.DEVTYPE_SUBTYPE - cluster: "DiscoveryCommands" - command: "FindCommissionableByDeviceType" - arguments: - values: - - name: "value" - value: deviceType - - - label: "Step 7g: Check Commissioning Mode (_CM) subtype _CM is present" - cluster: "DiscoveryCommands" - command: "FindCommissionableByCommissioningMode" - - - label: - "Step 7h: If (MCORE.SC.VP_KEY ) present, VP key must contain at least - Vendor ID is present." - PICS: MCORE.SC.VP_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "vendorId" - value: vendorId - - - label: - "Step 7i: If (MCORE.SC.VP_KEY ) present, VP key must contain at least - Product ID is present" - PICS: MCORE.SC.VP_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "productId" - value: productId - - - label: - "Step 7j: Optional TXT key for MRP Retry Interval Idle. if - (MCORE.SC.SII_OP_DISCOVERY_KEY) present, SII key must be an unsigned - integer with units of milliseconds and shall be encoded as a variable - length decimal number in ASCII, omitting leading zeros. Shall not - exceed 3600000" - PICS: MCORE.SC.SII_OP_DISCOVERY_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "mrpRetryIntervalIdle" - constraints: - maxValue: 3600000 - - - label: - "Step 7k: Optional TXT key for MRP Retry Interval Active. if - (MCORE.SC.SAI_OP_DISCOVERY_KEY) present, SAI key must be an unsigned - integer with units of milliseconds and shall be encoded as a variable - length decimal number in ASCII, omitting leading zeros. Shall not - exceed 3600000." - PICS: MCORE.SC.SAI_OP_DISCOVERY_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "mrpRetryIntervalActive" - constraints: - maxValue: 3600000 - - - label: - "Step 7l: Optional TXT key for MRP Retry Active Mode Threshold. If - (MCORE.SC.SAT_OP_DISCOVERY_KEY) present, SAT key must be an unsigned - integer with units of milliseconds and shall be encoded as a variable - length decimal number in ASCII, omitting leading zeros. Shall not - exceed 65535." - PICS: MCORE.SC.SAI_OP_DISCOVERY_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "mrpRetryActiveThreshold" - constraints: - maxValue: 65535 - - - label: "Step 7m: TXT key for commissioning mode. CM=2 must be present" - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "commissioningMode" - value: 2 - - - label: - "Step 7n: If (MCORE.SC.DT_KEY) present, DT key must contain the device - type identifier from Data Model Device Types and must be encoded as a - variable length decimal ASCII number without leading zeros" - PICS: MCORE.SC.DT_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "deviceType" - value: deviceType - - - label: - "Step 7o: If (MCORE.SC.DN_KEY) present, DN key must be a UTF-8 encoded - string with a maximum length of 32B" - PICS: MCORE.SC.DN_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "deviceName" - constraints: - maxLength: 32 - - - label: - "Step 7p: If (MCORE.SC.RI_KEY) present, key RI must include the - Rotating Device Identifier encoded as a uppercase string with a - maximum length of 100 chars" - PICS: MCORE.SC.RI_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "rotatingIdLen" - constraints: - maxValue: 100 - - - label: - "Step 7q: If (MCORE.SC.PH_KEY) present, key PH must be encoded as a - variable-length decimal number in ASCII text, omitting any leading - zeros. If present value must be different of 0" - PICS: MCORE.SC.PH_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "pairingHint" - constraints: - notValue: 0 - - - label: - "Step 7r: If (MCORE.SC.PI_KEY) present, key PI must be encoded as a - valid UTF-8 string with a maximum length of 128 bytes" - PICS: MCORE.SC.PI_KEY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "pairingInstruction" - constraints: - maxLength: 128 - - - label: - "Step 7s: DUT must publish AAAA records for each IPv6 address upon - which they are willing to accept Matter messages" - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "numIPs" - constraints: - minValue: 1 - - - label: "Step 8: Wait for OCW timeout to expire" - cluster: "DelayCommands" - command: "WaitForMs" - arguments: - values: - - name: "ms" - value: 180000 - - - label: - "Step 9: If (MCORE.SC.EXTENDED_DISCOVERY ) enable Extended Discovery. - DUT should start to send Commissionable Node Discovery DNS-SD - advertisements" - verification: | - If the device supports Extended Discovery, pass the PROMPT before the extended time period expires. - - the Device should continue to advertise. Use the avahi-browse command and you should see the _matterc._udp advertisement - - Reference Raspberrypi device is not supporting extended discovery. - cluster: "LogCommands" - command: "UserPrompt" - PICS: PICS_SKIP_SAMPLE_APP && MCORE.SC.EXTENDED_DISCOVERY - arguments: - values: - - name: "message" - value: "Enter 'y' after success" - - name: "expectedValue" - value: "y" - - - label: - "Step 10a: Check DNS-SD instance name must be 64-bit randomly selected - ID expressed as a sixteen-char hex string with capital letters" - PICS: MCORE.SC.EXTENDED_DISCOVERY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "instanceName" - constraints: - minLength: 16 - maxLength: 16 - isUpperCase: true - isHexString: true - - - label: - "Step 10aa: If ( && ICDM.S.A0002) TH reads from the DUT the - ActiveModeThreshold attribute" - PICS: ICDM.S.A0002 - cluster: "ICDManagement" - command: "readAttribute" - attribute: "ActiveModeThreshold" - response: - saveAs: ActiveModeThresholdValue - - - label: "Step 10b: service type must be _matterc._udp" - verification: | - Run and Verify on the below output in TH terminal Log: (Below is the sample log , as RPI doesn't support the extended discovery) - Verify the CM flag value is 0 - - avahi-browse -rt _matterc._udp - Verify the device is advertising _matterc._udp service like below output in TH terminal Log: (Verify for the DUT's actual values (like vendor ID, PID ..etc) as mentioned in the expected outcome of the test plan, The below log contains the data from the reference raspi accessory) - - + wlp0s20f3 IPv6 FD37FE5156C56632 _matterc._udp local - = wlp0s20f3 IPv6 FD37FE5156C56632 _matterc._udp local - hostname = [8C1D96786A130000.local] - address = [fe80::e9f6:2c08:2794:357d] - port = [5540] - txt = ["PI=" "PH=36" "CM=2" "D=3840" "T=1" "DT=65535" "VP=65521+32769"] - cluster: "LogCommands" - command: "UserPrompt" - PICS: PICS_SKIP_SAMPLE_APP && MCORE.SC.EXTENDED_DISCOVERY - arguments: - values: - - name: "message" - value: "Enter 'y' after success" - - name: "expectedValue" - value: "y" - - #validate the service type and the service domain - - - label: - "Step 10c: Check Hostname. If (MCORE.COM.WIFI) OR (MCORE.COM.ETH) - target hostname is derived from the 48bit or 64bit MAC address - expressed as a twelve or sixteen capital letter hex string" - # On macOS the hostname is the device name and because of it this test is disabled for now. - PICS: - "(MCORE.COM.WIFI || MCORE.COM.ETH) && !MCORE.COM.THR && - MCORE.SC.EXTENDED_DISCOVERY" - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "hostName" - constraints: - minLength: 12 - maxLength: 16 - isUpperCase: true - isHexString: true - - - label: - "Step 10c: Check Hostname. If (MCORE.COM.THR) target hostname is - derived from the 48bit or 64bit MAC extended address expressed as a - twelve or sixteen capital letter hex string." - # On macOS the hostname is the device name and because of it this test is disabled for now. - PICS: - "(!MCORE.COM.WIFI && !MCORE.COM.ETH) && MCORE.COM.THR && - MCORE.SC.EXTENDED_DISCOVERY" - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "hostName" - constraints: - minLength: 12 - maxLength: 16 - isUpperCase: true - isHexString: true - - # Commissioning Subtypes - - - label: "Step 10d: Check Long Discriminator _L" - PICS: MCORE.SC.EXTENDED_DISCOVERY - cluster: "DiscoveryCommands" - command: "FindCommissionableByLongDiscriminator" - arguments: - values: - - name: "value" - value: discriminator - - - label: "Step 10e: Check Short Discriminator (_S)" - PICS: MCORE.SC.EXTENDED_DISCOVERY - cluster: "DiscoveryCommands" - command: "FindCommissionableByShortDiscriminator" - arguments: - values: - - name: "value" - value: shortDiscriminator - - - label: - "Step 10f: If (MCORE.SC.VENDOR_SUBTYPE ) present, subtype _V is - present must be 16-bit vendor id, encoded as a variable-length decimal - number in ASCII text, omitting any leading zeros" - PICS: MCORE.SC.VENDOR_SUBTYPE && MCORE.SC.EXTENDED_DISCOVERY - cluster: "DiscoveryCommands" - command: "FindCommissionableByVendorId" - arguments: - values: - - name: "value" - value: vendorId - - - label: - "Step 10g: If (MCORE.SC.DEVTYPE_SUBTYPE) present, subtype _T is - present, represents device type from Data Model and must be - represented as a variable length decimal number in ASCII without - leading zeros" - # The device type is not broadcasted by the accessory under CI. - PICS: MCORE.SC.DEVTYPE_SUBTYPE && MCORE.SC.EXTENDED_DISCOVERY - cluster: "DiscoveryCommands" - command: "FindCommissionableByDeviceType" - arguments: - values: - - name: "value" - value: deviceType - - #TODO - - label: "Step 10h: Check Commissioning Mode (_CM)" - verification: | - subtype _CM must not be present - cluster: "LogCommands" - command: "UserPrompt" - PICS: PICS_SKIP_SAMPLE_APP && MCORE.SC.EXTENDED_DISCOVERY - arguments: - values: - - name: "message" - value: "Enter 'y' after success" - - name: "expectedValue" - value: "y" - - # TXT Records - - - label: "Step 10i: TXT key for discriminator (D)" - PICS: MCORE.SC.EXTENDED_DISCOVERY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "longDiscriminator" - value: discriminator - constraints: - minValue: 0 - maxValue: 4096 - - - label: - "Step 10j: If (MCORE.SC.VP_KEY) present, VP key must contain at least - Vendor ID is present" - PICS: MCORE.SC.VP_KEY && MCORE.SC.EXTENDED_DISCOVERY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "vendorId" - value: vendorId - - - label: - "Step 10k: If (MCORE.SC.VP_KEY) present, VP key must contain at least - Product ID is present" - PICS: MCORE.SC.VP_KEY && MCORE.SC.EXTENDED_DISCOVERY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "productId" - value: productId - - - label: - "Step 10l: If (MCORE.SC.SII_OP_DISCOVERY_KEY) present, SII key must be - an unsigned integer with units of milliseconds and shall be encoded as - a variable length decimal number in ASCII, omitting leading zeros. - Shall not exceed 3600000." - PICS: MCORE.SC.SII_OP_DISCOVERY_KEY && MCORE.SC.EXTENDED_DISCOVERY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "mrpRetryIntervalIdle" - constraints: - maxValue: 3600000 - - - label: - "Step 10m: If (MCORE.SC.SAI_OP_DISCOVERY_KEY) present, SAI key must be - an unsigned integer with units of milliseconds and shall be encoded as - a variable length decimal number in ASCII, omitting leading zeros. - Shall not exceed 3600000." - PICS: MCORE.SC.SAI_OP_DISCOVERY_KEY && MCORE.SC.EXTENDED_DISCOVERY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "mrpRetryIntervalActive" - constraints: - maxValue: 3600000 - - - label: - "Step 10n: If (MCORE.SC.SAT_OP_DISCOVERY_KEY) present, SAT key must be - an unsigned integer with units of milliseconds and shall be encoded as - a variable length decimal number in ASCII, omitting leading zeros. - Shall not exceed 65535." - PICS: MCORE.SC.SAI_OP_DISCOVERY_KEY && MCORE.SC.EXTENDED_DISCOVERY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "mrpRetryActiveThreshold" - constraints: - maxValue: 65535 - - - label: - "Step 10o: TXT key for commissioning mode (CM), CM=0 may be present" - PICS: MCORE.SC.EXTENDED_DISCOVERY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "commissioningMode" - value: 0 - - - label: - "Step 10p: If (MCORE.SC.DT_KEY) present, DT key must contain the - device type identifier from Data Model Device Types and must be - encoded as a variable length decimal ASCII number without leading - zeros" - PICS: MCORE.SC.DT_KEY && MCORE.SC.EXTENDED_DISCOVERY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "deviceType" - value: deviceType - - - label: - "Step 10q: If (MCORE.SC.DN_KEY) present, DN key must be a UTF-8 - encoded string with a maximum length of 32B" - PICS: MCORE.SC.DN_KEY && MCORE.SC.EXTENDED_DISCOVERY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "deviceName" - constraints: - maxLength: 32 - - - label: - "Step 10r: If (MCORE.SC.RI_KEY) present, key RI must include the - Rotating Device Identifier encoded as a uppercase string with a - maximum length of 100 chars" - PICS: MCORE.SC.RI_KEY && MCORE.SC.EXTENDED_DISCOVERY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "rotatingIdLen" - constraints: - maxValue: 100 - - - label: - "Step 10s: If (MCORE.SC.PH_KEY) present, key PH must be encoded as a - variable-length decimal number in ASCII text, omitting any leading - zeros. If present value must be different of 0" - PICS: MCORE.SC.PH_KEY && MCORE.SC.EXTENDED_DISCOVERY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "pairingHint" - constraints: - notValue: 0 - - - label: - "Step 10t: If (MCORE.SC.PI_KEY) present, key PI must be encoded as a - valid UTF-8 string with a maximum length of 128 bytes" - PICS: MCORE.SC.PI_KEY && MCORE.SC.EXTENDED_DISCOVERY - cluster: "DiscoveryCommands" - command: "FindCommissionable" - response: - values: - - name: "pairingInstruction" - constraints: - maxLength: 128 diff --git a/src/app/tests/suites/certification/ci-pics-values b/src/app/tests/suites/certification/ci-pics-values index 80d563020ba..6b38d46ffe7 100644 --- a/src/app/tests/suites/certification/ci-pics-values +++ b/src/app/tests/suites/certification/ci-pics-values @@ -2101,6 +2101,7 @@ MCORE.SC.PI_KEY=1 MCORE.SC.EXTENDED_DISCOVERY=0 MCORE.SC.SED=1 MCORE.SC.ADV=1 +MCORE.SC.TCP=1 MCORE.ROLE.COMMISSIONEE=1 MCORE.ROLE.COMMISSIONER=0 MCORE.ROLE.CONTROLLER=0 diff --git a/src/app/tests/suites/manualTests.json b/src/app/tests/suites/manualTests.json index 3cd2050ec04..f2461a1e17e 100644 --- a/src/app/tests/suites/manualTests.json +++ b/src/app/tests/suites/manualTests.json @@ -202,7 +202,6 @@ "Test_TC_SC_3_2", "Test_TC_SC_3_3", "Test_TC_SC_3_4", - "Test_TC_SC_4_1", "Test_TC_SC_4_2", "Test_TC_SC_4_4", "Test_TC_SC_4_5", diff --git a/src/app/zap-templates/zcl/data-model/chip/camera-av-settings-user-level-management-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/camera-av-settings-user-level-management-cluster.xml index 64939f9c2d2..ffff0b34c45 100644 --- a/src/app/zap-templates/zcl/data-model/chip/camera-av-settings-user-level-management-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/camera-av-settings-user-level-management-cluster.xml @@ -86,22 +86,22 @@ Git: 0.7-summer-2025-ncr-1615-gf52f22908
- + - + - + - + diff --git a/src/app/zap-templates/zcl/data-model/chip/camera-av-stream-management-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/camera-av-stream-management-cluster.xml index 1ab32e836d4..b9c61172a2a 100644 --- a/src/app/zap-templates/zcl/data-model/chip/camera-av-stream-management-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/camera-av-stream-management-cluster.xml @@ -1,6 +1,6 @@ @@ -32,6 +32,7 @@ Alchemy: v1.5.55 + @@ -87,7 +88,7 @@ Alchemy: v1.5.55 - + @@ -95,7 +96,7 @@ Alchemy: v1.5.55 - + @@ -465,7 +466,7 @@ Alchemy: v1.5.55 This command SHALL allocate a snapshot stream on the device and return an allocated snapshot stream identifier. - + @@ -531,7 +532,7 @@ Alchemy: v1.5.55 This command SHALL be sent by the device in response to the CaptureSnapshot command, carrying the requested snapshot. - + diff --git a/src/app/zap-templates/zcl/data-model/chip/chime-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/chime-cluster.xml index 886c92efefb..d068f6ef217 100644 --- a/src/app/zap-templates/zcl/data-model/chip/chime-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/chime-cluster.xml @@ -1,6 +1,6 @@ @@ -36,13 +37,28 @@ Git: 0.7-summer-2025-1-ge4654a5ef This cluster provides facilities to configure and play Chime sounds, such as those used in a doorbell. true true - - InstalledChimeSounds - SelectedChime - Enabled - - + + + + + + This command will play the currently selected chime or the chime passed in. + + + + This event SHALL indicate a Chime sound has just started playing. + + + + + + + + + + + diff --git a/src/app/zap-templates/zcl/data-model/chip/global-structs.xml b/src/app/zap-templates/zcl/data-model/chip/global-structs.xml index c1e4569559f..0c2859afdc4 100644 --- a/src/app/zap-templates/zcl/data-model/chip/global-structs.xml +++ b/src/app/zap-templates/zcl/data-model/chip/global-structs.xml @@ -1,6 +1,6 @@ @@ -114,5 +114,7 @@ Alchemy: v1.5.55 + + diff --git a/src/app/zap-templates/zcl/data-model/chip/push-av-stream-transport-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/push-av-stream-transport-cluster.xml index 03ba7248482..4e5b408292b 100644 --- a/src/app/zap-templates/zcl/data-model/chip/push-av-stream-transport-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/push-av-stream-transport-cluster.xml @@ -1,6 +1,6 @@ @@ -52,6 +52,8 @@ Alchemy: v1.5.55 + + @@ -72,8 +74,15 @@ Alchemy: v1.5.55 + + + + + + + @@ -82,7 +91,7 @@ Alchemy: v1.5.55 - + @@ -124,6 +133,8 @@ Alchemy: v1.5.55 + + @@ -141,7 +152,13 @@ Alchemy: v1.5.55 - + + + + + + + Cameras Push AV Stream Transport 0x0555 @@ -157,7 +174,7 @@ Alchemy: v1.5.55 true - + @@ -196,7 +213,7 @@ Alchemy: v1.5.55 This command SHALL be generated to request the Node to manually start the specified push transport. - + @@ -216,13 +233,17 @@ Alchemy: v1.5.55 - + + + This event SHALL indicate a push transport transmission has begun. - This event SHALL indicate a push transport transmission has ended. + + + This event SHALL indicate a push transport upload of the indicated recording has completed. diff --git a/src/app/zap-templates/zcl/data-model/chip/tls-certificate-management-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/tls-certificate-management-cluster.xml index ed1ae6f3506..ae302224d9c 100644 --- a/src/app/zap-templates/zcl/data-model/chip/tls-certificate-management-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/tls-certificate-management-cluster.xml @@ -1,6 +1,6 @@ diff --git a/src/app/zap-templates/zcl/data-model/chip/tls-client-management-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/tls-client-management-cluster.xml index 3fcee8f4467..4ae148e80f4 100644 --- a/src/app/zap-templates/zcl/data-model/chip/tls-client-management-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/tls-client-management-cluster.xml @@ -1,6 +1,6 @@ diff --git a/src/app/zap-templates/zcl/data-model/chip/webrtc-provider-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/webrtc-provider-cluster.xml index b2a43e622c6..3f06c80cf98 100644 --- a/src/app/zap-templates/zcl/data-model/chip/webrtc-provider-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/webrtc-provider-cluster.xml @@ -1,6 +1,6 @@ @@ -45,8 +46,8 @@ Git: 0.9-fall2025-432-g64aebe458 - - + + @@ -56,10 +57,12 @@ Git: 0.9-fall2025-432-g64aebe458 - + + + @@ -80,10 +83,12 @@ Git: 0.9-fall2025-432-g64aebe458 - + + + diff --git a/src/app/zap-templates/zcl/data-model/chip/webrtc-requestor-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/webrtc-requestor-cluster.xml index 0f1e9cb32c6..bf7cb716114 100644 --- a/src/app/zap-templates/zcl/data-model/chip/webrtc-requestor-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/webrtc-requestor-cluster.xml @@ -1,6 +1,6 @@ @@ -30,8 +31,8 @@ Git: 0.9-fall2025-22-gb3c08d7c1 The WebRTC transport requestor cluster provides a way for stream consumers (e.g. Matter Stream Viewer) to establish a WebRTC connection with a stream provider. true true - - + + diff --git a/src/app/zap-templates/zcl/data-model/chip/zone-management-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/zone-management-cluster.xml index 784c2d12957..926585db896 100644 --- a/src/app/zap-templates/zcl/data-model/chip/zone-management-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/zone-management-cluster.xml @@ -1,6 +1,6 @@ diff --git a/src/app/zap-templates/zcl/zcl-with-test-extensions.json b/src/app/zap-templates/zcl/zcl-with-test-extensions.json index 2293bc5b959..54545a6a4e0 100644 --- a/src/app/zap-templates/zcl/zcl-with-test-extensions.json +++ b/src/app/zap-templates/zcl/zcl-with-test-extensions.json @@ -820,7 +820,17 @@ "StatusLightBrightness", "FeatureMap" ], - "Camera AV Settings User Level Management": ["MPTZPosition"], + "Camera AV Settings User Level Management": [ + "FeatureMap", + "MPTZPosition", + "MaxPresets", + "ZoomMax", + "TiltMin", + "TiltMax", + "PanMin", + "PanMax", + "MovementState" + ], "Fixed Label": ["LabelList", "ClusterRevision", "FeatureMap"], "Soil Measurement": [ "SoilMoistureMeasurementLimits", diff --git a/src/app/zap-templates/zcl/zcl.json b/src/app/zap-templates/zcl/zcl.json index bee58fc8af2..70b557f6cea 100644 --- a/src/app/zap-templates/zcl/zcl.json +++ b/src/app/zap-templates/zcl/zcl.json @@ -820,7 +820,17 @@ "StatusLightBrightness", "FeatureMap" ], - "Camera AV Settings User Level Management": ["MPTZPosition"], + "Camera AV Settings User Level Management": [ + "FeatureMap", + "MPTZPosition", + "MaxPresets", + "ZoomMax", + "TiltMin", + "TiltMax", + "PanMin", + "PanMax", + "MovementState" + ], "Fixed Label": ["LabelList", "ClusterRevision", "FeatureMap"], "Soil Measurement": [ "SoilMoistureMeasurementLimits", diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index cb70794679f..856547e69f7 100644 --- a/src/controller/data_model/controller-clusters.matter +++ b/src/controller/data_model/controller-clusters.matter @@ -352,6 +352,8 @@ fabric_scoped struct WebRTCSessionStruct { nullable int16u videoStreamID = 4; nullable int16u audioStreamID = 5; boolean metadataEnabled = 6; + optional int16u videoStreams[] = 7; + optional int16u audioStreams[] = 8; fabric_idx fabricIndex = 254; } @@ -10050,6 +10052,7 @@ cluster CameraAvStreamManagement = 1361 { enum ImageCodecEnum : enum8 { kJPEG = 0 [spec_name = "JPEG"]; + kHEIC = 1 [spec_name = "HEIC"]; } enum TriStateAutoEnum : enum8 { @@ -10417,7 +10420,7 @@ cluster CameraAvSettingsUserLevelManagement = 1362 { /** The WebRTC transport provider cluster provides a way for stream providers (e.g. Cameras) to stream or receive their data through WebRTC. */ cluster WebRTCTransportProvider = 1363 { - revision 1; + revision 2; bitmap Feature : bitmap32 { kMetadata = 0x1; @@ -10445,6 +10448,8 @@ cluster WebRTCTransportProvider = 1363 { optional char_string<16> ICETransportPolicy = 5; optional boolean metadataEnabled = 6; optional SFrameStruct SFrameConfig = 7; + optional int16u videoStreams[] = 8; + optional int16u audioStreams[] = 9; } response struct SolicitOfferResponse = 1 { @@ -10465,6 +10470,8 @@ cluster WebRTCTransportProvider = 1363 { optional char_string<16> ICETransportPolicy = 7; optional boolean metadataEnabled = 8; optional SFrameStruct SFrameConfig = 9; + optional int16u videoStreams[] = 10; + optional int16u audioStreams[] = 11; } response struct ProvideOfferResponse = 3 { @@ -10502,7 +10509,7 @@ cluster WebRTCTransportProvider = 1363 { /** The WebRTC transport requestor cluster provides a way for stream consumers (e.g. Matter Stream Viewer) to establish a WebRTC connection with a stream provider. */ cluster WebRTCTransportRequestor = 1364 { - revision 1; + revision 2; readonly attribute access(read: administer) WebRTCSessionStruct currentSessions[] = 0; readonly attribute command_id generatedCommandList[] = 65528; @@ -10545,7 +10552,7 @@ cluster WebRTCTransportRequestor = 1364 { /** This cluster implements the upload of Audio and Video streams from the Push AV Stream Transport Cluster using suitable push-based transports. */ cluster PushAvStreamTransport = 1365 { - revision 1; + revision 2; enum CMAFInterfaceEnum : enum8 { kInterface1 = 0; @@ -10572,6 +10579,8 @@ cluster PushAvStreamTransport = 1365 { kInvalidOptions = 9; kInvalidStreamUsage = 10; kInvalidTime = 11; + kInvalidPreRollLength = 12; + kDuplicateStreamValues = 13; } enum TransportStatusEnum : enum8 { @@ -10589,6 +10598,7 @@ cluster PushAvStreamTransport = 1365 { kUserInitiated = 0; kAutomation = 1; kEmergency = 2; + kDoorbellPressed = 3; } bitmap Feature : bitmap32 { @@ -10608,6 +10618,16 @@ cluster PushAvStreamTransport = 1365 { optional int8u sensitivity = 1; } + struct AudioStreamStruct { + char_string<16> audioStreamName = 0; + int16u audioStreamID = 1; + } + + struct VideoStreamStruct { + char_string<16> videoStreamName = 0; + int16u videoStreamID = 1; + } + struct TransportTriggerOptionsStruct { TransportTriggerTypeEnum triggerType = 0; optional nullable TransportZoneOptionsStruct motionZones[] = 1; @@ -10642,6 +10662,8 @@ cluster PushAvStreamTransport = 1365 { IngestMethodsEnum ingestMethod = 6; ContainerOptionsStruct containerOptions = 7; optional epoch_s expiryTime = 8; + optional VideoStreamStruct videoStreams[] = 9; + optional AudioStreamStruct audioStreams[] = 10; } fabric_scoped struct TransportConfigurationStruct { @@ -10660,10 +10682,14 @@ cluster PushAvStreamTransport = 1365 { int16u connectionID = 0; TransportTriggerTypeEnum triggerType = 1; optional TriggerActivationReasonEnum activationReason = 2; + ContainerFormatEnum containerType = 3; + optional int64u CMAFSessionNumber = 4; } info event PushTransportEnd = 1 { int16u connectionID = 0; + ContainerFormatEnum containerType = 1; + optional int64u CMAFSessionNumber = 2; } readonly attribute SupportedFormatStruct supportedFormats[] = 0; @@ -10727,13 +10753,17 @@ cluster PushAvStreamTransport = 1365 { /** This cluster provides facilities to configure and play Chime sounds, such as those used in a doorbell. */ cluster Chime = 1366 { - revision 1; + revision 2; struct ChimeSoundStruct { int8u chimeID = 0; char_string<48> name = 1; } + info event ChimeStartedPlaying = 0 { + int8u chimeID = 0; + } + readonly attribute ChimeSoundStruct installedChimeSounds[] = 0; attribute int8u selectedChime = 1; attribute boolean enabled = 2; @@ -10743,7 +10773,12 @@ cluster Chime = 1366 { readonly attribute bitmap32 featureMap = 65532; readonly attribute int16u clusterRevision = 65533; - command PlayChimeSound(): DefaultSuccess = 0; + request struct PlayChimeSoundRequest { + optional int8u chimeID = 0; + } + + /** This command will play the currently selected chime or the chime passed in. */ + command PlayChimeSound(PlayChimeSoundRequest): DefaultSuccess = 0; } /** The CommodityTariffCluster provides the mechanism for communicating Commodity Tariff information within the premises. */ diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java index 69ef1c2123a..dbd2f7668ce 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java @@ -60959,11 +60959,11 @@ public long initWithDevice(long devicePtr, int endpointId) { return 0L; } - public void solicitOffer(SolicitOfferResponseCallback callback, Integer streamUsage, Integer originatingEndpointID, @Nullable Optional videoStreamID, @Nullable Optional audioStreamID, Optional> ICEServers, Optional ICETransportPolicy, Optional metadataEnabled, Optional SFrameConfig) { - solicitOffer(callback, streamUsage, originatingEndpointID, videoStreamID, audioStreamID, ICEServers, ICETransportPolicy, metadataEnabled, SFrameConfig, 0); + public void solicitOffer(SolicitOfferResponseCallback callback, Integer streamUsage, Integer originatingEndpointID, @Nullable Optional videoStreamID, @Nullable Optional audioStreamID, Optional> ICEServers, Optional ICETransportPolicy, Optional metadataEnabled, Optional SFrameConfig, Optional> videoStreams, Optional> audioStreams) { + solicitOffer(callback, streamUsage, originatingEndpointID, videoStreamID, audioStreamID, ICEServers, ICETransportPolicy, metadataEnabled, SFrameConfig, videoStreams, audioStreams, 0); } - public void solicitOffer(SolicitOfferResponseCallback callback, Integer streamUsage, Integer originatingEndpointID, @Nullable Optional videoStreamID, @Nullable Optional audioStreamID, Optional> ICEServers, Optional ICETransportPolicy, Optional metadataEnabled, Optional SFrameConfig, int timedInvokeTimeoutMs) { + public void solicitOffer(SolicitOfferResponseCallback callback, Integer streamUsage, Integer originatingEndpointID, @Nullable Optional videoStreamID, @Nullable Optional audioStreamID, Optional> ICEServers, Optional ICETransportPolicy, Optional metadataEnabled, Optional SFrameConfig, Optional> videoStreams, Optional> audioStreams, int timedInvokeTimeoutMs) { final long commandId = 0L; ArrayList elements = new ArrayList<>(); @@ -60999,6 +60999,14 @@ public void solicitOffer(SolicitOfferResponseCallback callback, Integer streamUs BaseTLVType SFrameConfigtlvValue = SFrameConfig.map((nonOptionalSFrameConfig) -> nonOptionalSFrameConfig.encodeTlv()).orElse(new EmptyType()); elements.add(new StructElement(SFrameConfigFieldID, SFrameConfigtlvValue)); + final long videoStreamsFieldID = 8L; + BaseTLVType videoStreamstlvValue = videoStreams.map((nonOptionalvideoStreams) -> ArrayType.generateArrayType(nonOptionalvideoStreams, (elementnonOptionalvideoStreams) -> new UIntType(elementnonOptionalvideoStreams))).orElse(new EmptyType()); + elements.add(new StructElement(videoStreamsFieldID, videoStreamstlvValue)); + + final long audioStreamsFieldID = 9L; + BaseTLVType audioStreamstlvValue = audioStreams.map((nonOptionalaudioStreams) -> ArrayType.generateArrayType(nonOptionalaudioStreams, (elementnonOptionalaudioStreams) -> new UIntType(elementnonOptionalaudioStreams))).orElse(new EmptyType()); + elements.add(new StructElement(audioStreamsFieldID, audioStreamstlvValue)); + StructType commandArgs = new StructType(elements); invoke(new InvokeCallbackImpl(callback) { @Override @@ -61038,11 +61046,11 @@ public void onResponse(StructType invokeStructValue) { }}, commandId, commandArgs, timedInvokeTimeoutMs); } - public void provideOffer(ProvideOfferResponseCallback callback, @Nullable Integer webRTCSessionID, String sdp, Integer streamUsage, Integer originatingEndpointID, @Nullable Optional videoStreamID, @Nullable Optional audioStreamID, Optional> ICEServers, Optional ICETransportPolicy, Optional metadataEnabled, Optional SFrameConfig) { - provideOffer(callback, webRTCSessionID, sdp, streamUsage, originatingEndpointID, videoStreamID, audioStreamID, ICEServers, ICETransportPolicy, metadataEnabled, SFrameConfig, 0); + public void provideOffer(ProvideOfferResponseCallback callback, @Nullable Integer webRTCSessionID, String sdp, Integer streamUsage, Integer originatingEndpointID, @Nullable Optional videoStreamID, @Nullable Optional audioStreamID, Optional> ICEServers, Optional ICETransportPolicy, Optional metadataEnabled, Optional SFrameConfig, Optional> videoStreams, Optional> audioStreams) { + provideOffer(callback, webRTCSessionID, sdp, streamUsage, originatingEndpointID, videoStreamID, audioStreamID, ICEServers, ICETransportPolicy, metadataEnabled, SFrameConfig, videoStreams, audioStreams, 0); } - public void provideOffer(ProvideOfferResponseCallback callback, @Nullable Integer webRTCSessionID, String sdp, Integer streamUsage, Integer originatingEndpointID, @Nullable Optional videoStreamID, @Nullable Optional audioStreamID, Optional> ICEServers, Optional ICETransportPolicy, Optional metadataEnabled, Optional SFrameConfig, int timedInvokeTimeoutMs) { + public void provideOffer(ProvideOfferResponseCallback callback, @Nullable Integer webRTCSessionID, String sdp, Integer streamUsage, Integer originatingEndpointID, @Nullable Optional videoStreamID, @Nullable Optional audioStreamID, Optional> ICEServers, Optional ICETransportPolicy, Optional metadataEnabled, Optional SFrameConfig, Optional> videoStreams, Optional> audioStreams, int timedInvokeTimeoutMs) { final long commandId = 2L; ArrayList elements = new ArrayList<>(); @@ -61086,6 +61094,14 @@ public void provideOffer(ProvideOfferResponseCallback callback, @Nullable Intege BaseTLVType SFrameConfigtlvValue = SFrameConfig.map((nonOptionalSFrameConfig) -> nonOptionalSFrameConfig.encodeTlv()).orElse(new EmptyType()); elements.add(new StructElement(SFrameConfigFieldID, SFrameConfigtlvValue)); + final long videoStreamsFieldID = 10L; + BaseTLVType videoStreamstlvValue = videoStreams.map((nonOptionalvideoStreams) -> ArrayType.generateArrayType(nonOptionalvideoStreams, (elementnonOptionalvideoStreams) -> new UIntType(elementnonOptionalvideoStreams))).orElse(new EmptyType()); + elements.add(new StructElement(videoStreamsFieldID, videoStreamstlvValue)); + + final long audioStreamsFieldID = 11L; + BaseTLVType audioStreamstlvValue = audioStreams.map((nonOptionalaudioStreams) -> ArrayType.generateArrayType(nonOptionalaudioStreams, (elementnonOptionalaudioStreams) -> new UIntType(elementnonOptionalaudioStreams))).orElse(new EmptyType()); + elements.add(new StructElement(audioStreamsFieldID, audioStreamstlvValue)); + StructType commandArgs = new StructType(elements); invoke(new InvokeCallbackImpl(callback) { @Override @@ -62097,14 +62113,18 @@ public long initWithDevice(long devicePtr, int endpointId) { return 0L; } - public void playChimeSound(DefaultClusterCallback callback) { - playChimeSound(callback, 0); + public void playChimeSound(DefaultClusterCallback callback, Optional chimeID) { + playChimeSound(callback, chimeID, 0); } - public void playChimeSound(DefaultClusterCallback callback, int timedInvokeTimeoutMs) { + public void playChimeSound(DefaultClusterCallback callback, Optional chimeID, int timedInvokeTimeoutMs) { final long commandId = 0L; ArrayList elements = new ArrayList<>(); + final long chimeIDFieldID = 0L; + BaseTLVType chimeIDtlvValue = chimeID.map((nonOptionalchimeID) -> new UIntType(nonOptionalchimeID)).orElse(new EmptyType()); + elements.add(new StructElement(chimeIDFieldID, chimeIDtlvValue)); + StructType commandArgs = new StructType(elements); invoke(new InvokeCallbackImpl(callback) { @Override diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipEventStructs.java b/src/controller/java/generated/java/chip/devicecontroller/ChipEventStructs.java index 72fbda77003..edb506aab1f 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipEventStructs.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipEventStructs.java @@ -6997,18 +6997,26 @@ public static class PushAvStreamTransportClusterPushTransportBeginEvent { public Integer connectionID; public Integer triggerType; public Optional activationReason; + public Integer containerType; + public Optional CMAFSessionNumber; private static final long CONNECTION_ID_ID = 0L; private static final long TRIGGER_TYPE_ID = 1L; private static final long ACTIVATION_REASON_ID = 2L; + private static final long CONTAINER_TYPE_ID = 3L; + private static final long CMAF_SESSION_NUMBER_ID = 4L; public PushAvStreamTransportClusterPushTransportBeginEvent( Integer connectionID, Integer triggerType, - Optional activationReason + Optional activationReason, + Integer containerType, + Optional CMAFSessionNumber ) { this.connectionID = connectionID; this.triggerType = triggerType; this.activationReason = activationReason; + this.containerType = containerType; + this.CMAFSessionNumber = CMAFSessionNumber; } public StructType encodeTlv() { @@ -7016,6 +7024,8 @@ public StructType encodeTlv() { values.add(new StructElement(CONNECTION_ID_ID, new UIntType(connectionID))); values.add(new StructElement(TRIGGER_TYPE_ID, new UIntType(triggerType))); values.add(new StructElement(ACTIVATION_REASON_ID, activationReason.map((nonOptionalactivationReason) -> new UIntType(nonOptionalactivationReason)).orElse(new EmptyType()))); + values.add(new StructElement(CONTAINER_TYPE_ID, new UIntType(containerType))); + values.add(new StructElement(CMAF_SESSION_NUMBER_ID, CMAFSessionNumber.map((nonOptionalCMAFSessionNumber) -> new UIntType(nonOptionalCMAFSessionNumber)).orElse(new EmptyType()))); return new StructType(values); } @@ -7027,6 +7037,8 @@ public static PushAvStreamTransportClusterPushTransportBeginEvent decodeTlv(Base Integer connectionID = null; Integer triggerType = null; Optional activationReason = Optional.empty(); + Integer containerType = null; + Optional CMAFSessionNumber = Optional.empty(); for (StructElement element: ((StructType)tlvValue).value()) { if (element.contextTagNum() == CONNECTION_ID_ID) { if (element.value(BaseTLVType.class).type() == TLVType.UInt) { @@ -7043,12 +7055,24 @@ public static PushAvStreamTransportClusterPushTransportBeginEvent decodeTlv(Base UIntType castingValue = element.value(UIntType.class); activationReason = Optional.of(castingValue.value(Integer.class)); } + } else if (element.contextTagNum() == CONTAINER_TYPE_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + containerType = castingValue.value(Integer.class); + } + } else if (element.contextTagNum() == CMAF_SESSION_NUMBER_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + CMAFSessionNumber = Optional.of(castingValue.value(Long.class)); + } } } return new PushAvStreamTransportClusterPushTransportBeginEvent( connectionID, triggerType, - activationReason + activationReason, + containerType, + CMAFSessionNumber ); } @@ -7065,23 +7089,39 @@ public String toString() { output.append("\tactivationReason: "); output.append(activationReason); output.append("\n"); + output.append("\tcontainerType: "); + output.append(containerType); + output.append("\n"); + output.append("\tCMAFSessionNumber: "); + output.append(CMAFSessionNumber); + output.append("\n"); output.append("}\n"); return output.toString(); } } public static class PushAvStreamTransportClusterPushTransportEndEvent { public Integer connectionID; + public Integer containerType; + public Optional CMAFSessionNumber; private static final long CONNECTION_ID_ID = 0L; + private static final long CONTAINER_TYPE_ID = 1L; + private static final long CMAF_SESSION_NUMBER_ID = 2L; public PushAvStreamTransportClusterPushTransportEndEvent( - Integer connectionID + Integer connectionID, + Integer containerType, + Optional CMAFSessionNumber ) { this.connectionID = connectionID; + this.containerType = containerType; + this.CMAFSessionNumber = CMAFSessionNumber; } public StructType encodeTlv() { ArrayList values = new ArrayList<>(); values.add(new StructElement(CONNECTION_ID_ID, new UIntType(connectionID))); + values.add(new StructElement(CONTAINER_TYPE_ID, new UIntType(containerType))); + values.add(new StructElement(CMAF_SESSION_NUMBER_ID, CMAFSessionNumber.map((nonOptionalCMAFSessionNumber) -> new UIntType(nonOptionalCMAFSessionNumber)).orElse(new EmptyType()))); return new StructType(values); } @@ -7091,16 +7131,30 @@ public static PushAvStreamTransportClusterPushTransportEndEvent decodeTlv(BaseTL return null; } Integer connectionID = null; + Integer containerType = null; + Optional CMAFSessionNumber = Optional.empty(); for (StructElement element: ((StructType)tlvValue).value()) { if (element.contextTagNum() == CONNECTION_ID_ID) { if (element.value(BaseTLVType.class).type() == TLVType.UInt) { UIntType castingValue = element.value(UIntType.class); connectionID = castingValue.value(Integer.class); } + } else if (element.contextTagNum() == CONTAINER_TYPE_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + containerType = castingValue.value(Integer.class); + } + } else if (element.contextTagNum() == CMAF_SESSION_NUMBER_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + CMAFSessionNumber = Optional.of(castingValue.value(Long.class)); + } } } return new PushAvStreamTransportClusterPushTransportEndEvent( - connectionID + connectionID, + containerType, + CMAFSessionNumber ); } @@ -7111,6 +7165,58 @@ public String toString() { output.append("\tconnectionID: "); output.append(connectionID); output.append("\n"); + output.append("\tcontainerType: "); + output.append(containerType); + output.append("\n"); + output.append("\tCMAFSessionNumber: "); + output.append(CMAFSessionNumber); + output.append("\n"); + output.append("}\n"); + return output.toString(); + } +} +public static class ChimeClusterChimeStartedPlayingEvent { + public Integer chimeID; + private static final long CHIME_ID_ID = 0L; + + public ChimeClusterChimeStartedPlayingEvent( + Integer chimeID + ) { + this.chimeID = chimeID; + } + + public StructType encodeTlv() { + ArrayList values = new ArrayList<>(); + values.add(new StructElement(CHIME_ID_ID, new UIntType(chimeID))); + + return new StructType(values); + } + + public static ChimeClusterChimeStartedPlayingEvent decodeTlv(BaseTLVType tlvValue) { + if (tlvValue == null || tlvValue.type() != TLVType.Struct) { + return null; + } + Integer chimeID = null; + for (StructElement element: ((StructType)tlvValue).value()) { + if (element.contextTagNum() == CHIME_ID_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + chimeID = castingValue.value(Integer.class); + } + } + } + return new ChimeClusterChimeStartedPlayingEvent( + chimeID + ); + } + + @Override + public String toString() { + StringBuilder output = new StringBuilder(); + output.append("ChimeClusterChimeStartedPlayingEvent {\n"); + output.append("\tchimeID: "); + output.append(chimeID); + output.append("\n"); output.append("}\n"); return output.toString(); } diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java b/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java index dd33190edae..6dfd4be77f1 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java @@ -15838,6 +15838,8 @@ public static class WebRTCTransportProviderClusterWebRTCSessionStruct { public @Nullable Integer videoStreamID; public @Nullable Integer audioStreamID; public Boolean metadataEnabled; + public Optional> videoStreams; + public Optional> audioStreams; public Integer fabricIndex; private static final long ID_ID = 0L; private static final long PEER_NODE_ID_ID = 1L; @@ -15846,6 +15848,8 @@ public static class WebRTCTransportProviderClusterWebRTCSessionStruct { private static final long VIDEO_STREAM_ID_ID = 4L; private static final long AUDIO_STREAM_ID_ID = 5L; private static final long METADATA_ENABLED_ID = 6L; + private static final long VIDEO_STREAMS_ID = 7L; + private static final long AUDIO_STREAMS_ID = 8L; private static final long FABRIC_INDEX_ID = 254L; public WebRTCTransportProviderClusterWebRTCSessionStruct( @@ -15856,6 +15860,8 @@ public WebRTCTransportProviderClusterWebRTCSessionStruct( @Nullable Integer videoStreamID, @Nullable Integer audioStreamID, Boolean metadataEnabled, + Optional> videoStreams, + Optional> audioStreams, Integer fabricIndex ) { this.id = id; @@ -15865,6 +15871,8 @@ public WebRTCTransportProviderClusterWebRTCSessionStruct( this.videoStreamID = videoStreamID; this.audioStreamID = audioStreamID; this.metadataEnabled = metadataEnabled; + this.videoStreams = videoStreams; + this.audioStreams = audioStreams; this.fabricIndex = fabricIndex; } @@ -15877,6 +15885,8 @@ public StructType encodeTlv() { values.add(new StructElement(VIDEO_STREAM_ID_ID, videoStreamID != null ? new UIntType(videoStreamID) : new NullType())); values.add(new StructElement(AUDIO_STREAM_ID_ID, audioStreamID != null ? new UIntType(audioStreamID) : new NullType())); values.add(new StructElement(METADATA_ENABLED_ID, new BooleanType(metadataEnabled))); + values.add(new StructElement(VIDEO_STREAMS_ID, videoStreams.map((nonOptionalvideoStreams) -> ArrayType.generateArrayType(nonOptionalvideoStreams, (elementnonOptionalvideoStreams) -> new UIntType(elementnonOptionalvideoStreams))).orElse(new EmptyType()))); + values.add(new StructElement(AUDIO_STREAMS_ID, audioStreams.map((nonOptionalaudioStreams) -> ArrayType.generateArrayType(nonOptionalaudioStreams, (elementnonOptionalaudioStreams) -> new UIntType(elementnonOptionalaudioStreams))).orElse(new EmptyType()))); values.add(new StructElement(FABRIC_INDEX_ID, new UIntType(fabricIndex))); return new StructType(values); @@ -15893,6 +15903,8 @@ public static WebRTCTransportProviderClusterWebRTCSessionStruct decodeTlv(BaseTL @Nullable Integer videoStreamID = null; @Nullable Integer audioStreamID = null; Boolean metadataEnabled = null; + Optional> videoStreams = Optional.empty(); + Optional> audioStreams = Optional.empty(); Integer fabricIndex = null; for (StructElement element: ((StructType)tlvValue).value()) { if (element.contextTagNum() == ID_ID) { @@ -15930,6 +15942,16 @@ public static WebRTCTransportProviderClusterWebRTCSessionStruct decodeTlv(BaseTL BooleanType castingValue = element.value(BooleanType.class); metadataEnabled = castingValue.value(Boolean.class); } + } else if (element.contextTagNum() == VIDEO_STREAMS_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.Array) { + ArrayType castingValue = element.value(ArrayType.class); + videoStreams = Optional.of(castingValue.map((elementcastingValue) -> elementcastingValue.value(Integer.class))); + } + } else if (element.contextTagNum() == AUDIO_STREAMS_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.Array) { + ArrayType castingValue = element.value(ArrayType.class); + audioStreams = Optional.of(castingValue.map((elementcastingValue) -> elementcastingValue.value(Integer.class))); + } } else if (element.contextTagNum() == FABRIC_INDEX_ID) { if (element.value(BaseTLVType.class).type() == TLVType.UInt) { UIntType castingValue = element.value(UIntType.class); @@ -15945,6 +15967,8 @@ public static WebRTCTransportProviderClusterWebRTCSessionStruct decodeTlv(BaseTL videoStreamID, audioStreamID, metadataEnabled, + videoStreams, + audioStreams, fabricIndex ); } @@ -15974,6 +15998,12 @@ public String toString() { output.append("\tmetadataEnabled: "); output.append(metadataEnabled); output.append("\n"); + output.append("\tvideoStreams: "); + output.append(videoStreams); + output.append("\n"); + output.append("\taudioStreams: "); + output.append(audioStreams); + output.append("\n"); output.append("\tfabricIndex: "); output.append(fabricIndex); output.append("\n"); @@ -16156,6 +16186,8 @@ public static class WebRTCTransportRequestorClusterWebRTCSessionStruct { public @Nullable Integer videoStreamID; public @Nullable Integer audioStreamID; public Boolean metadataEnabled; + public Optional> videoStreams; + public Optional> audioStreams; public Integer fabricIndex; private static final long ID_ID = 0L; private static final long PEER_NODE_ID_ID = 1L; @@ -16164,6 +16196,8 @@ public static class WebRTCTransportRequestorClusterWebRTCSessionStruct { private static final long VIDEO_STREAM_ID_ID = 4L; private static final long AUDIO_STREAM_ID_ID = 5L; private static final long METADATA_ENABLED_ID = 6L; + private static final long VIDEO_STREAMS_ID = 7L; + private static final long AUDIO_STREAMS_ID = 8L; private static final long FABRIC_INDEX_ID = 254L; public WebRTCTransportRequestorClusterWebRTCSessionStruct( @@ -16174,6 +16208,8 @@ public WebRTCTransportRequestorClusterWebRTCSessionStruct( @Nullable Integer videoStreamID, @Nullable Integer audioStreamID, Boolean metadataEnabled, + Optional> videoStreams, + Optional> audioStreams, Integer fabricIndex ) { this.id = id; @@ -16183,6 +16219,8 @@ public WebRTCTransportRequestorClusterWebRTCSessionStruct( this.videoStreamID = videoStreamID; this.audioStreamID = audioStreamID; this.metadataEnabled = metadataEnabled; + this.videoStreams = videoStreams; + this.audioStreams = audioStreams; this.fabricIndex = fabricIndex; } @@ -16195,6 +16233,8 @@ public StructType encodeTlv() { values.add(new StructElement(VIDEO_STREAM_ID_ID, videoStreamID != null ? new UIntType(videoStreamID) : new NullType())); values.add(new StructElement(AUDIO_STREAM_ID_ID, audioStreamID != null ? new UIntType(audioStreamID) : new NullType())); values.add(new StructElement(METADATA_ENABLED_ID, new BooleanType(metadataEnabled))); + values.add(new StructElement(VIDEO_STREAMS_ID, videoStreams.map((nonOptionalvideoStreams) -> ArrayType.generateArrayType(nonOptionalvideoStreams, (elementnonOptionalvideoStreams) -> new UIntType(elementnonOptionalvideoStreams))).orElse(new EmptyType()))); + values.add(new StructElement(AUDIO_STREAMS_ID, audioStreams.map((nonOptionalaudioStreams) -> ArrayType.generateArrayType(nonOptionalaudioStreams, (elementnonOptionalaudioStreams) -> new UIntType(elementnonOptionalaudioStreams))).orElse(new EmptyType()))); values.add(new StructElement(FABRIC_INDEX_ID, new UIntType(fabricIndex))); return new StructType(values); @@ -16211,6 +16251,8 @@ public static WebRTCTransportRequestorClusterWebRTCSessionStruct decodeTlv(BaseT @Nullable Integer videoStreamID = null; @Nullable Integer audioStreamID = null; Boolean metadataEnabled = null; + Optional> videoStreams = Optional.empty(); + Optional> audioStreams = Optional.empty(); Integer fabricIndex = null; for (StructElement element: ((StructType)tlvValue).value()) { if (element.contextTagNum() == ID_ID) { @@ -16248,6 +16290,16 @@ public static WebRTCTransportRequestorClusterWebRTCSessionStruct decodeTlv(BaseT BooleanType castingValue = element.value(BooleanType.class); metadataEnabled = castingValue.value(Boolean.class); } + } else if (element.contextTagNum() == VIDEO_STREAMS_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.Array) { + ArrayType castingValue = element.value(ArrayType.class); + videoStreams = Optional.of(castingValue.map((elementcastingValue) -> elementcastingValue.value(Integer.class))); + } + } else if (element.contextTagNum() == AUDIO_STREAMS_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.Array) { + ArrayType castingValue = element.value(ArrayType.class); + audioStreams = Optional.of(castingValue.map((elementcastingValue) -> elementcastingValue.value(Integer.class))); + } } else if (element.contextTagNum() == FABRIC_INDEX_ID) { if (element.value(BaseTLVType.class).type() == TLVType.UInt) { UIntType castingValue = element.value(UIntType.class); @@ -16263,6 +16315,8 @@ public static WebRTCTransportRequestorClusterWebRTCSessionStruct decodeTlv(BaseT videoStreamID, audioStreamID, metadataEnabled, + videoStreams, + audioStreams, fabricIndex ); } @@ -16292,6 +16346,12 @@ public String toString() { output.append("\tmetadataEnabled: "); output.append(metadataEnabled); output.append("\n"); + output.append("\tvideoStreams: "); + output.append(videoStreams); + output.append("\n"); + output.append("\taudioStreams: "); + output.append(audioStreams); + output.append("\n"); output.append("\tfabricIndex: "); output.append(fabricIndex); output.append("\n"); @@ -16451,6 +16511,128 @@ public String toString() { return output.toString(); } } +public static class PushAvStreamTransportClusterAudioStreamStruct { + public String audioStreamName; + public Integer audioStreamID; + private static final long AUDIO_STREAM_NAME_ID = 0L; + private static final long AUDIO_STREAM_ID_ID = 1L; + + public PushAvStreamTransportClusterAudioStreamStruct( + String audioStreamName, + Integer audioStreamID + ) { + this.audioStreamName = audioStreamName; + this.audioStreamID = audioStreamID; + } + + public StructType encodeTlv() { + ArrayList values = new ArrayList<>(); + values.add(new StructElement(AUDIO_STREAM_NAME_ID, new StringType(audioStreamName))); + values.add(new StructElement(AUDIO_STREAM_ID_ID, new UIntType(audioStreamID))); + + return new StructType(values); + } + + public static PushAvStreamTransportClusterAudioStreamStruct decodeTlv(BaseTLVType tlvValue) { + if (tlvValue == null || tlvValue.type() != TLVType.Struct) { + return null; + } + String audioStreamName = null; + Integer audioStreamID = null; + for (StructElement element: ((StructType)tlvValue).value()) { + if (element.contextTagNum() == AUDIO_STREAM_NAME_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.String) { + StringType castingValue = element.value(StringType.class); + audioStreamName = castingValue.value(String.class); + } + } else if (element.contextTagNum() == AUDIO_STREAM_ID_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + audioStreamID = castingValue.value(Integer.class); + } + } + } + return new PushAvStreamTransportClusterAudioStreamStruct( + audioStreamName, + audioStreamID + ); + } + + @Override + public String toString() { + StringBuilder output = new StringBuilder(); + output.append("PushAvStreamTransportClusterAudioStreamStruct {\n"); + output.append("\taudioStreamName: "); + output.append(audioStreamName); + output.append("\n"); + output.append("\taudioStreamID: "); + output.append(audioStreamID); + output.append("\n"); + output.append("}\n"); + return output.toString(); + } +} +public static class PushAvStreamTransportClusterVideoStreamStruct { + public String videoStreamName; + public Integer videoStreamID; + private static final long VIDEO_STREAM_NAME_ID = 0L; + private static final long VIDEO_STREAM_ID_ID = 1L; + + public PushAvStreamTransportClusterVideoStreamStruct( + String videoStreamName, + Integer videoStreamID + ) { + this.videoStreamName = videoStreamName; + this.videoStreamID = videoStreamID; + } + + public StructType encodeTlv() { + ArrayList values = new ArrayList<>(); + values.add(new StructElement(VIDEO_STREAM_NAME_ID, new StringType(videoStreamName))); + values.add(new StructElement(VIDEO_STREAM_ID_ID, new UIntType(videoStreamID))); + + return new StructType(values); + } + + public static PushAvStreamTransportClusterVideoStreamStruct decodeTlv(BaseTLVType tlvValue) { + if (tlvValue == null || tlvValue.type() != TLVType.Struct) { + return null; + } + String videoStreamName = null; + Integer videoStreamID = null; + for (StructElement element: ((StructType)tlvValue).value()) { + if (element.contextTagNum() == VIDEO_STREAM_NAME_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.String) { + StringType castingValue = element.value(StringType.class); + videoStreamName = castingValue.value(String.class); + } + } else if (element.contextTagNum() == VIDEO_STREAM_ID_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + videoStreamID = castingValue.value(Integer.class); + } + } + } + return new PushAvStreamTransportClusterVideoStreamStruct( + videoStreamName, + videoStreamID + ); + } + + @Override + public String toString() { + StringBuilder output = new StringBuilder(); + output.append("PushAvStreamTransportClusterVideoStreamStruct {\n"); + output.append("\tvideoStreamName: "); + output.append(videoStreamName); + output.append("\n"); + output.append("\tvideoStreamID: "); + output.append(videoStreamID); + output.append("\n"); + output.append("}\n"); + return output.toString(); + } +} public static class PushAvStreamTransportClusterTransportTriggerOptionsStruct { public Integer triggerType; public @Nullable Optional> motionZones; @@ -16779,6 +16961,8 @@ public static class PushAvStreamTransportClusterTransportOptionsStruct { public Integer ingestMethod; public ChipStructs.PushAvStreamTransportClusterContainerOptionsStruct containerOptions; public Optional expiryTime; + public Optional> videoStreams; + public Optional> audioStreams; private static final long STREAM_USAGE_ID = 0L; private static final long VIDEO_STREAM_ID_ID = 1L; private static final long AUDIO_STREAM_ID_ID = 2L; @@ -16788,6 +16972,8 @@ public static class PushAvStreamTransportClusterTransportOptionsStruct { private static final long INGEST_METHOD_ID = 6L; private static final long CONTAINER_OPTIONS_ID = 7L; private static final long EXPIRY_TIME_ID = 8L; + private static final long VIDEO_STREAMS_ID = 9L; + private static final long AUDIO_STREAMS_ID = 10L; public PushAvStreamTransportClusterTransportOptionsStruct( Integer streamUsage, @@ -16798,7 +16984,9 @@ public PushAvStreamTransportClusterTransportOptionsStruct( ChipStructs.PushAvStreamTransportClusterTransportTriggerOptionsStruct triggerOptions, Integer ingestMethod, ChipStructs.PushAvStreamTransportClusterContainerOptionsStruct containerOptions, - Optional expiryTime + Optional expiryTime, + Optional> videoStreams, + Optional> audioStreams ) { this.streamUsage = streamUsage; this.videoStreamID = videoStreamID; @@ -16809,6 +16997,8 @@ public PushAvStreamTransportClusterTransportOptionsStruct( this.ingestMethod = ingestMethod; this.containerOptions = containerOptions; this.expiryTime = expiryTime; + this.videoStreams = videoStreams; + this.audioStreams = audioStreams; } public StructType encodeTlv() { @@ -16822,6 +17012,8 @@ public StructType encodeTlv() { values.add(new StructElement(INGEST_METHOD_ID, new UIntType(ingestMethod))); values.add(new StructElement(CONTAINER_OPTIONS_ID, containerOptions.encodeTlv())); values.add(new StructElement(EXPIRY_TIME_ID, expiryTime.map((nonOptionalexpiryTime) -> new UIntType(nonOptionalexpiryTime)).orElse(new EmptyType()))); + values.add(new StructElement(VIDEO_STREAMS_ID, videoStreams.map((nonOptionalvideoStreams) -> ArrayType.generateArrayType(nonOptionalvideoStreams, (elementnonOptionalvideoStreams) -> elementnonOptionalvideoStreams.encodeTlv())).orElse(new EmptyType()))); + values.add(new StructElement(AUDIO_STREAMS_ID, audioStreams.map((nonOptionalaudioStreams) -> ArrayType.generateArrayType(nonOptionalaudioStreams, (elementnonOptionalaudioStreams) -> elementnonOptionalaudioStreams.encodeTlv())).orElse(new EmptyType()))); return new StructType(values); } @@ -16839,6 +17031,8 @@ public static PushAvStreamTransportClusterTransportOptionsStruct decodeTlv(BaseT Integer ingestMethod = null; ChipStructs.PushAvStreamTransportClusterContainerOptionsStruct containerOptions = null; Optional expiryTime = Optional.empty(); + Optional> videoStreams = Optional.empty(); + Optional> audioStreams = Optional.empty(); for (StructElement element: ((StructType)tlvValue).value()) { if (element.contextTagNum() == STREAM_USAGE_ID) { if (element.value(BaseTLVType.class).type() == TLVType.UInt) { @@ -16885,6 +17079,16 @@ public static PushAvStreamTransportClusterTransportOptionsStruct decodeTlv(BaseT UIntType castingValue = element.value(UIntType.class); expiryTime = Optional.of(castingValue.value(Long.class)); } + } else if (element.contextTagNum() == VIDEO_STREAMS_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.Array) { + ArrayType castingValue = element.value(ArrayType.class); + videoStreams = Optional.of(castingValue.map((elementcastingValue) -> ChipStructs.PushAvStreamTransportClusterVideoStreamStruct.decodeTlv(elementcastingValue))); + } + } else if (element.contextTagNum() == AUDIO_STREAMS_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.Array) { + ArrayType castingValue = element.value(ArrayType.class); + audioStreams = Optional.of(castingValue.map((elementcastingValue) -> ChipStructs.PushAvStreamTransportClusterAudioStreamStruct.decodeTlv(elementcastingValue))); + } } } return new PushAvStreamTransportClusterTransportOptionsStruct( @@ -16896,7 +17100,9 @@ public static PushAvStreamTransportClusterTransportOptionsStruct decodeTlv(BaseT triggerOptions, ingestMethod, containerOptions, - expiryTime + expiryTime, + videoStreams, + audioStreams ); } @@ -16931,6 +17137,12 @@ public String toString() { output.append("\texpiryTime: "); output.append(expiryTime); output.append("\n"); + output.append("\tvideoStreams: "); + output.append(videoStreams); + output.append("\n"); + output.append("\taudioStreams: "); + output.append(audioStreams); + output.append("\n"); output.append("}\n"); return output.toString(); } diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java index 28918e026bd..e1dc5e83588 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java @@ -18577,7 +18577,7 @@ public static Command value(long id) throws NoSuchFieldError { } throw new NoSuchFieldError(); } - }public enum SolicitOfferCommandField {StreamUsage(0),OriginatingEndpointID(1),VideoStreamID(2),AudioStreamID(3),ICEServers(4),ICETransportPolicy(5),MetadataEnabled(6),SFrameConfig(7),; + }public enum SolicitOfferCommandField {StreamUsage(0),OriginatingEndpointID(1),VideoStreamID(2),AudioStreamID(3),ICEServers(4),ICETransportPolicy(5),MetadataEnabled(6),SFrameConfig(7),VideoStreams(8),AudioStreams(9),; private final int id; SolicitOfferCommandField(int id) { this.id = id; @@ -18594,7 +18594,7 @@ public static SolicitOfferCommandField value(int id) throws NoSuchFieldError { } throw new NoSuchFieldError(); } - }public enum ProvideOfferCommandField {WebRTCSessionID(0),Sdp(1),StreamUsage(2),OriginatingEndpointID(3),VideoStreamID(4),AudioStreamID(5),ICEServers(6),ICETransportPolicy(7),MetadataEnabled(8),SFrameConfig(9),; + }public enum ProvideOfferCommandField {WebRTCSessionID(0),Sdp(1),StreamUsage(2),OriginatingEndpointID(3),VideoStreamID(4),AudioStreamID(5),ICEServers(6),ICETransportPolicy(7),MetadataEnabled(8),SFrameConfig(9),VideoStreams(10),AudioStreams(11),; private final int id; ProvideOfferCommandField(int id) { this.id = id; @@ -19109,7 +19109,8 @@ public static Attribute value(long id) throws NoSuchFieldError { } } - public enum Event {; + public enum Event { + ChimeStartedPlaying(0L),; private final long id; Event(long id) { this.id = id; @@ -19148,7 +19149,24 @@ public static Command value(long id) throws NoSuchFieldError { } throw new NoSuchFieldError(); } - }@Override + }public enum PlayChimeSoundCommandField {ChimeID(0),; + private final int id; + PlayChimeSoundCommandField(int id) { + this.id = id; + } + + public int getID() { + return id; + } + public static PlayChimeSoundCommandField value(int id) throws NoSuchFieldError { + for (PlayChimeSoundCommandField field : PlayChimeSoundCommandField.values()) { + if (field.getID() == id) { + return field; + } + } + throw new NoSuchFieldError(); + } + }@Override public String getAttributeName(long id) throws NoSuchFieldError { return Attribute.value(id).toString(); } diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java index cef49d64cda..bed776b1483 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java @@ -30715,6 +30715,12 @@ public Map> getCommandMap() { CommandParameterInfo webRTCTransportProvidersolicitOffermetadataEnabledCommandParameterInfo = new CommandParameterInfo("metadataEnabled", Optional.class, Boolean.class); webRTCTransportProvidersolicitOfferCommandParams.put("metadataEnabled",webRTCTransportProvidersolicitOffermetadataEnabledCommandParameterInfo); + + CommandParameterInfo webRTCTransportProvidersolicitOffervideoStreamsCommandParameterInfo = new CommandParameterInfo("videoStreams", Optional.class, ArrayList.class); + webRTCTransportProvidersolicitOfferCommandParams.put("videoStreams",webRTCTransportProvidersolicitOffervideoStreamsCommandParameterInfo); + + CommandParameterInfo webRTCTransportProvidersolicitOfferaudioStreamsCommandParameterInfo = new CommandParameterInfo("audioStreams", Optional.class, ArrayList.class); + webRTCTransportProvidersolicitOfferCommandParams.put("audioStreams",webRTCTransportProvidersolicitOfferaudioStreamsCommandParameterInfo); InteractionInfo webRTCTransportProvidersolicitOfferInteractionInfo = new InteractionInfo( (cluster, callback, commandArguments) -> { ((ChipClusters.WebRTCTransportProviderCluster) cluster) @@ -30743,6 +30749,12 @@ public Map> getCommandMap() { , (Optional) commandArguments.get("SFrameConfig") + , (Optional>) + commandArguments.get("videoStreams") + + , (Optional>) + commandArguments.get("audioStreams") + ); }, () -> new DelegatedWebRTCTransportProviderClusterSolicitOfferResponseCallback(), @@ -30777,6 +30789,12 @@ public Map> getCommandMap() { CommandParameterInfo webRTCTransportProviderprovideOffermetadataEnabledCommandParameterInfo = new CommandParameterInfo("metadataEnabled", Optional.class, Boolean.class); webRTCTransportProviderprovideOfferCommandParams.put("metadataEnabled",webRTCTransportProviderprovideOffermetadataEnabledCommandParameterInfo); + + CommandParameterInfo webRTCTransportProviderprovideOffervideoStreamsCommandParameterInfo = new CommandParameterInfo("videoStreams", Optional.class, ArrayList.class); + webRTCTransportProviderprovideOfferCommandParams.put("videoStreams",webRTCTransportProviderprovideOffervideoStreamsCommandParameterInfo); + + CommandParameterInfo webRTCTransportProviderprovideOfferaudioStreamsCommandParameterInfo = new CommandParameterInfo("audioStreams", Optional.class, ArrayList.class); + webRTCTransportProviderprovideOfferCommandParams.put("audioStreams",webRTCTransportProviderprovideOfferaudioStreamsCommandParameterInfo); InteractionInfo webRTCTransportProviderprovideOfferInteractionInfo = new InteractionInfo( (cluster, callback, commandArguments) -> { ((ChipClusters.WebRTCTransportProviderCluster) cluster) @@ -30811,6 +30829,12 @@ public Map> getCommandMap() { , (Optional) commandArguments.get("SFrameConfig") + , (Optional>) + commandArguments.get("videoStreams") + + , (Optional>) + commandArguments.get("audioStreams") + ); }, () -> new DelegatedWebRTCTransportProviderClusterProvideOfferResponseCallback(), @@ -31112,10 +31136,15 @@ public Map> getCommandMap() { Map chimeClusterInteractionInfoMap = new LinkedHashMap<>(); Map chimeplayChimeSoundCommandParams = new LinkedHashMap(); + + CommandParameterInfo chimeplayChimeSoundchimeIDCommandParameterInfo = new CommandParameterInfo("chimeID", Optional.class, Integer.class); + chimeplayChimeSoundCommandParams.put("chimeID",chimeplayChimeSoundchimeIDCommandParameterInfo); InteractionInfo chimeplayChimeSoundInteractionInfo = new InteractionInfo( (cluster, callback, commandArguments) -> { ((ChipClusters.ChimeCluster) cluster) .playChimeSound((DefaultClusterCallback) callback + , (Optional) + commandArguments.get("chimeID") ); }, () -> new DelegatedDefaultClusterCallback(), diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/ChimeClusterChimeStartedPlayingEvent.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/ChimeClusterChimeStartedPlayingEvent.kt new file mode 100644 index 00000000000..d2975629d11 --- /dev/null +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/ChimeClusterChimeStartedPlayingEvent.kt @@ -0,0 +1,52 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package chip.devicecontroller.cluster.eventstructs + +import chip.devicecontroller.cluster.* +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class ChimeClusterChimeStartedPlayingEvent(val chimeID: UInt) { + override fun toString(): String = buildString { + append("ChimeClusterChimeStartedPlayingEvent {\n") + append("\tchimeID : $chimeID\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + put(ContextSpecificTag(TAG_CHIME_ID), chimeID) + endStructure() + } + } + + companion object { + private const val TAG_CHIME_ID = 0 + + fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): ChimeClusterChimeStartedPlayingEvent { + tlvReader.enterStructure(tlvTag) + val chimeID = tlvReader.getUInt(ContextSpecificTag(TAG_CHIME_ID)) + + tlvReader.exitContainer() + + return ChimeClusterChimeStartedPlayingEvent(chimeID) + } + } +} diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/PushAvStreamTransportClusterPushTransportBeginEvent.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/PushAvStreamTransportClusterPushTransportBeginEvent.kt index c95fd429ca2..1e4db338418 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/PushAvStreamTransportClusterPushTransportBeginEvent.kt +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/PushAvStreamTransportClusterPushTransportBeginEvent.kt @@ -27,12 +27,16 @@ class PushAvStreamTransportClusterPushTransportBeginEvent( val connectionID: UInt, val triggerType: UInt, val activationReason: Optional, + val containerType: UInt, + val CMAFSessionNumber: Optional, ) { override fun toString(): String = buildString { append("PushAvStreamTransportClusterPushTransportBeginEvent {\n") append("\tconnectionID : $connectionID\n") append("\ttriggerType : $triggerType\n") append("\tactivationReason : $activationReason\n") + append("\tcontainerType : $containerType\n") + append("\tCMAFSessionNumber : $CMAFSessionNumber\n") append("}\n") } @@ -45,6 +49,11 @@ class PushAvStreamTransportClusterPushTransportBeginEvent( val optactivationReason = activationReason.get() put(ContextSpecificTag(TAG_ACTIVATION_REASON), optactivationReason) } + put(ContextSpecificTag(TAG_CONTAINER_TYPE), containerType) + if (CMAFSessionNumber.isPresent) { + val optCMAFSessionNumber = CMAFSessionNumber.get() + put(ContextSpecificTag(TAG_CMAF_SESSION_NUMBER), optCMAFSessionNumber) + } endStructure() } } @@ -53,6 +62,8 @@ class PushAvStreamTransportClusterPushTransportBeginEvent( private const val TAG_CONNECTION_ID = 0 private const val TAG_TRIGGER_TYPE = 1 private const val TAG_ACTIVATION_REASON = 2 + private const val TAG_CONTAINER_TYPE = 3 + private const val TAG_CMAF_SESSION_NUMBER = 4 fun fromTlv( tlvTag: Tag, @@ -67,6 +78,13 @@ class PushAvStreamTransportClusterPushTransportBeginEvent( } else { Optional.empty() } + val containerType = tlvReader.getUInt(ContextSpecificTag(TAG_CONTAINER_TYPE)) + val CMAFSessionNumber = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_CMAF_SESSION_NUMBER))) { + Optional.of(tlvReader.getULong(ContextSpecificTag(TAG_CMAF_SESSION_NUMBER))) + } else { + Optional.empty() + } tlvReader.exitContainer() @@ -74,6 +92,8 @@ class PushAvStreamTransportClusterPushTransportBeginEvent( connectionID, triggerType, activationReason, + containerType, + CMAFSessionNumber, ) } } diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/PushAvStreamTransportClusterPushTransportEndEvent.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/PushAvStreamTransportClusterPushTransportEndEvent.kt index 1bc03e63e9a..63e85ee1f5b 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/PushAvStreamTransportClusterPushTransportEndEvent.kt +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/PushAvStreamTransportClusterPushTransportEndEvent.kt @@ -17,15 +17,22 @@ package chip.devicecontroller.cluster.eventstructs import chip.devicecontroller.cluster.* +import java.util.Optional import matter.tlv.ContextSpecificTag import matter.tlv.Tag import matter.tlv.TlvReader import matter.tlv.TlvWriter -class PushAvStreamTransportClusterPushTransportEndEvent(val connectionID: UInt) { +class PushAvStreamTransportClusterPushTransportEndEvent( + val connectionID: UInt, + val containerType: UInt, + val CMAFSessionNumber: Optional, +) { override fun toString(): String = buildString { append("PushAvStreamTransportClusterPushTransportEndEvent {\n") append("\tconnectionID : $connectionID\n") + append("\tcontainerType : $containerType\n") + append("\tCMAFSessionNumber : $CMAFSessionNumber\n") append("}\n") } @@ -33,12 +40,19 @@ class PushAvStreamTransportClusterPushTransportEndEvent(val connectionID: UInt) tlvWriter.apply { startStructure(tlvTag) put(ContextSpecificTag(TAG_CONNECTION_ID), connectionID) + put(ContextSpecificTag(TAG_CONTAINER_TYPE), containerType) + if (CMAFSessionNumber.isPresent) { + val optCMAFSessionNumber = CMAFSessionNumber.get() + put(ContextSpecificTag(TAG_CMAF_SESSION_NUMBER), optCMAFSessionNumber) + } endStructure() } } companion object { private const val TAG_CONNECTION_ID = 0 + private const val TAG_CONTAINER_TYPE = 1 + private const val TAG_CMAF_SESSION_NUMBER = 2 fun fromTlv( tlvTag: Tag, @@ -46,10 +60,21 @@ class PushAvStreamTransportClusterPushTransportEndEvent(val connectionID: UInt) ): PushAvStreamTransportClusterPushTransportEndEvent { tlvReader.enterStructure(tlvTag) val connectionID = tlvReader.getUInt(ContextSpecificTag(TAG_CONNECTION_ID)) + val containerType = tlvReader.getUInt(ContextSpecificTag(TAG_CONTAINER_TYPE)) + val CMAFSessionNumber = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_CMAF_SESSION_NUMBER))) { + Optional.of(tlvReader.getULong(ContextSpecificTag(TAG_CMAF_SESSION_NUMBER))) + } else { + Optional.empty() + } tlvReader.exitContainer() - return PushAvStreamTransportClusterPushTransportEndEvent(connectionID) + return PushAvStreamTransportClusterPushTransportEndEvent( + connectionID, + containerType, + CMAFSessionNumber, + ) } } } diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/files.gni b/src/controller/java/generated/java/chip/devicecontroller/cluster/files.gni index 5bab7ac2384..29b50c77739 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/cluster/files.gni +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/files.gni @@ -160,6 +160,7 @@ structs_sources = [ "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PowerSourceClusterBatFaultChangeType.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PowerSourceClusterWiredFaultChangeType.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PowerTopologyClusterCircuitNodeStruct.kt", + "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterAudioStreamStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterCMAFContainerOptionsStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterContainerOptionsStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterSupportedFormatStruct.kt", @@ -168,6 +169,7 @@ structs_sources = [ "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterTransportOptionsStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterTransportTriggerOptionsStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterTransportZoneOptionsStruct.kt", + "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterVideoStreamStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/RefrigeratorAndTemperatureControlledCabinetModeClusterModeOptionStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/RefrigeratorAndTemperatureControlledCabinetModeClusterModeTagStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/RvcCleanModeClusterModeOptionStruct.kt", @@ -252,6 +254,7 @@ eventstructs_sources = [ "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/BridgedDeviceBasicInformationClusterActiveChangedEvent.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/BridgedDeviceBasicInformationClusterReachableChangedEvent.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/BridgedDeviceBasicInformationClusterStartUpEvent.kt", + "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/ChimeClusterChimeStartedPlayingEvent.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/ClosureControlClusterEngageStateChangedEvent.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/ClosureControlClusterOperationalErrorEvent.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/ClosureControlClusterSecureStateChangedEvent.kt", diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterAudioStreamStruct.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterAudioStreamStruct.kt new file mode 100644 index 00000000000..9702381b0c0 --- /dev/null +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterAudioStreamStruct.kt @@ -0,0 +1,59 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package chip.devicecontroller.cluster.structs + +import chip.devicecontroller.cluster.* +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class PushAvStreamTransportClusterAudioStreamStruct( + val audioStreamName: String, + val audioStreamID: UInt, +) { + override fun toString(): String = buildString { + append("PushAvStreamTransportClusterAudioStreamStruct {\n") + append("\taudioStreamName : $audioStreamName\n") + append("\taudioStreamID : $audioStreamID\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + put(ContextSpecificTag(TAG_AUDIO_STREAM_NAME), audioStreamName) + put(ContextSpecificTag(TAG_AUDIO_STREAM_ID), audioStreamID) + endStructure() + } + } + + companion object { + private const val TAG_AUDIO_STREAM_NAME = 0 + private const val TAG_AUDIO_STREAM_ID = 1 + + fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): PushAvStreamTransportClusterAudioStreamStruct { + tlvReader.enterStructure(tlvTag) + val audioStreamName = tlvReader.getString(ContextSpecificTag(TAG_AUDIO_STREAM_NAME)) + val audioStreamID = tlvReader.getUInt(ContextSpecificTag(TAG_AUDIO_STREAM_ID)) + + tlvReader.exitContainer() + + return PushAvStreamTransportClusterAudioStreamStruct(audioStreamName, audioStreamID) + } + } +} diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterTransportOptionsStruct.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterTransportOptionsStruct.kt index 87070f34846..3da39630a89 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterTransportOptionsStruct.kt +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterTransportOptionsStruct.kt @@ -18,6 +18,7 @@ package chip.devicecontroller.cluster.structs import chip.devicecontroller.cluster.* import java.util.Optional +import matter.tlv.AnonymousTag import matter.tlv.ContextSpecificTag import matter.tlv.Tag import matter.tlv.TlvReader @@ -33,6 +34,8 @@ class PushAvStreamTransportClusterTransportOptionsStruct( val ingestMethod: UInt, val containerOptions: PushAvStreamTransportClusterContainerOptionsStruct, val expiryTime: Optional, + val videoStreams: Optional>, + val audioStreams: Optional>, ) { override fun toString(): String = buildString { append("PushAvStreamTransportClusterTransportOptionsStruct {\n") @@ -45,6 +48,8 @@ class PushAvStreamTransportClusterTransportOptionsStruct( append("\tingestMethod : $ingestMethod\n") append("\tcontainerOptions : $containerOptions\n") append("\texpiryTime : $expiryTime\n") + append("\tvideoStreams : $videoStreams\n") + append("\taudioStreams : $audioStreams\n") append("}\n") } @@ -77,6 +82,22 @@ class PushAvStreamTransportClusterTransportOptionsStruct( val optexpiryTime = expiryTime.get() put(ContextSpecificTag(TAG_EXPIRY_TIME), optexpiryTime) } + if (videoStreams.isPresent) { + val optvideoStreams = videoStreams.get() + startArray(ContextSpecificTag(TAG_VIDEO_STREAMS)) + for (item in optvideoStreams.iterator()) { + item.toTlv(AnonymousTag, this) + } + endArray() + } + if (audioStreams.isPresent) { + val optaudioStreams = audioStreams.get() + startArray(ContextSpecificTag(TAG_AUDIO_STREAMS)) + for (item in optaudioStreams.iterator()) { + item.toTlv(AnonymousTag, this) + } + endArray() + } endStructure() } } @@ -91,6 +112,8 @@ class PushAvStreamTransportClusterTransportOptionsStruct( private const val TAG_INGEST_METHOD = 6 private const val TAG_CONTAINER_OPTIONS = 7 private const val TAG_EXPIRY_TIME = 8 + private const val TAG_VIDEO_STREAMS = 9 + private const val TAG_AUDIO_STREAMS = 10 fun fromTlv( tlvTag: Tag, @@ -139,6 +162,34 @@ class PushAvStreamTransportClusterTransportOptionsStruct( } else { Optional.empty() } + val videoStreams = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_VIDEO_STREAMS))) { + Optional.of( + buildList { + tlvReader.enterArray(ContextSpecificTag(TAG_VIDEO_STREAMS)) + while (!tlvReader.isEndOfContainer()) { + add(PushAvStreamTransportClusterVideoStreamStruct.fromTlv(AnonymousTag, tlvReader)) + } + tlvReader.exitContainer() + } + ) + } else { + Optional.empty() + } + val audioStreams = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_AUDIO_STREAMS))) { + Optional.of( + buildList { + tlvReader.enterArray(ContextSpecificTag(TAG_AUDIO_STREAMS)) + while (!tlvReader.isEndOfContainer()) { + add(PushAvStreamTransportClusterAudioStreamStruct.fromTlv(AnonymousTag, tlvReader)) + } + tlvReader.exitContainer() + } + ) + } else { + Optional.empty() + } tlvReader.exitContainer() @@ -152,6 +203,8 @@ class PushAvStreamTransportClusterTransportOptionsStruct( ingestMethod, containerOptions, expiryTime, + videoStreams, + audioStreams, ) } } diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterVideoStreamStruct.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterVideoStreamStruct.kt new file mode 100644 index 00000000000..221eab44036 --- /dev/null +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/PushAvStreamTransportClusterVideoStreamStruct.kt @@ -0,0 +1,59 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package chip.devicecontroller.cluster.structs + +import chip.devicecontroller.cluster.* +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class PushAvStreamTransportClusterVideoStreamStruct( + val videoStreamName: String, + val videoStreamID: UInt, +) { + override fun toString(): String = buildString { + append("PushAvStreamTransportClusterVideoStreamStruct {\n") + append("\tvideoStreamName : $videoStreamName\n") + append("\tvideoStreamID : $videoStreamID\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + put(ContextSpecificTag(TAG_VIDEO_STREAM_NAME), videoStreamName) + put(ContextSpecificTag(TAG_VIDEO_STREAM_ID), videoStreamID) + endStructure() + } + } + + companion object { + private const val TAG_VIDEO_STREAM_NAME = 0 + private const val TAG_VIDEO_STREAM_ID = 1 + + fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): PushAvStreamTransportClusterVideoStreamStruct { + tlvReader.enterStructure(tlvTag) + val videoStreamName = tlvReader.getString(ContextSpecificTag(TAG_VIDEO_STREAM_NAME)) + val videoStreamID = tlvReader.getUInt(ContextSpecificTag(TAG_VIDEO_STREAM_ID)) + + tlvReader.exitContainer() + + return PushAvStreamTransportClusterVideoStreamStruct(videoStreamName, videoStreamID) + } + } +} diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/WebRTCTransportProviderClusterWebRTCSessionStruct.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/WebRTCTransportProviderClusterWebRTCSessionStruct.kt index 863ff1ff91d..602d7fc5245 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/WebRTCTransportProviderClusterWebRTCSessionStruct.kt +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/WebRTCTransportProviderClusterWebRTCSessionStruct.kt @@ -17,6 +17,8 @@ package chip.devicecontroller.cluster.structs import chip.devicecontroller.cluster.* +import java.util.Optional +import matter.tlv.AnonymousTag import matter.tlv.ContextSpecificTag import matter.tlv.Tag import matter.tlv.TlvReader @@ -30,6 +32,8 @@ class WebRTCTransportProviderClusterWebRTCSessionStruct( val videoStreamID: UInt?, val audioStreamID: UInt?, val metadataEnabled: Boolean, + val videoStreams: Optional>, + val audioStreams: Optional>, val fabricIndex: UInt, ) { override fun toString(): String = buildString { @@ -41,6 +45,8 @@ class WebRTCTransportProviderClusterWebRTCSessionStruct( append("\tvideoStreamID : $videoStreamID\n") append("\taudioStreamID : $audioStreamID\n") append("\tmetadataEnabled : $metadataEnabled\n") + append("\tvideoStreams : $videoStreams\n") + append("\taudioStreams : $audioStreams\n") append("\tfabricIndex : $fabricIndex\n") append("}\n") } @@ -63,6 +69,22 @@ class WebRTCTransportProviderClusterWebRTCSessionStruct( putNull(ContextSpecificTag(TAG_AUDIO_STREAM_ID)) } put(ContextSpecificTag(TAG_METADATA_ENABLED), metadataEnabled) + if (videoStreams.isPresent) { + val optvideoStreams = videoStreams.get() + startArray(ContextSpecificTag(TAG_VIDEO_STREAMS)) + for (item in optvideoStreams.iterator()) { + put(AnonymousTag, item) + } + endArray() + } + if (audioStreams.isPresent) { + val optaudioStreams = audioStreams.get() + startArray(ContextSpecificTag(TAG_AUDIO_STREAMS)) + for (item in optaudioStreams.iterator()) { + put(AnonymousTag, item) + } + endArray() + } put(ContextSpecificTag(TAG_FABRIC_INDEX), fabricIndex) endStructure() } @@ -76,6 +98,8 @@ class WebRTCTransportProviderClusterWebRTCSessionStruct( private const val TAG_VIDEO_STREAM_ID = 4 private const val TAG_AUDIO_STREAM_ID = 5 private const val TAG_METADATA_ENABLED = 6 + private const val TAG_VIDEO_STREAMS = 7 + private const val TAG_AUDIO_STREAMS = 8 private const val TAG_FABRIC_INDEX = 254 fun fromTlv( @@ -102,6 +126,34 @@ class WebRTCTransportProviderClusterWebRTCSessionStruct( null } val metadataEnabled = tlvReader.getBoolean(ContextSpecificTag(TAG_METADATA_ENABLED)) + val videoStreams = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_VIDEO_STREAMS))) { + Optional.of( + buildList { + tlvReader.enterArray(ContextSpecificTag(TAG_VIDEO_STREAMS)) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getUInt(AnonymousTag)) + } + tlvReader.exitContainer() + } + ) + } else { + Optional.empty() + } + val audioStreams = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_AUDIO_STREAMS))) { + Optional.of( + buildList { + tlvReader.enterArray(ContextSpecificTag(TAG_AUDIO_STREAMS)) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getUInt(AnonymousTag)) + } + tlvReader.exitContainer() + } + ) + } else { + Optional.empty() + } val fabricIndex = tlvReader.getUInt(ContextSpecificTag(TAG_FABRIC_INDEX)) tlvReader.exitContainer() @@ -114,6 +166,8 @@ class WebRTCTransportProviderClusterWebRTCSessionStruct( videoStreamID, audioStreamID, metadataEnabled, + videoStreams, + audioStreams, fabricIndex, ) } diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/WebRTCTransportRequestorClusterWebRTCSessionStruct.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/WebRTCTransportRequestorClusterWebRTCSessionStruct.kt index 1a18814d042..5ac20ab4d7e 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/WebRTCTransportRequestorClusterWebRTCSessionStruct.kt +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/WebRTCTransportRequestorClusterWebRTCSessionStruct.kt @@ -17,6 +17,8 @@ package chip.devicecontroller.cluster.structs import chip.devicecontroller.cluster.* +import java.util.Optional +import matter.tlv.AnonymousTag import matter.tlv.ContextSpecificTag import matter.tlv.Tag import matter.tlv.TlvReader @@ -30,6 +32,8 @@ class WebRTCTransportRequestorClusterWebRTCSessionStruct( val videoStreamID: UInt?, val audioStreamID: UInt?, val metadataEnabled: Boolean, + val videoStreams: Optional>, + val audioStreams: Optional>, val fabricIndex: UInt, ) { override fun toString(): String = buildString { @@ -41,6 +45,8 @@ class WebRTCTransportRequestorClusterWebRTCSessionStruct( append("\tvideoStreamID : $videoStreamID\n") append("\taudioStreamID : $audioStreamID\n") append("\tmetadataEnabled : $metadataEnabled\n") + append("\tvideoStreams : $videoStreams\n") + append("\taudioStreams : $audioStreams\n") append("\tfabricIndex : $fabricIndex\n") append("}\n") } @@ -63,6 +69,22 @@ class WebRTCTransportRequestorClusterWebRTCSessionStruct( putNull(ContextSpecificTag(TAG_AUDIO_STREAM_ID)) } put(ContextSpecificTag(TAG_METADATA_ENABLED), metadataEnabled) + if (videoStreams.isPresent) { + val optvideoStreams = videoStreams.get() + startArray(ContextSpecificTag(TAG_VIDEO_STREAMS)) + for (item in optvideoStreams.iterator()) { + put(AnonymousTag, item) + } + endArray() + } + if (audioStreams.isPresent) { + val optaudioStreams = audioStreams.get() + startArray(ContextSpecificTag(TAG_AUDIO_STREAMS)) + for (item in optaudioStreams.iterator()) { + put(AnonymousTag, item) + } + endArray() + } put(ContextSpecificTag(TAG_FABRIC_INDEX), fabricIndex) endStructure() } @@ -76,6 +98,8 @@ class WebRTCTransportRequestorClusterWebRTCSessionStruct( private const val TAG_VIDEO_STREAM_ID = 4 private const val TAG_AUDIO_STREAM_ID = 5 private const val TAG_METADATA_ENABLED = 6 + private const val TAG_VIDEO_STREAMS = 7 + private const val TAG_AUDIO_STREAMS = 8 private const val TAG_FABRIC_INDEX = 254 fun fromTlv( @@ -102,6 +126,34 @@ class WebRTCTransportRequestorClusterWebRTCSessionStruct( null } val metadataEnabled = tlvReader.getBoolean(ContextSpecificTag(TAG_METADATA_ENABLED)) + val videoStreams = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_VIDEO_STREAMS))) { + Optional.of( + buildList { + tlvReader.enterArray(ContextSpecificTag(TAG_VIDEO_STREAMS)) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getUInt(AnonymousTag)) + } + tlvReader.exitContainer() + } + ) + } else { + Optional.empty() + } + val audioStreams = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_AUDIO_STREAMS))) { + Optional.of( + buildList { + tlvReader.enterArray(ContextSpecificTag(TAG_AUDIO_STREAMS)) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getUInt(AnonymousTag)) + } + tlvReader.exitContainer() + } + ) + } else { + Optional.empty() + } val fabricIndex = tlvReader.getUInt(ContextSpecificTag(TAG_FABRIC_INDEX)) tlvReader.exitContainer() @@ -114,6 +166,8 @@ class WebRTCTransportRequestorClusterWebRTCSessionStruct( videoStreamID, audioStreamID, metadataEnabled, + videoStreams, + audioStreams, fabricIndex, ) } diff --git a/src/controller/java/generated/java/matter/controller/cluster/clusters/ChimeCluster.kt b/src/controller/java/generated/java/matter/controller/cluster/clusters/ChimeCluster.kt index 5227405b82c..08407e4ba3a 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/clusters/ChimeCluster.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/clusters/ChimeCluster.kt @@ -40,6 +40,7 @@ import matter.controller.cluster.structs.* import matter.controller.model.AttributePath import matter.controller.model.CommandPath import matter.tlv.AnonymousTag +import matter.tlv.ContextSpecificTag import matter.tlv.TlvReader import matter.tlv.TlvWriter @@ -85,11 +86,14 @@ class ChimeCluster(private val controller: MatterController, private val endpoin object SubscriptionEstablished : AttributeListAttributeSubscriptionState() } - suspend fun playChimeSound(timedInvokeTimeout: Duration? = null) { + suspend fun playChimeSound(chimeID: UByte?, timedInvokeTimeout: Duration? = null) { val commandId: UInt = 0u val tlvWriter = TlvWriter() tlvWriter.startStructure(AnonymousTag) + + val TAG_CHIME_ID_REQ: Int = 0 + chimeID?.let { tlvWriter.put(ContextSpecificTag(TAG_CHIME_ID_REQ), chimeID) } tlvWriter.endStructure() val request: InvokeRequest = diff --git a/src/controller/java/generated/java/matter/controller/cluster/clusters/WebRTCTransportProviderCluster.kt b/src/controller/java/generated/java/matter/controller/cluster/clusters/WebRTCTransportProviderCluster.kt index 7c944cf507c..adf22de60b1 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/clusters/WebRTCTransportProviderCluster.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/clusters/WebRTCTransportProviderCluster.kt @@ -108,6 +108,8 @@ class WebRTCTransportProviderCluster( ICETransportPolicy: String?, metadataEnabled: Boolean?, SFrameConfig: WebRTCTransportProviderClusterSFrameStruct?, + videoStreams: List?, + audioStreams: List?, timedInvokeTimeout: Duration? = null, ): SolicitOfferResponse { val commandId: UInt = 0u @@ -148,6 +150,24 @@ class WebRTCTransportProviderCluster( val TAG_S_FRAME_CONFIG_REQ: Int = 7 SFrameConfig?.let { SFrameConfig.toTlv(ContextSpecificTag(TAG_S_FRAME_CONFIG_REQ), tlvWriter) } + + val TAG_VIDEO_STREAMS_REQ: Int = 8 + videoStreams?.let { + tlvWriter.startArray(ContextSpecificTag(TAG_VIDEO_STREAMS_REQ)) + for (item in videoStreams.iterator()) { + tlvWriter.put(AnonymousTag, item) + } + tlvWriter.endArray() + } + + val TAG_AUDIO_STREAMS_REQ: Int = 9 + audioStreams?.let { + tlvWriter.startArray(ContextSpecificTag(TAG_AUDIO_STREAMS_REQ)) + for (item in audioStreams.iterator()) { + tlvWriter.put(AnonymousTag, item) + } + tlvWriter.endArray() + } tlvWriter.endStructure() val request: InvokeRequest = @@ -255,6 +275,8 @@ class WebRTCTransportProviderCluster( ICETransportPolicy: String?, metadataEnabled: Boolean?, SFrameConfig: WebRTCTransportProviderClusterSFrameStruct?, + videoStreams: List?, + audioStreams: List?, timedInvokeTimeout: Duration? = null, ): ProvideOfferResponse { val commandId: UInt = 2u @@ -303,6 +325,24 @@ class WebRTCTransportProviderCluster( val TAG_S_FRAME_CONFIG_REQ: Int = 9 SFrameConfig?.let { SFrameConfig.toTlv(ContextSpecificTag(TAG_S_FRAME_CONFIG_REQ), tlvWriter) } + + val TAG_VIDEO_STREAMS_REQ: Int = 10 + videoStreams?.let { + tlvWriter.startArray(ContextSpecificTag(TAG_VIDEO_STREAMS_REQ)) + for (item in videoStreams.iterator()) { + tlvWriter.put(AnonymousTag, item) + } + tlvWriter.endArray() + } + + val TAG_AUDIO_STREAMS_REQ: Int = 11 + audioStreams?.let { + tlvWriter.startArray(ContextSpecificTag(TAG_AUDIO_STREAMS_REQ)) + for (item in audioStreams.iterator()) { + tlvWriter.put(AnonymousTag, item) + } + tlvWriter.endArray() + } tlvWriter.endStructure() val request: InvokeRequest = diff --git a/src/controller/java/generated/java/matter/controller/cluster/eventstructs/ChimeClusterChimeStartedPlayingEvent.kt b/src/controller/java/generated/java/matter/controller/cluster/eventstructs/ChimeClusterChimeStartedPlayingEvent.kt new file mode 100644 index 00000000000..6e5b7816e00 --- /dev/null +++ b/src/controller/java/generated/java/matter/controller/cluster/eventstructs/ChimeClusterChimeStartedPlayingEvent.kt @@ -0,0 +1,52 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package matter.controller.cluster.eventstructs + +import matter.controller.cluster.* +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class ChimeClusterChimeStartedPlayingEvent(val chimeID: UByte) { + override fun toString(): String = buildString { + append("ChimeClusterChimeStartedPlayingEvent {\n") + append("\tchimeID : $chimeID\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + put(ContextSpecificTag(TAG_CHIME_ID), chimeID) + endStructure() + } + } + + companion object { + private const val TAG_CHIME_ID = 0 + + fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): ChimeClusterChimeStartedPlayingEvent { + tlvReader.enterStructure(tlvTag) + val chimeID = tlvReader.getUByte(ContextSpecificTag(TAG_CHIME_ID)) + + tlvReader.exitContainer() + + return ChimeClusterChimeStartedPlayingEvent(chimeID) + } + } +} diff --git a/src/controller/java/generated/java/matter/controller/cluster/eventstructs/PushAvStreamTransportClusterPushTransportBeginEvent.kt b/src/controller/java/generated/java/matter/controller/cluster/eventstructs/PushAvStreamTransportClusterPushTransportBeginEvent.kt index 0aeaf246b39..ce8530c6f71 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/eventstructs/PushAvStreamTransportClusterPushTransportBeginEvent.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/eventstructs/PushAvStreamTransportClusterPushTransportBeginEvent.kt @@ -27,12 +27,16 @@ class PushAvStreamTransportClusterPushTransportBeginEvent( val connectionID: UShort, val triggerType: UByte, val activationReason: Optional, + val containerType: UByte, + val CMAFSessionNumber: Optional, ) { override fun toString(): String = buildString { append("PushAvStreamTransportClusterPushTransportBeginEvent {\n") append("\tconnectionID : $connectionID\n") append("\ttriggerType : $triggerType\n") append("\tactivationReason : $activationReason\n") + append("\tcontainerType : $containerType\n") + append("\tCMAFSessionNumber : $CMAFSessionNumber\n") append("}\n") } @@ -45,6 +49,11 @@ class PushAvStreamTransportClusterPushTransportBeginEvent( val optactivationReason = activationReason.get() put(ContextSpecificTag(TAG_ACTIVATION_REASON), optactivationReason) } + put(ContextSpecificTag(TAG_CONTAINER_TYPE), containerType) + if (CMAFSessionNumber.isPresent) { + val optCMAFSessionNumber = CMAFSessionNumber.get() + put(ContextSpecificTag(TAG_CMAF_SESSION_NUMBER), optCMAFSessionNumber) + } endStructure() } } @@ -53,6 +62,8 @@ class PushAvStreamTransportClusterPushTransportBeginEvent( private const val TAG_CONNECTION_ID = 0 private const val TAG_TRIGGER_TYPE = 1 private const val TAG_ACTIVATION_REASON = 2 + private const val TAG_CONTAINER_TYPE = 3 + private const val TAG_CMAF_SESSION_NUMBER = 4 fun fromTlv( tlvTag: Tag, @@ -67,6 +78,13 @@ class PushAvStreamTransportClusterPushTransportBeginEvent( } else { Optional.empty() } + val containerType = tlvReader.getUByte(ContextSpecificTag(TAG_CONTAINER_TYPE)) + val CMAFSessionNumber = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_CMAF_SESSION_NUMBER))) { + Optional.of(tlvReader.getULong(ContextSpecificTag(TAG_CMAF_SESSION_NUMBER))) + } else { + Optional.empty() + } tlvReader.exitContainer() @@ -74,6 +92,8 @@ class PushAvStreamTransportClusterPushTransportBeginEvent( connectionID, triggerType, activationReason, + containerType, + CMAFSessionNumber, ) } } diff --git a/src/controller/java/generated/java/matter/controller/cluster/eventstructs/PushAvStreamTransportClusterPushTransportEndEvent.kt b/src/controller/java/generated/java/matter/controller/cluster/eventstructs/PushAvStreamTransportClusterPushTransportEndEvent.kt index 89f1f9b6db3..7c0239ff2f1 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/eventstructs/PushAvStreamTransportClusterPushTransportEndEvent.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/eventstructs/PushAvStreamTransportClusterPushTransportEndEvent.kt @@ -16,16 +16,23 @@ */ package matter.controller.cluster.eventstructs +import java.util.Optional import matter.controller.cluster.* import matter.tlv.ContextSpecificTag import matter.tlv.Tag import matter.tlv.TlvReader import matter.tlv.TlvWriter -class PushAvStreamTransportClusterPushTransportEndEvent(val connectionID: UShort) { +class PushAvStreamTransportClusterPushTransportEndEvent( + val connectionID: UShort, + val containerType: UByte, + val CMAFSessionNumber: Optional, +) { override fun toString(): String = buildString { append("PushAvStreamTransportClusterPushTransportEndEvent {\n") append("\tconnectionID : $connectionID\n") + append("\tcontainerType : $containerType\n") + append("\tCMAFSessionNumber : $CMAFSessionNumber\n") append("}\n") } @@ -33,12 +40,19 @@ class PushAvStreamTransportClusterPushTransportEndEvent(val connectionID: UShort tlvWriter.apply { startStructure(tlvTag) put(ContextSpecificTag(TAG_CONNECTION_ID), connectionID) + put(ContextSpecificTag(TAG_CONTAINER_TYPE), containerType) + if (CMAFSessionNumber.isPresent) { + val optCMAFSessionNumber = CMAFSessionNumber.get() + put(ContextSpecificTag(TAG_CMAF_SESSION_NUMBER), optCMAFSessionNumber) + } endStructure() } } companion object { private const val TAG_CONNECTION_ID = 0 + private const val TAG_CONTAINER_TYPE = 1 + private const val TAG_CMAF_SESSION_NUMBER = 2 fun fromTlv( tlvTag: Tag, @@ -46,10 +60,21 @@ class PushAvStreamTransportClusterPushTransportEndEvent(val connectionID: UShort ): PushAvStreamTransportClusterPushTransportEndEvent { tlvReader.enterStructure(tlvTag) val connectionID = tlvReader.getUShort(ContextSpecificTag(TAG_CONNECTION_ID)) + val containerType = tlvReader.getUByte(ContextSpecificTag(TAG_CONTAINER_TYPE)) + val CMAFSessionNumber = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_CMAF_SESSION_NUMBER))) { + Optional.of(tlvReader.getULong(ContextSpecificTag(TAG_CMAF_SESSION_NUMBER))) + } else { + Optional.empty() + } tlvReader.exitContainer() - return PushAvStreamTransportClusterPushTransportEndEvent(connectionID) + return PushAvStreamTransportClusterPushTransportEndEvent( + connectionID, + containerType, + CMAFSessionNumber, + ) } } } diff --git a/src/controller/java/generated/java/matter/controller/cluster/files.gni b/src/controller/java/generated/java/matter/controller/cluster/files.gni index 72774cac843..b3da24146e1 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/files.gni +++ b/src/controller/java/generated/java/matter/controller/cluster/files.gni @@ -160,6 +160,7 @@ matter_structs_sources = [ "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/PowerSourceClusterBatFaultChangeType.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/PowerSourceClusterWiredFaultChangeType.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/PowerTopologyClusterCircuitNodeStruct.kt", + "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterAudioStreamStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterCMAFContainerOptionsStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterContainerOptionsStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterSupportedFormatStruct.kt", @@ -168,6 +169,7 @@ matter_structs_sources = [ "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterTransportOptionsStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterTransportTriggerOptionsStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterTransportZoneOptionsStruct.kt", + "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterVideoStreamStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/RefrigeratorAndTemperatureControlledCabinetModeClusterModeOptionStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/RefrigeratorAndTemperatureControlledCabinetModeClusterModeTagStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/RvcCleanModeClusterModeOptionStruct.kt", @@ -252,6 +254,7 @@ matter_eventstructs_sources = [ "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/BridgedDeviceBasicInformationClusterActiveChangedEvent.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/BridgedDeviceBasicInformationClusterReachableChangedEvent.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/BridgedDeviceBasicInformationClusterStartUpEvent.kt", + "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/ChimeClusterChimeStartedPlayingEvent.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/ClosureControlClusterEngageStateChangedEvent.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/ClosureControlClusterOperationalErrorEvent.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/ClosureControlClusterSecureStateChangedEvent.kt", diff --git a/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterAudioStreamStruct.kt b/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterAudioStreamStruct.kt new file mode 100644 index 00000000000..8e6b048844c --- /dev/null +++ b/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterAudioStreamStruct.kt @@ -0,0 +1,59 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package matter.controller.cluster.structs + +import matter.controller.cluster.* +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class PushAvStreamTransportClusterAudioStreamStruct( + val audioStreamName: String, + val audioStreamID: UShort, +) { + override fun toString(): String = buildString { + append("PushAvStreamTransportClusterAudioStreamStruct {\n") + append("\taudioStreamName : $audioStreamName\n") + append("\taudioStreamID : $audioStreamID\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + put(ContextSpecificTag(TAG_AUDIO_STREAM_NAME), audioStreamName) + put(ContextSpecificTag(TAG_AUDIO_STREAM_ID), audioStreamID) + endStructure() + } + } + + companion object { + private const val TAG_AUDIO_STREAM_NAME = 0 + private const val TAG_AUDIO_STREAM_ID = 1 + + fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): PushAvStreamTransportClusterAudioStreamStruct { + tlvReader.enterStructure(tlvTag) + val audioStreamName = tlvReader.getString(ContextSpecificTag(TAG_AUDIO_STREAM_NAME)) + val audioStreamID = tlvReader.getUShort(ContextSpecificTag(TAG_AUDIO_STREAM_ID)) + + tlvReader.exitContainer() + + return PushAvStreamTransportClusterAudioStreamStruct(audioStreamName, audioStreamID) + } + } +} diff --git a/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterTransportOptionsStruct.kt b/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterTransportOptionsStruct.kt index d794ed50627..20b81947bc7 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterTransportOptionsStruct.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterTransportOptionsStruct.kt @@ -18,6 +18,7 @@ package matter.controller.cluster.structs import java.util.Optional import matter.controller.cluster.* +import matter.tlv.AnonymousTag import matter.tlv.ContextSpecificTag import matter.tlv.Tag import matter.tlv.TlvReader @@ -33,6 +34,8 @@ class PushAvStreamTransportClusterTransportOptionsStruct( val ingestMethod: UByte, val containerOptions: PushAvStreamTransportClusterContainerOptionsStruct, val expiryTime: Optional, + val videoStreams: Optional>, + val audioStreams: Optional>, ) { override fun toString(): String = buildString { append("PushAvStreamTransportClusterTransportOptionsStruct {\n") @@ -45,6 +48,8 @@ class PushAvStreamTransportClusterTransportOptionsStruct( append("\tingestMethod : $ingestMethod\n") append("\tcontainerOptions : $containerOptions\n") append("\texpiryTime : $expiryTime\n") + append("\tvideoStreams : $videoStreams\n") + append("\taudioStreams : $audioStreams\n") append("}\n") } @@ -77,6 +82,22 @@ class PushAvStreamTransportClusterTransportOptionsStruct( val optexpiryTime = expiryTime.get() put(ContextSpecificTag(TAG_EXPIRY_TIME), optexpiryTime) } + if (videoStreams.isPresent) { + val optvideoStreams = videoStreams.get() + startArray(ContextSpecificTag(TAG_VIDEO_STREAMS)) + for (item in optvideoStreams.iterator()) { + item.toTlv(AnonymousTag, this) + } + endArray() + } + if (audioStreams.isPresent) { + val optaudioStreams = audioStreams.get() + startArray(ContextSpecificTag(TAG_AUDIO_STREAMS)) + for (item in optaudioStreams.iterator()) { + item.toTlv(AnonymousTag, this) + } + endArray() + } endStructure() } } @@ -91,6 +112,8 @@ class PushAvStreamTransportClusterTransportOptionsStruct( private const val TAG_INGEST_METHOD = 6 private const val TAG_CONTAINER_OPTIONS = 7 private const val TAG_EXPIRY_TIME = 8 + private const val TAG_VIDEO_STREAMS = 9 + private const val TAG_AUDIO_STREAMS = 10 fun fromTlv( tlvTag: Tag, @@ -139,6 +162,34 @@ class PushAvStreamTransportClusterTransportOptionsStruct( } else { Optional.empty() } + val videoStreams = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_VIDEO_STREAMS))) { + Optional.of( + buildList { + tlvReader.enterArray(ContextSpecificTag(TAG_VIDEO_STREAMS)) + while (!tlvReader.isEndOfContainer()) { + add(PushAvStreamTransportClusterVideoStreamStruct.fromTlv(AnonymousTag, tlvReader)) + } + tlvReader.exitContainer() + } + ) + } else { + Optional.empty() + } + val audioStreams = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_AUDIO_STREAMS))) { + Optional.of( + buildList { + tlvReader.enterArray(ContextSpecificTag(TAG_AUDIO_STREAMS)) + while (!tlvReader.isEndOfContainer()) { + add(PushAvStreamTransportClusterAudioStreamStruct.fromTlv(AnonymousTag, tlvReader)) + } + tlvReader.exitContainer() + } + ) + } else { + Optional.empty() + } tlvReader.exitContainer() @@ -152,6 +203,8 @@ class PushAvStreamTransportClusterTransportOptionsStruct( ingestMethod, containerOptions, expiryTime, + videoStreams, + audioStreams, ) } } diff --git a/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterVideoStreamStruct.kt b/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterVideoStreamStruct.kt new file mode 100644 index 00000000000..a93d309693a --- /dev/null +++ b/src/controller/java/generated/java/matter/controller/cluster/structs/PushAvStreamTransportClusterVideoStreamStruct.kt @@ -0,0 +1,59 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package matter.controller.cluster.structs + +import matter.controller.cluster.* +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class PushAvStreamTransportClusterVideoStreamStruct( + val videoStreamName: String, + val videoStreamID: UShort, +) { + override fun toString(): String = buildString { + append("PushAvStreamTransportClusterVideoStreamStruct {\n") + append("\tvideoStreamName : $videoStreamName\n") + append("\tvideoStreamID : $videoStreamID\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + put(ContextSpecificTag(TAG_VIDEO_STREAM_NAME), videoStreamName) + put(ContextSpecificTag(TAG_VIDEO_STREAM_ID), videoStreamID) + endStructure() + } + } + + companion object { + private const val TAG_VIDEO_STREAM_NAME = 0 + private const val TAG_VIDEO_STREAM_ID = 1 + + fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): PushAvStreamTransportClusterVideoStreamStruct { + tlvReader.enterStructure(tlvTag) + val videoStreamName = tlvReader.getString(ContextSpecificTag(TAG_VIDEO_STREAM_NAME)) + val videoStreamID = tlvReader.getUShort(ContextSpecificTag(TAG_VIDEO_STREAM_ID)) + + tlvReader.exitContainer() + + return PushAvStreamTransportClusterVideoStreamStruct(videoStreamName, videoStreamID) + } + } +} diff --git a/src/controller/java/generated/java/matter/controller/cluster/structs/WebRTCTransportProviderClusterWebRTCSessionStruct.kt b/src/controller/java/generated/java/matter/controller/cluster/structs/WebRTCTransportProviderClusterWebRTCSessionStruct.kt index 7c740bd08ac..e83171f5d2e 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/structs/WebRTCTransportProviderClusterWebRTCSessionStruct.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/structs/WebRTCTransportProviderClusterWebRTCSessionStruct.kt @@ -16,7 +16,9 @@ */ package matter.controller.cluster.structs +import java.util.Optional import matter.controller.cluster.* +import matter.tlv.AnonymousTag import matter.tlv.ContextSpecificTag import matter.tlv.Tag import matter.tlv.TlvReader @@ -30,6 +32,8 @@ class WebRTCTransportProviderClusterWebRTCSessionStruct( val videoStreamID: UShort?, val audioStreamID: UShort?, val metadataEnabled: Boolean, + val videoStreams: Optional>, + val audioStreams: Optional>, val fabricIndex: UByte, ) { override fun toString(): String = buildString { @@ -41,6 +45,8 @@ class WebRTCTransportProviderClusterWebRTCSessionStruct( append("\tvideoStreamID : $videoStreamID\n") append("\taudioStreamID : $audioStreamID\n") append("\tmetadataEnabled : $metadataEnabled\n") + append("\tvideoStreams : $videoStreams\n") + append("\taudioStreams : $audioStreams\n") append("\tfabricIndex : $fabricIndex\n") append("}\n") } @@ -63,6 +69,22 @@ class WebRTCTransportProviderClusterWebRTCSessionStruct( putNull(ContextSpecificTag(TAG_AUDIO_STREAM_ID)) } put(ContextSpecificTag(TAG_METADATA_ENABLED), metadataEnabled) + if (videoStreams.isPresent) { + val optvideoStreams = videoStreams.get() + startArray(ContextSpecificTag(TAG_VIDEO_STREAMS)) + for (item in optvideoStreams.iterator()) { + put(AnonymousTag, item) + } + endArray() + } + if (audioStreams.isPresent) { + val optaudioStreams = audioStreams.get() + startArray(ContextSpecificTag(TAG_AUDIO_STREAMS)) + for (item in optaudioStreams.iterator()) { + put(AnonymousTag, item) + } + endArray() + } put(ContextSpecificTag(TAG_FABRIC_INDEX), fabricIndex) endStructure() } @@ -76,6 +98,8 @@ class WebRTCTransportProviderClusterWebRTCSessionStruct( private const val TAG_VIDEO_STREAM_ID = 4 private const val TAG_AUDIO_STREAM_ID = 5 private const val TAG_METADATA_ENABLED = 6 + private const val TAG_VIDEO_STREAMS = 7 + private const val TAG_AUDIO_STREAMS = 8 private const val TAG_FABRIC_INDEX = 254 fun fromTlv( @@ -102,6 +126,34 @@ class WebRTCTransportProviderClusterWebRTCSessionStruct( null } val metadataEnabled = tlvReader.getBoolean(ContextSpecificTag(TAG_METADATA_ENABLED)) + val videoStreams = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_VIDEO_STREAMS))) { + Optional.of( + buildList { + tlvReader.enterArray(ContextSpecificTag(TAG_VIDEO_STREAMS)) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getUShort(AnonymousTag)) + } + tlvReader.exitContainer() + } + ) + } else { + Optional.empty() + } + val audioStreams = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_AUDIO_STREAMS))) { + Optional.of( + buildList { + tlvReader.enterArray(ContextSpecificTag(TAG_AUDIO_STREAMS)) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getUShort(AnonymousTag)) + } + tlvReader.exitContainer() + } + ) + } else { + Optional.empty() + } val fabricIndex = tlvReader.getUByte(ContextSpecificTag(TAG_FABRIC_INDEX)) tlvReader.exitContainer() @@ -114,6 +166,8 @@ class WebRTCTransportProviderClusterWebRTCSessionStruct( videoStreamID, audioStreamID, metadataEnabled, + videoStreams, + audioStreams, fabricIndex, ) } diff --git a/src/controller/java/generated/java/matter/controller/cluster/structs/WebRTCTransportRequestorClusterWebRTCSessionStruct.kt b/src/controller/java/generated/java/matter/controller/cluster/structs/WebRTCTransportRequestorClusterWebRTCSessionStruct.kt index 2749f0b4e1c..359d7fca12b 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/structs/WebRTCTransportRequestorClusterWebRTCSessionStruct.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/structs/WebRTCTransportRequestorClusterWebRTCSessionStruct.kt @@ -16,7 +16,9 @@ */ package matter.controller.cluster.structs +import java.util.Optional import matter.controller.cluster.* +import matter.tlv.AnonymousTag import matter.tlv.ContextSpecificTag import matter.tlv.Tag import matter.tlv.TlvReader @@ -30,6 +32,8 @@ class WebRTCTransportRequestorClusterWebRTCSessionStruct( val videoStreamID: UShort?, val audioStreamID: UShort?, val metadataEnabled: Boolean, + val videoStreams: Optional>, + val audioStreams: Optional>, val fabricIndex: UByte, ) { override fun toString(): String = buildString { @@ -41,6 +45,8 @@ class WebRTCTransportRequestorClusterWebRTCSessionStruct( append("\tvideoStreamID : $videoStreamID\n") append("\taudioStreamID : $audioStreamID\n") append("\tmetadataEnabled : $metadataEnabled\n") + append("\tvideoStreams : $videoStreams\n") + append("\taudioStreams : $audioStreams\n") append("\tfabricIndex : $fabricIndex\n") append("}\n") } @@ -63,6 +69,22 @@ class WebRTCTransportRequestorClusterWebRTCSessionStruct( putNull(ContextSpecificTag(TAG_AUDIO_STREAM_ID)) } put(ContextSpecificTag(TAG_METADATA_ENABLED), metadataEnabled) + if (videoStreams.isPresent) { + val optvideoStreams = videoStreams.get() + startArray(ContextSpecificTag(TAG_VIDEO_STREAMS)) + for (item in optvideoStreams.iterator()) { + put(AnonymousTag, item) + } + endArray() + } + if (audioStreams.isPresent) { + val optaudioStreams = audioStreams.get() + startArray(ContextSpecificTag(TAG_AUDIO_STREAMS)) + for (item in optaudioStreams.iterator()) { + put(AnonymousTag, item) + } + endArray() + } put(ContextSpecificTag(TAG_FABRIC_INDEX), fabricIndex) endStructure() } @@ -76,6 +98,8 @@ class WebRTCTransportRequestorClusterWebRTCSessionStruct( private const val TAG_VIDEO_STREAM_ID = 4 private const val TAG_AUDIO_STREAM_ID = 5 private const val TAG_METADATA_ENABLED = 6 + private const val TAG_VIDEO_STREAMS = 7 + private const val TAG_AUDIO_STREAMS = 8 private const val TAG_FABRIC_INDEX = 254 fun fromTlv( @@ -102,6 +126,34 @@ class WebRTCTransportRequestorClusterWebRTCSessionStruct( null } val metadataEnabled = tlvReader.getBoolean(ContextSpecificTag(TAG_METADATA_ENABLED)) + val videoStreams = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_VIDEO_STREAMS))) { + Optional.of( + buildList { + tlvReader.enterArray(ContextSpecificTag(TAG_VIDEO_STREAMS)) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getUShort(AnonymousTag)) + } + tlvReader.exitContainer() + } + ) + } else { + Optional.empty() + } + val audioStreams = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_AUDIO_STREAMS))) { + Optional.of( + buildList { + tlvReader.enterArray(ContextSpecificTag(TAG_AUDIO_STREAMS)) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getUShort(AnonymousTag)) + } + tlvReader.exitContainer() + } + ) + } else { + Optional.empty() + } val fabricIndex = tlvReader.getUByte(ContextSpecificTag(TAG_FABRIC_INDEX)) tlvReader.exitContainer() @@ -114,6 +166,8 @@ class WebRTCTransportRequestorClusterWebRTCSessionStruct( videoStreamID, audioStreamID, metadataEnabled, + videoStreams, + audioStreams, fabricIndex, ) } diff --git a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp index 936e3fb7d0c..219626d2539 100644 --- a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp +++ b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp @@ -44766,6 +44766,56 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR chip::JniReferences::GetInstance().CreateBoxedObject( newElement_0_metadataEnabledClassName.c_str(), newElement_0_metadataEnabledCtorSignature.c_str(), jninewElement_0_metadataEnabled, newElement_0_metadataEnabled); + jobject newElement_0_videoStreams; + if (!entry_0.videoStreams.HasValue()) + { + chip::JniReferences::GetInstance().CreateOptional(nullptr, newElement_0_videoStreams); + } + else + { + jobject newElement_0_videoStreamsInsideOptional; + chip::JniReferences::GetInstance().CreateArrayList(newElement_0_videoStreamsInsideOptional); + + auto iter_newElement_0_videoStreamsInsideOptional_3 = entry_0.videoStreams.Value().begin(); + while (iter_newElement_0_videoStreamsInsideOptional_3.Next()) + { + auto & entry_3 = iter_newElement_0_videoStreamsInsideOptional_3.GetValue(); + jobject newElement_3; + std::string newElement_3ClassName = "java/lang/Integer"; + std::string newElement_3CtorSignature = "(I)V"; + jint jninewElement_3 = static_cast(entry_3); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_3ClassName.c_str(), newElement_3CtorSignature.c_str(), jninewElement_3, newElement_3); + chip::JniReferences::GetInstance().AddToList(newElement_0_videoStreamsInsideOptional, newElement_3); + } + chip::JniReferences::GetInstance().CreateOptional(newElement_0_videoStreamsInsideOptional, + newElement_0_videoStreams); + } + jobject newElement_0_audioStreams; + if (!entry_0.audioStreams.HasValue()) + { + chip::JniReferences::GetInstance().CreateOptional(nullptr, newElement_0_audioStreams); + } + else + { + jobject newElement_0_audioStreamsInsideOptional; + chip::JniReferences::GetInstance().CreateArrayList(newElement_0_audioStreamsInsideOptional); + + auto iter_newElement_0_audioStreamsInsideOptional_3 = entry_0.audioStreams.Value().begin(); + while (iter_newElement_0_audioStreamsInsideOptional_3.Next()) + { + auto & entry_3 = iter_newElement_0_audioStreamsInsideOptional_3.GetValue(); + jobject newElement_3; + std::string newElement_3ClassName = "java/lang/Integer"; + std::string newElement_3CtorSignature = "(I)V"; + jint jninewElement_3 = static_cast(entry_3); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_3ClassName.c_str(), newElement_3CtorSignature.c_str(), jninewElement_3, newElement_3); + chip::JniReferences::GetInstance().AddToList(newElement_0_audioStreamsInsideOptional, newElement_3); + } + chip::JniReferences::GetInstance().CreateOptional(newElement_0_audioStreamsInsideOptional, + newElement_0_audioStreams); + } jobject newElement_0_fabricIndex; std::string newElement_0_fabricIndexClassName = "java/lang/Integer"; std::string newElement_0_fabricIndexCtorSignature = "(I)V"; @@ -44789,7 +44839,7 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR err = chip::JniReferences::GetInstance().FindMethod( env, webRTCSessionStructStructClass_1, "", "(Ljava/lang/Integer;Ljava/lang/Long;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/" - "Integer;Ljava/lang/Boolean;Ljava/lang/Integer;)V", + "Integer;Ljava/lang/Boolean;Ljava/util/Optional;Ljava/util/Optional;Ljava/lang/Integer;)V", &webRTCSessionStructStructCtor_1); if (err != CHIP_NO_ERROR || webRTCSessionStructStructCtor_1 == nullptr) { @@ -44798,10 +44848,11 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR return nullptr; } - newElement_0 = env->NewObject(webRTCSessionStructStructClass_1, webRTCSessionStructStructCtor_1, - newElement_0_id, newElement_0_peerNodeID, newElement_0_peerEndpointID, - newElement_0_streamUsage, newElement_0_videoStreamID, newElement_0_audioStreamID, - newElement_0_metadataEnabled, newElement_0_fabricIndex); + newElement_0 = + env->NewObject(webRTCSessionStructStructClass_1, webRTCSessionStructStructCtor_1, newElement_0_id, + newElement_0_peerNodeID, newElement_0_peerEndpointID, newElement_0_streamUsage, + newElement_0_videoStreamID, newElement_0_audioStreamID, newElement_0_metadataEnabled, + newElement_0_videoStreams, newElement_0_audioStreams, newElement_0_fabricIndex); } chip::JniReferences::GetInstance().AddToList(value, newElement_0); } @@ -45002,6 +45053,56 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR chip::JniReferences::GetInstance().CreateBoxedObject( newElement_0_metadataEnabledClassName.c_str(), newElement_0_metadataEnabledCtorSignature.c_str(), jninewElement_0_metadataEnabled, newElement_0_metadataEnabled); + jobject newElement_0_videoStreams; + if (!entry_0.videoStreams.HasValue()) + { + chip::JniReferences::GetInstance().CreateOptional(nullptr, newElement_0_videoStreams); + } + else + { + jobject newElement_0_videoStreamsInsideOptional; + chip::JniReferences::GetInstance().CreateArrayList(newElement_0_videoStreamsInsideOptional); + + auto iter_newElement_0_videoStreamsInsideOptional_3 = entry_0.videoStreams.Value().begin(); + while (iter_newElement_0_videoStreamsInsideOptional_3.Next()) + { + auto & entry_3 = iter_newElement_0_videoStreamsInsideOptional_3.GetValue(); + jobject newElement_3; + std::string newElement_3ClassName = "java/lang/Integer"; + std::string newElement_3CtorSignature = "(I)V"; + jint jninewElement_3 = static_cast(entry_3); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_3ClassName.c_str(), newElement_3CtorSignature.c_str(), jninewElement_3, newElement_3); + chip::JniReferences::GetInstance().AddToList(newElement_0_videoStreamsInsideOptional, newElement_3); + } + chip::JniReferences::GetInstance().CreateOptional(newElement_0_videoStreamsInsideOptional, + newElement_0_videoStreams); + } + jobject newElement_0_audioStreams; + if (!entry_0.audioStreams.HasValue()) + { + chip::JniReferences::GetInstance().CreateOptional(nullptr, newElement_0_audioStreams); + } + else + { + jobject newElement_0_audioStreamsInsideOptional; + chip::JniReferences::GetInstance().CreateArrayList(newElement_0_audioStreamsInsideOptional); + + auto iter_newElement_0_audioStreamsInsideOptional_3 = entry_0.audioStreams.Value().begin(); + while (iter_newElement_0_audioStreamsInsideOptional_3.Next()) + { + auto & entry_3 = iter_newElement_0_audioStreamsInsideOptional_3.GetValue(); + jobject newElement_3; + std::string newElement_3ClassName = "java/lang/Integer"; + std::string newElement_3CtorSignature = "(I)V"; + jint jninewElement_3 = static_cast(entry_3); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_3ClassName.c_str(), newElement_3CtorSignature.c_str(), jninewElement_3, newElement_3); + chip::JniReferences::GetInstance().AddToList(newElement_0_audioStreamsInsideOptional, newElement_3); + } + chip::JniReferences::GetInstance().CreateOptional(newElement_0_audioStreamsInsideOptional, + newElement_0_audioStreams); + } jobject newElement_0_fabricIndex; std::string newElement_0_fabricIndexClassName = "java/lang/Integer"; std::string newElement_0_fabricIndexCtorSignature = "(I)V"; @@ -45025,7 +45126,7 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR err = chip::JniReferences::GetInstance().FindMethod( env, webRTCSessionStructStructClass_1, "", "(Ljava/lang/Integer;Ljava/lang/Long;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/" - "Integer;Ljava/lang/Boolean;Ljava/lang/Integer;)V", + "Integer;Ljava/lang/Boolean;Ljava/util/Optional;Ljava/util/Optional;Ljava/lang/Integer;)V", &webRTCSessionStructStructCtor_1); if (err != CHIP_NO_ERROR || webRTCSessionStructStructCtor_1 == nullptr) { @@ -45034,10 +45135,11 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR return nullptr; } - newElement_0 = env->NewObject(webRTCSessionStructStructClass_1, webRTCSessionStructStructCtor_1, - newElement_0_id, newElement_0_peerNodeID, newElement_0_peerEndpointID, - newElement_0_streamUsage, newElement_0_videoStreamID, newElement_0_audioStreamID, - newElement_0_metadataEnabled, newElement_0_fabricIndex); + newElement_0 = + env->NewObject(webRTCSessionStructStructClass_1, webRTCSessionStructStructCtor_1, newElement_0_id, + newElement_0_peerNodeID, newElement_0_peerEndpointID, newElement_0_streamUsage, + newElement_0_videoStreamID, newElement_0_audioStreamID, newElement_0_metadataEnabled, + newElement_0_videoStreams, newElement_0_audioStreams, newElement_0_fabricIndex); } chip::JniReferences::GetInstance().AddToList(value, newElement_0); } @@ -45992,6 +46094,134 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR newElement_0_transportOptionsInsideOptional_expiryTimeInsideOptional, newElement_0_transportOptionsInsideOptional_expiryTime); } + jobject newElement_0_transportOptionsInsideOptional_videoStreams; + if (!entry_0.transportOptions.Value().videoStreams.HasValue()) + { + chip::JniReferences::GetInstance().CreateOptional(nullptr, + newElement_0_transportOptionsInsideOptional_videoStreams); + } + else + { + jobject newElement_0_transportOptionsInsideOptional_videoStreamsInsideOptional; + chip::JniReferences::GetInstance().CreateArrayList( + newElement_0_transportOptionsInsideOptional_videoStreamsInsideOptional); + + auto iter_newElement_0_transportOptionsInsideOptional_videoStreamsInsideOptional_5 = + entry_0.transportOptions.Value().videoStreams.Value().begin(); + while (iter_newElement_0_transportOptionsInsideOptional_videoStreamsInsideOptional_5.Next()) + { + auto & entry_5 = + iter_newElement_0_transportOptionsInsideOptional_videoStreamsInsideOptional_5.GetValue(); + jobject newElement_5; + jobject newElement_5_videoStreamName; + LogErrorOnFailure(chip::JniReferences::GetInstance().CharToStringUTF(entry_5.videoStreamName, + newElement_5_videoStreamName)); + jobject newElement_5_videoStreamID; + std::string newElement_5_videoStreamIDClassName = "java/lang/Integer"; + std::string newElement_5_videoStreamIDCtorSignature = "(I)V"; + jint jninewElement_5_videoStreamID = static_cast(entry_5.videoStreamID); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_5_videoStreamIDClassName.c_str(), newElement_5_videoStreamIDCtorSignature.c_str(), + jninewElement_5_videoStreamID, newElement_5_videoStreamID); + + { + jclass videoStreamStructStructClass_6; + err = chip::JniReferences::GetInstance().GetLocalClassRef( + env, "chip/devicecontroller/ChipStructs$PushAvStreamTransportClusterVideoStreamStruct", + videoStreamStructStructClass_6); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, + "Could not find class ChipStructs$PushAvStreamTransportClusterVideoStreamStruct"); + return nullptr; + } + + jmethodID videoStreamStructStructCtor_6; + err = chip::JniReferences::GetInstance().FindMethod(env, videoStreamStructStructClass_6, "", + "(Ljava/lang/String;Ljava/lang/Integer;)V", + &videoStreamStructStructCtor_6); + if (err != CHIP_NO_ERROR || videoStreamStructStructCtor_6 == nullptr) + { + ChipLogError( + Zcl, + "Could not find ChipStructs$PushAvStreamTransportClusterVideoStreamStruct constructor"); + return nullptr; + } + + newElement_5 = env->NewObject(videoStreamStructStructClass_6, videoStreamStructStructCtor_6, + newElement_5_videoStreamName, newElement_5_videoStreamID); + } + chip::JniReferences::GetInstance().AddToList( + newElement_0_transportOptionsInsideOptional_videoStreamsInsideOptional, newElement_5); + } + chip::JniReferences::GetInstance().CreateOptional( + newElement_0_transportOptionsInsideOptional_videoStreamsInsideOptional, + newElement_0_transportOptionsInsideOptional_videoStreams); + } + jobject newElement_0_transportOptionsInsideOptional_audioStreams; + if (!entry_0.transportOptions.Value().audioStreams.HasValue()) + { + chip::JniReferences::GetInstance().CreateOptional(nullptr, + newElement_0_transportOptionsInsideOptional_audioStreams); + } + else + { + jobject newElement_0_transportOptionsInsideOptional_audioStreamsInsideOptional; + chip::JniReferences::GetInstance().CreateArrayList( + newElement_0_transportOptionsInsideOptional_audioStreamsInsideOptional); + + auto iter_newElement_0_transportOptionsInsideOptional_audioStreamsInsideOptional_5 = + entry_0.transportOptions.Value().audioStreams.Value().begin(); + while (iter_newElement_0_transportOptionsInsideOptional_audioStreamsInsideOptional_5.Next()) + { + auto & entry_5 = + iter_newElement_0_transportOptionsInsideOptional_audioStreamsInsideOptional_5.GetValue(); + jobject newElement_5; + jobject newElement_5_audioStreamName; + LogErrorOnFailure(chip::JniReferences::GetInstance().CharToStringUTF(entry_5.audioStreamName, + newElement_5_audioStreamName)); + jobject newElement_5_audioStreamID; + std::string newElement_5_audioStreamIDClassName = "java/lang/Integer"; + std::string newElement_5_audioStreamIDCtorSignature = "(I)V"; + jint jninewElement_5_audioStreamID = static_cast(entry_5.audioStreamID); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_5_audioStreamIDClassName.c_str(), newElement_5_audioStreamIDCtorSignature.c_str(), + jninewElement_5_audioStreamID, newElement_5_audioStreamID); + + { + jclass audioStreamStructStructClass_6; + err = chip::JniReferences::GetInstance().GetLocalClassRef( + env, "chip/devicecontroller/ChipStructs$PushAvStreamTransportClusterAudioStreamStruct", + audioStreamStructStructClass_6); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, + "Could not find class ChipStructs$PushAvStreamTransportClusterAudioStreamStruct"); + return nullptr; + } + + jmethodID audioStreamStructStructCtor_6; + err = chip::JniReferences::GetInstance().FindMethod(env, audioStreamStructStructClass_6, "", + "(Ljava/lang/String;Ljava/lang/Integer;)V", + &audioStreamStructStructCtor_6); + if (err != CHIP_NO_ERROR || audioStreamStructStructCtor_6 == nullptr) + { + ChipLogError( + Zcl, + "Could not find ChipStructs$PushAvStreamTransportClusterAudioStreamStruct constructor"); + return nullptr; + } + + newElement_5 = env->NewObject(audioStreamStructStructClass_6, audioStreamStructStructCtor_6, + newElement_5_audioStreamName, newElement_5_audioStreamID); + } + chip::JniReferences::GetInstance().AddToList( + newElement_0_transportOptionsInsideOptional_audioStreamsInsideOptional, newElement_5); + } + chip::JniReferences::GetInstance().CreateOptional( + newElement_0_transportOptionsInsideOptional_audioStreamsInsideOptional, + newElement_0_transportOptionsInsideOptional_audioStreams); + } { jclass transportOptionsStructStructClass_3; @@ -46012,7 +46242,7 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR "String;Lchip/devicecontroller/" "ChipStructs$PushAvStreamTransportClusterTransportTriggerOptionsStruct;Ljava/lang/Integer;Lchip/" "devicecontroller/ChipStructs$PushAvStreamTransportClusterContainerOptionsStruct;Ljava/util/" - "Optional;)V", + "Optional;Ljava/util/Optional;Ljava/util/Optional;)V", &transportOptionsStructStructCtor_3); if (err != CHIP_NO_ERROR || transportOptionsStructStructCtor_3 == nullptr) { @@ -46031,7 +46261,9 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR newElement_0_transportOptionsInsideOptional_triggerOptions, newElement_0_transportOptionsInsideOptional_ingestMethod, newElement_0_transportOptionsInsideOptional_containerOptions, - newElement_0_transportOptionsInsideOptional_expiryTime); + newElement_0_transportOptionsInsideOptional_expiryTime, + newElement_0_transportOptionsInsideOptional_videoStreams, + newElement_0_transportOptionsInsideOptional_audioStreams); } chip::JniReferences::GetInstance().CreateOptional(newElement_0_transportOptionsInsideOptional, newElement_0_transportOptions); diff --git a/src/controller/java/zap-generated/CHIPEventTLVValueDecoder.cpp b/src/controller/java/zap-generated/CHIPEventTLVValueDecoder.cpp index f789eafdcc3..ca3a3fdf422 100644 --- a/src/controller/java/zap-generated/CHIPEventTLVValueDecoder.cpp +++ b/src/controller/java/zap-generated/CHIPEventTLVValueDecoder.cpp @@ -9380,6 +9380,32 @@ jobject DecodeEventValue(const app::ConcreteEventPath & aPath, TLV::TLVReader & chip::JniReferences::GetInstance().CreateOptional(value_activationReasonInsideOptional, value_activationReason); } + jobject value_containerType; + std::string value_containerTypeClassName = "java/lang/Integer"; + std::string value_containerTypeCtorSignature = "(I)V"; + jint jnivalue_containerType = static_cast(cppValue.containerType); + chip::JniReferences::GetInstance().CreateBoxedObject(value_containerTypeClassName.c_str(), + value_containerTypeCtorSignature.c_str(), + jnivalue_containerType, value_containerType); + + jobject value_CMAFSessionNumber; + if (!cppValue.CMAFSessionNumber.HasValue()) + { + chip::JniReferences::GetInstance().CreateOptional(nullptr, value_CMAFSessionNumber); + } + else + { + jobject value_CMAFSessionNumberInsideOptional; + std::string value_CMAFSessionNumberInsideOptionalClassName = "java/lang/Long"; + std::string value_CMAFSessionNumberInsideOptionalCtorSignature = "(J)V"; + jlong jnivalue_CMAFSessionNumberInsideOptional = static_cast(cppValue.CMAFSessionNumber.Value()); + chip::JniReferences::GetInstance().CreateBoxedObject( + value_CMAFSessionNumberInsideOptionalClassName.c_str(), + value_CMAFSessionNumberInsideOptionalCtorSignature.c_str(), jnivalue_CMAFSessionNumberInsideOptional, + value_CMAFSessionNumberInsideOptional); + chip::JniReferences::GetInstance().CreateOptional(value_CMAFSessionNumberInsideOptional, value_CMAFSessionNumber); + } + jclass pushTransportBeginStructClass; err = chip::JniReferences::GetInstance().GetLocalClassRef( env, "chip/devicecontroller/ChipEventStructs$PushAvStreamTransportClusterPushTransportBeginEvent", @@ -9391,9 +9417,10 @@ jobject DecodeEventValue(const app::ConcreteEventPath & aPath, TLV::TLVReader & } jmethodID pushTransportBeginStructCtor; - err = chip::JniReferences::GetInstance().FindMethod(env, pushTransportBeginStructClass, "", - "(Ljava/lang/Integer;Ljava/lang/Integer;Ljava/util/Optional;)V", - &pushTransportBeginStructCtor); + err = chip::JniReferences::GetInstance().FindMethod( + env, pushTransportBeginStructClass, "", + "(Ljava/lang/Integer;Ljava/lang/Integer;Ljava/util/Optional;Ljava/lang/Integer;Ljava/util/Optional;)V", + &pushTransportBeginStructCtor); if (err != CHIP_NO_ERROR || pushTransportBeginStructCtor == nullptr) { ChipLogError(Zcl, @@ -9402,7 +9429,7 @@ jobject DecodeEventValue(const app::ConcreteEventPath & aPath, TLV::TLVReader & } jobject value = env->NewObject(pushTransportBeginStructClass, pushTransportBeginStructCtor, value_connectionID, - value_triggerType, value_activationReason); + value_triggerType, value_activationReason, value_containerType, value_CMAFSessionNumber); return value; } @@ -9421,6 +9448,32 @@ jobject DecodeEventValue(const app::ConcreteEventPath & aPath, TLV::TLVReader & value_connectionIDCtorSignature.c_str(), jnivalue_connectionID, value_connectionID); + jobject value_containerType; + std::string value_containerTypeClassName = "java/lang/Integer"; + std::string value_containerTypeCtorSignature = "(I)V"; + jint jnivalue_containerType = static_cast(cppValue.containerType); + chip::JniReferences::GetInstance().CreateBoxedObject(value_containerTypeClassName.c_str(), + value_containerTypeCtorSignature.c_str(), + jnivalue_containerType, value_containerType); + + jobject value_CMAFSessionNumber; + if (!cppValue.CMAFSessionNumber.HasValue()) + { + chip::JniReferences::GetInstance().CreateOptional(nullptr, value_CMAFSessionNumber); + } + else + { + jobject value_CMAFSessionNumberInsideOptional; + std::string value_CMAFSessionNumberInsideOptionalClassName = "java/lang/Long"; + std::string value_CMAFSessionNumberInsideOptionalCtorSignature = "(J)V"; + jlong jnivalue_CMAFSessionNumberInsideOptional = static_cast(cppValue.CMAFSessionNumber.Value()); + chip::JniReferences::GetInstance().CreateBoxedObject( + value_CMAFSessionNumberInsideOptionalClassName.c_str(), + value_CMAFSessionNumberInsideOptionalCtorSignature.c_str(), jnivalue_CMAFSessionNumberInsideOptional, + value_CMAFSessionNumberInsideOptional); + chip::JniReferences::GetInstance().CreateOptional(value_CMAFSessionNumberInsideOptional, value_CMAFSessionNumber); + } + jclass pushTransportEndStructClass; err = chip::JniReferences::GetInstance().GetLocalClassRef( env, "chip/devicecontroller/ChipEventStructs$PushAvStreamTransportClusterPushTransportEndEvent", @@ -9433,14 +9486,16 @@ jobject DecodeEventValue(const app::ConcreteEventPath & aPath, TLV::TLVReader & jmethodID pushTransportEndStructCtor; err = chip::JniReferences::GetInstance().FindMethod(env, pushTransportEndStructClass, "", - "(Ljava/lang/Integer;)V", &pushTransportEndStructCtor); + "(Ljava/lang/Integer;Ljava/lang/Integer;Ljava/util/Optional;)V", + &pushTransportEndStructCtor); if (err != CHIP_NO_ERROR || pushTransportEndStructCtor == nullptr) { ChipLogError(Zcl, "Could not find ChipEventStructs$PushAvStreamTransportClusterPushTransportEndEvent constructor"); return nullptr; } - jobject value = env->NewObject(pushTransportEndStructClass, pushTransportEndStructCtor, value_connectionID); + jobject value = env->NewObject(pushTransportEndStructClass, pushTransportEndStructCtor, value_connectionID, + value_containerType, value_CMAFSessionNumber); return value; } @@ -9454,6 +9509,42 @@ jobject DecodeEventValue(const app::ConcreteEventPath & aPath, TLV::TLVReader & using namespace app::Clusters::Chime; switch (aPath.mEventId) { + case Events::ChimeStartedPlaying::Id: { + Events::ChimeStartedPlaying::DecodableType cppValue; + *aError = app::DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) + { + return nullptr; + } + jobject value_chimeID; + std::string value_chimeIDClassName = "java/lang/Integer"; + std::string value_chimeIDCtorSignature = "(I)V"; + jint jnivalue_chimeID = static_cast(cppValue.chimeID); + chip::JniReferences::GetInstance().CreateBoxedObject( + value_chimeIDClassName.c_str(), value_chimeIDCtorSignature.c_str(), jnivalue_chimeID, value_chimeID); + + jclass chimeStartedPlayingStructClass; + err = chip::JniReferences::GetInstance().GetLocalClassRef( + env, "chip/devicecontroller/ChipEventStructs$ChimeClusterChimeStartedPlayingEvent", chimeStartedPlayingStructClass); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Could not find class ChipEventStructs$ChimeClusterChimeStartedPlayingEvent"); + return nullptr; + } + + jmethodID chimeStartedPlayingStructCtor; + err = chip::JniReferences::GetInstance().FindMethod(env, chimeStartedPlayingStructClass, "", + "(Ljava/lang/Integer;)V", &chimeStartedPlayingStructCtor); + if (err != CHIP_NO_ERROR || chimeStartedPlayingStructCtor == nullptr) + { + ChipLogError(Zcl, "Could not find ChipEventStructs$ChimeClusterChimeStartedPlayingEvent constructor"); + return nullptr; + } + + jobject value = env->NewObject(chimeStartedPlayingStructClass, chimeStartedPlayingStructCtor, value_chimeID); + + return value; + } default: *aError = CHIP_ERROR_IM_MALFORMED_EVENT_PATH_IB; break; diff --git a/src/controller/python/matter/clusters/CHIPClusters.py b/src/controller/python/matter/clusters/CHIPClusters.py index d186d6076f5..b49b01f8ab4 100644 --- a/src/controller/python/matter/clusters/CHIPClusters.py +++ b/src/controller/python/matter/clusters/CHIPClusters.py @@ -13536,6 +13536,8 @@ class ChipClusters: "ICETransportPolicy": "str", "metadataEnabled": "bool", "SFrameConfig": "SFrameStruct", + "videoStreams": "int", + "audioStreams": "int", }, }, 0x00000002: { @@ -13552,6 +13554,8 @@ class ChipClusters: "ICETransportPolicy": "str", "metadataEnabled": "bool", "SFrameConfig": "SFrameStruct", + "videoStreams": "int", + "audioStreams": "int", }, }, 0x00000004: { @@ -13801,6 +13805,7 @@ class ChipClusters: "commandId": 0x00000000, "commandName": "PlayChimeSound", "args": { + "chimeID": "int", }, }, }, diff --git a/src/controller/python/matter/clusters/Objects.py b/src/controller/python/matter/clusters/Objects.py index a75479387a2..31a1cea09a1 100644 --- a/src/controller/python/matter/clusters/Objects.py +++ b/src/controller/python/matter/clusters/Objects.py @@ -713,6 +713,8 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="videoStreamID", Tag=4, Type=typing.Union[Nullable, uint]), ClusterObjectFieldDescriptor(Label="audioStreamID", Tag=5, Type=typing.Union[Nullable, uint]), ClusterObjectFieldDescriptor(Label="metadataEnabled", Tag=6, Type=bool), + ClusterObjectFieldDescriptor(Label="videoStreams", Tag=7, Type=typing.Optional[typing.List[uint]]), + ClusterObjectFieldDescriptor(Label="audioStreams", Tag=8, Type=typing.Optional[typing.List[uint]]), ClusterObjectFieldDescriptor(Label="fabricIndex", Tag=254, Type=uint), ]) @@ -723,6 +725,8 @@ def descriptor(cls) -> ClusterObjectDescriptor: videoStreamID: 'typing.Union[Nullable, uint]' = NullValue audioStreamID: 'typing.Union[Nullable, uint]' = NullValue metadataEnabled: 'bool' = False + videoStreams: 'typing.Optional[typing.List[uint]]' = None + audioStreams: 'typing.Optional[typing.List[uint]]' = None fabricIndex: 'uint' = 0 @@ -47516,11 +47520,12 @@ class AudioCodecEnum(MatterIntEnum): class ImageCodecEnum(MatterIntEnum): kJpeg = 0x00 + kHeic = 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 an unknown # enum value. This specific value should never be transmitted. - kUnknownEnumValue = 1 + kUnknownEnumValue = 2 class TriStateAutoEnum(MatterIntEnum): kOff = 0x00 @@ -49298,6 +49303,8 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="ICETransportPolicy", Tag=5, Type=typing.Optional[str]), ClusterObjectFieldDescriptor(Label="metadataEnabled", Tag=6, Type=typing.Optional[bool]), ClusterObjectFieldDescriptor(Label="SFrameConfig", Tag=7, Type=typing.Optional[WebRTCTransportProvider.Structs.SFrameStruct]), + ClusterObjectFieldDescriptor(Label="videoStreams", Tag=8, Type=typing.Optional[typing.List[uint]]), + ClusterObjectFieldDescriptor(Label="audioStreams", Tag=9, Type=typing.Optional[typing.List[uint]]), ]) streamUsage: Globals.Enums.StreamUsageEnum = 0 @@ -49308,6 +49315,8 @@ def descriptor(cls) -> ClusterObjectDescriptor: ICETransportPolicy: typing.Optional[str] = None metadataEnabled: typing.Optional[bool] = None SFrameConfig: typing.Optional[WebRTCTransportProvider.Structs.SFrameStruct] = None + videoStreams: typing.Optional[typing.List[uint]] = None + audioStreams: typing.Optional[typing.List[uint]] = None @dataclass class SolicitOfferResponse(ClusterCommand): @@ -49352,6 +49361,8 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="ICETransportPolicy", Tag=7, Type=typing.Optional[str]), ClusterObjectFieldDescriptor(Label="metadataEnabled", Tag=8, Type=typing.Optional[bool]), ClusterObjectFieldDescriptor(Label="SFrameConfig", Tag=9, Type=typing.Optional[WebRTCTransportProvider.Structs.SFrameStruct]), + ClusterObjectFieldDescriptor(Label="videoStreams", Tag=10, Type=typing.Optional[typing.List[uint]]), + ClusterObjectFieldDescriptor(Label="audioStreams", Tag=11, Type=typing.Optional[typing.List[uint]]), ]) webRTCSessionID: typing.Union[Nullable, uint] = NullValue @@ -49364,6 +49375,8 @@ def descriptor(cls) -> ClusterObjectDescriptor: ICETransportPolicy: typing.Optional[str] = None metadataEnabled: typing.Optional[bool] = None SFrameConfig: typing.Optional[WebRTCTransportProvider.Structs.SFrameStruct] = None + videoStreams: typing.Optional[typing.List[uint]] = None + audioStreams: typing.Optional[typing.List[uint]] = None @dataclass class ProvideOfferResponse(ClusterCommand): @@ -49798,6 +49811,8 @@ class StatusCodeEnum(MatterIntEnum): kInvalidOptions = 0x09 kInvalidStreamUsage = 0x0A kInvalidTime = 0x0B + kInvalidPreRollLength = 0x0C + kDuplicateStreamValues = 0x0D # 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 an unknown @@ -49827,11 +49842,12 @@ class TriggerActivationReasonEnum(MatterIntEnum): kUserInitiated = 0x00 kAutomation = 0x01 kEmergency = 0x02 + kDoorbellPressed = 0x03 # 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 an unknown # enum value. This specific value should never be transmitted. - kUnknownEnumValue = 3 + kUnknownEnumValue = 4 class Bitmaps: class Feature(IntFlag): @@ -49869,6 +49885,32 @@ def descriptor(cls) -> ClusterObjectDescriptor: zone: 'typing.Union[Nullable, uint]' = NullValue sensitivity: 'typing.Optional[uint]' = None + @dataclass + class AudioStreamStruct(ClusterObject): + @ChipUtility.classproperty + def descriptor(cls) -> ClusterObjectDescriptor: + return ClusterObjectDescriptor( + Fields=[ + ClusterObjectFieldDescriptor(Label="audioStreamName", Tag=0, Type=str), + ClusterObjectFieldDescriptor(Label="audioStreamID", Tag=1, Type=uint), + ]) + + audioStreamName: 'str' = "" + audioStreamID: 'uint' = 0 + + @dataclass + class VideoStreamStruct(ClusterObject): + @ChipUtility.classproperty + def descriptor(cls) -> ClusterObjectDescriptor: + return ClusterObjectDescriptor( + Fields=[ + ClusterObjectFieldDescriptor(Label="videoStreamName", Tag=0, Type=str), + ClusterObjectFieldDescriptor(Label="videoStreamID", Tag=1, Type=uint), + ]) + + videoStreamName: 'str' = "" + videoStreamID: 'uint' = 0 + @dataclass class TransportTriggerOptionsStruct(ClusterObject): @ChipUtility.classproperty @@ -49941,6 +49983,8 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="ingestMethod", Tag=6, Type=PushAvStreamTransport.Enums.IngestMethodsEnum), ClusterObjectFieldDescriptor(Label="containerOptions", Tag=7, Type=PushAvStreamTransport.Structs.ContainerOptionsStruct), ClusterObjectFieldDescriptor(Label="expiryTime", Tag=8, Type=typing.Optional[uint]), + ClusterObjectFieldDescriptor(Label="videoStreams", Tag=9, Type=typing.Optional[typing.List[PushAvStreamTransport.Structs.VideoStreamStruct]]), + ClusterObjectFieldDescriptor(Label="audioStreams", Tag=10, Type=typing.Optional[typing.List[PushAvStreamTransport.Structs.AudioStreamStruct]]), ]) streamUsage: 'Globals.Enums.StreamUsageEnum' = 0 @@ -49952,6 +49996,8 @@ def descriptor(cls) -> ClusterObjectDescriptor: ingestMethod: 'PushAvStreamTransport.Enums.IngestMethodsEnum' = 0 containerOptions: 'PushAvStreamTransport.Structs.ContainerOptionsStruct' = field(default_factory=lambda: PushAvStreamTransport.Structs.ContainerOptionsStruct()) expiryTime: 'typing.Optional[uint]' = None + videoStreams: 'typing.Optional[typing.List[PushAvStreamTransport.Structs.VideoStreamStruct]]' = None + audioStreams: 'typing.Optional[typing.List[PushAvStreamTransport.Structs.AudioStreamStruct]]' = None @dataclass class TransportConfigurationStruct(ClusterObject): @@ -50253,11 +50299,15 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="connectionID", Tag=0, Type=uint), ClusterObjectFieldDescriptor(Label="triggerType", Tag=1, Type=PushAvStreamTransport.Enums.TransportTriggerTypeEnum), ClusterObjectFieldDescriptor(Label="activationReason", Tag=2, Type=typing.Optional[PushAvStreamTransport.Enums.TriggerActivationReasonEnum]), + ClusterObjectFieldDescriptor(Label="containerType", Tag=3, Type=PushAvStreamTransport.Enums.ContainerFormatEnum), + ClusterObjectFieldDescriptor(Label="CMAFSessionNumber", Tag=4, Type=typing.Optional[uint]), ]) connectionID: uint = 0 triggerType: PushAvStreamTransport.Enums.TransportTriggerTypeEnum = 0 activationReason: typing.Optional[PushAvStreamTransport.Enums.TriggerActivationReasonEnum] = None + containerType: PushAvStreamTransport.Enums.ContainerFormatEnum = 0 + CMAFSessionNumber: typing.Optional[uint] = None @dataclass class PushTransportEnd(ClusterEvent): @@ -50274,9 +50324,13 @@ def descriptor(cls) -> ClusterObjectDescriptor: return ClusterObjectDescriptor( Fields=[ ClusterObjectFieldDescriptor(Label="connectionID", Tag=0, Type=uint), + ClusterObjectFieldDescriptor(Label="containerType", Tag=1, Type=PushAvStreamTransport.Enums.ContainerFormatEnum), + ClusterObjectFieldDescriptor(Label="CMAFSessionNumber", Tag=2, Type=typing.Optional[uint]), ]) connectionID: uint = 0 + containerType: PushAvStreamTransport.Enums.ContainerFormatEnum = 0 + CMAFSessionNumber: typing.Optional[uint] = None @dataclass @@ -50332,8 +50386,11 @@ class PlayChimeSound(ClusterCommand): def descriptor(cls) -> ClusterObjectDescriptor: return ClusterObjectDescriptor( Fields=[ + ClusterObjectFieldDescriptor(Label="chimeID", Tag=0, Type=typing.Optional[uint]), ]) + chimeID: typing.Optional[uint] = None + class Attributes: @dataclass class InstalledChimeSounds(ClusterAttributeDescriptor): @@ -50463,6 +50520,26 @@ def attribute_type(cls) -> ClusterObjectFieldDescriptor: value: uint = 0 + class Events: + @dataclass + class ChimeStartedPlaying(ClusterEvent): + @ChipUtility.classproperty + def cluster_id(cls) -> int: + return 0x00000556 + + @ChipUtility.classproperty + def event_id(cls) -> int: + return 0x00000000 + + @ChipUtility.classproperty + def descriptor(cls) -> ClusterObjectDescriptor: + return ClusterObjectDescriptor( + Fields=[ + ClusterObjectFieldDescriptor(Label="chimeID", Tag=0, Type=uint), + ]) + + chimeID: uint = 0 + @dataclass class CommodityTariff(Cluster): diff --git a/src/controller/webrtc/WebRTCClient.cpp b/src/controller/webrtc/WebRTCClient.cpp index 682aaed4e82..aca0a419c86 100644 --- a/src/controller/webrtc/WebRTCClient.cpp +++ b/src/controller/webrtc/WebRTCClient.cpp @@ -30,6 +30,70 @@ int ExtractDynamicPayloadType(const std::string & sdp, const std::string & type, const std::string & codec); const char * GetPeerConnectionStateStr(rtc::PeerConnection::State state); +/** + * @brief Validates that an SDP contains the minimum required fields for WebRTC. + * + * This function checks that the SDP has the mandatory session-level fields per RFC 8866 + * plus the necessary ICE and DTLS parameters required by the underlying WebRTC library. + * Without these fields, the library would throw an exception when trying to set the + * remote description. + * + * Required fields (per RFC 8866): + * - Version (v=) + * - Origin (o=) + * - Session name (s=) + * - Connection (c=) + * - Timing (t=) + * - At least one media line (m=) + * + * Required fields (WebRTC-specific): + * - ICE user fragment (a=ice-ufrag:) + * - ICE password (a=ice-pwd:) + * - DTLS fingerprint (a=fingerprint:) + * + * @param sdp The SDP string to validate + * @return true if the SDP contains all required fields, false otherwise + */ +bool ValidateSdpFields(const std::string & sdp) +{ + if (sdp.empty()) + { + ChipLogError(NotSpecified, "ValidateSdpFields: SDP is empty"); + return false; + } + + struct SdpRequirement + { + const char * substring; + const char * description; + }; + + // Define the list of required substrings and their corresponding descriptions for error logging. + // These include mandatory SDP session-level fields per RFC 8866 plus WebRTC-specific requirements. + static const SdpRequirement kRequirements[] = { + { "v=", "version" }, + { "o=", "origin" }, + { "s=", "session name" }, + { "c=", "connection" }, + { "t=", "timing" }, + { "m=", "media line" }, + { "a=ice-ufrag:", "ICE user fragment" }, + { "a=ice-pwd:", "ICE password" }, + { "a=fingerprint:", "DTLS fingerprint" }, + }; + + for (const auto & req : kRequirements) + { + if (sdp.find(req.substring) == std::string::npos) + { + ChipLogError(NotSpecified, "ValidateSdpFields: SDP has no %s (%s): %s", req.description, req.substring, sdp.c_str()); + return false; + } + } + + return true; +} + WebRTCClient::WebRTCClient() { mPeerConnection = nullptr; @@ -215,6 +279,11 @@ void WebRTCClient::SetRemoteDescription(const std::string & sdp, const std::stri return; } + if (!ValidateSdpFields(sdp)) + { + return; + } + if (type == "offer") { // Controller is the answerer. Extract values from offer SDP and add tracks accordingly diff --git a/src/controller/webrtc/WebRTCTransportProviderClient.h b/src/controller/webrtc/WebRTCTransportProviderClient.h index 8bcedc32caf..5959bfffbb2 100644 --- a/src/controller/webrtc/WebRTCTransportProviderClient.h +++ b/src/controller/webrtc/WebRTCTransportProviderClient.h @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/controller/webrtc/WebRTCTransportRequestorManager.cpp b/src/controller/webrtc/WebRTCTransportRequestorManager.cpp index 2a99e961c14..b7b849b510a 100644 --- a/src/controller/webrtc/WebRTCTransportRequestorManager.cpp +++ b/src/controller/webrtc/WebRTCTransportRequestorManager.cpp @@ -19,7 +19,7 @@ #include #include "WebRTCTransportRequestorManager.h" -#include +#include #include #include @@ -73,21 +73,21 @@ void WebRTCTransportRequestorManager::InitCallbacks(OnOfferCallback onOnOfferCal gOnEndCallback = onEndCallback; } -CHIP_ERROR WebRTCTransportRequestorManager::HandleOffer(uint16_t sessionId, const OfferArgs & args) +CHIP_ERROR WebRTCTransportRequestorManager::HandleOffer(const WebRTCSessionStruct & session, const OfferArgs & args) { std::string offer = args.sdp; - int err = gOnOfferCallback(sessionId, offer.c_str()); + int err = gOnOfferCallback(session.id, offer.c_str()); return err == 0 ? CHIP_NO_ERROR : CHIP_ERROR_INCORRECT_STATE; } -CHIP_ERROR WebRTCTransportRequestorManager::HandleAnswer(uint16_t sessionId, const std::string & sdpAnswer) +CHIP_ERROR WebRTCTransportRequestorManager::HandleAnswer(const WebRTCSessionStruct & session, const std::string & sdpAnswer) { std::string answer = sdpAnswer; - int err = gOnAnswerCallback(sessionId, answer.c_str()); + int err = gOnAnswerCallback(session.id, answer.c_str()); return err == 0 ? CHIP_NO_ERROR : CHIP_ERROR_INCORRECT_STATE; } -CHIP_ERROR WebRTCTransportRequestorManager::HandleICECandidates(uint16_t sessionId, +CHIP_ERROR WebRTCTransportRequestorManager::HandleICECandidates(const WebRTCSessionStruct & session, const std::vector & candidates) { std::vector remoteCandidates; @@ -120,13 +120,14 @@ CHIP_ERROR WebRTCTransportRequestorManager::HandleICECandidates(uint16_t session cStrings.push_back(candidate.view); } - int err = gOnICECandidatesCallback(sessionId, cStrings.data(), static_cast(cStrings.size())); + int err = gOnICECandidatesCallback(session.id, cStrings.data(), static_cast(cStrings.size())); return err == 0 ? CHIP_NO_ERROR : CHIP_ERROR_INCORRECT_STATE; } -CHIP_ERROR WebRTCTransportRequestorManager::HandleEnd(uint16_t sessionId, WebRTCTransportRequestor::WebRTCEndReasonEnum reasonCode) +CHIP_ERROR WebRTCTransportRequestorManager::HandleEnd(const WebRTCSessionStruct & session, + WebRTCTransportRequestor::WebRTCEndReasonEnum reasonCode) { - int err = gOnEndCallback(sessionId, static_cast(reasonCode)); + int err = gOnEndCallback(session.id, static_cast(reasonCode)); return err == 0 ? CHIP_NO_ERROR : CHIP_ERROR_INCORRECT_STATE; } diff --git a/src/controller/webrtc/WebRTCTransportRequestorManager.h b/src/controller/webrtc/WebRTCTransportRequestorManager.h index 6839eb13c27..65c0e470e5d 100644 --- a/src/controller/webrtc/WebRTCTransportRequestorManager.h +++ b/src/controller/webrtc/WebRTCTransportRequestorManager.h @@ -18,7 +18,7 @@ #pragma once #include -#include +#include #include #include #include @@ -49,6 +49,7 @@ class WebRTCTransportRequestorManager : public chip::app::Clusters::WebRTCTransp { public: using ICECandidateStruct = chip::app::Clusters::Globals::Structs::ICECandidateStruct::Type; + using WebRTCSessionStruct = chip::app::Clusters::Globals::Structs::WebRTCSessionStruct::Type; using WebRTCEndReasonEnum = chip::app::Clusters::Globals::WebRTCEndReasonEnum; static WebRTCTransportRequestorManager & Instance() @@ -66,13 +67,14 @@ class WebRTCTransportRequestorManager : public chip::app::Clusters::WebRTCTransp OnICECandidatesCallback onICECandidatesCallback, OnEndCallback onEndCallback); // delegate methods - CHIP_ERROR HandleOffer(uint16_t sessionId, const OfferArgs & args) override; + CHIP_ERROR HandleOffer(const WebRTCSessionStruct & session, const OfferArgs & args) override; - CHIP_ERROR HandleAnswer(uint16_t sessionId, const std::string & sdpAnswer) override; + CHIP_ERROR HandleAnswer(const WebRTCSessionStruct & session, const std::string & sdpAnswer) override; - CHIP_ERROR HandleICECandidates(uint16_t sessionId, const std::vector & candidates) override; + CHIP_ERROR HandleICECandidates(const WebRTCSessionStruct & session, + const std::vector & candidates) override; - CHIP_ERROR HandleEnd(uint16_t sessionId, WebRTCEndReasonEnum reasonCode) override; + CHIP_ERROR HandleEnd(const WebRTCSessionStruct & session, WebRTCEndReasonEnum reasonCode) override; // method to be called by provider client void UpsertSession(const chip::app::Clusters::Globals::Structs::WebRTCSessionStruct::Type & session); @@ -81,6 +83,6 @@ class WebRTCTransportRequestorManager : public chip::app::Clusters::WebRTCTransp WebRTCTransportRequestorManager() = default; ~WebRTCTransportRequestorManager() = default; - chip::app::LazyRegisteredServerCluster + chip::app::LazyRegisteredServerCluster mWebRTCRegisteredServerCluster; }; diff --git a/src/credentials/GroupDataProviderImpl.cpp b/src/credentials/GroupDataProviderImpl.cpp index 987f1107afc..0272864098c 100644 --- a/src/credentials/GroupDataProviderImpl.cpp +++ b/src/credentials/GroupDataProviderImpl.cpp @@ -45,7 +45,7 @@ struct FabricList : public CommonPersistentData::FabricList constexpr size_t kPersistentBufferMax = 128; -struct LinkedData : public PersistentData +struct LinkedData : public PersistableData { static constexpr uint16_t kMinLinkId = 1; @@ -59,7 +59,7 @@ struct LinkedData : public PersistentData bool first = true; }; -struct FabricData : public PersistentData +struct FabricData : public PersistableData { static constexpr TLV::Tag TagFirstGroup() { return TLV::ContextTag(1); } static constexpr TLV::Tag TagGroupCount() { return TLV::ContextTag(2); } @@ -247,20 +247,20 @@ struct FabricData : public PersistentData return CHIP_ERROR_NOT_FOUND; } - CHIP_ERROR Save(PersistentStorageDelegate * storage) override + CHIP_ERROR Save(PersistentStorageDelegate * storage) // NOLINT(bugprone-derived-method-shadowing-base-method) { ReturnErrorOnFailure(Register(storage)); - return PersistentData::Save(storage); + return PersistableData::Save(storage); } - CHIP_ERROR Delete(PersistentStorageDelegate * storage) override + CHIP_ERROR Delete(PersistentStorageDelegate * storage) // NOLINT(bugprone-derived-method-shadowing-base-method) { ReturnErrorOnFailure(Unregister(storage)); - return PersistentData::Delete(storage); + return PersistableData::Delete(storage); } }; -struct GroupData : public GroupDataProvider::GroupInfo, PersistentData +struct GroupData : public GroupDataProvider::GroupInfo, PersistableData { static constexpr TLV::Tag TagName() { return TLV::ContextTag(1); } static constexpr TLV::Tag TagFirstEndpoint() { return TLV::ContextTag(2); } @@ -536,7 +536,7 @@ struct KeyMapData : public GroupDataProvider::GroupKey, LinkedData } }; -struct EndpointData : GroupDataProvider::GroupEndpoint, PersistentData +struct EndpointData : GroupDataProvider::GroupEndpoint, PersistableData { static constexpr TLV::Tag TagEndpoint() { return TLV::ContextTag(1); } static constexpr TLV::Tag TagNext() { return TLV::ContextTag(2); } @@ -621,7 +621,7 @@ struct EndpointData : GroupDataProvider::GroupEndpoint, PersistentData +struct KeySetData : PersistableData { static constexpr TLV::Tag TagPolicy() { return TLV::ContextTag(1); } static constexpr TLV::Tag TagNumKeys() { return TLV::ContextTag(2); } diff --git a/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.cpp b/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.cpp index 3623f4fe776..23829096f8d 100644 --- a/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.cpp +++ b/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.cpp @@ -636,13 +636,27 @@ AttestationVerificationResult DefaultDACVerifier::ValidateCertificationDeclarati ChipLogError(NotSpecified, "Disallowing CD signed by test key"); return AttestationVerificationResult::kCertificationDeclarationNoCertificateFound; } - ChipLogProgress(NotSpecified, "Allowing CD signed by test key"); } VerifyOrReturnError(CMS_Verify(cmsEnvelopeBuffer, verifyingKey, certDeclBuffer) == CHIP_NO_ERROR, AttestationVerificationResult::kCertificationDeclarationInvalidSignature); + // certDeclBuffer is populated by CMS_Verify so we need to do this check after the signature check + CertificationElementsWithoutPIDs cdContent; + VerifyOrReturnError(DecodeCertificationElements(certDeclBuffer, cdContent) == CHIP_NO_ERROR, + AttestationVerificationResult::kCertificationDeclarationInvalidFormat); + // Ensure we didn't use a test key for official or provisional certificates (if disallowed) + bool testKeyAllowedForCertificationType = + (cdContent.certificationType == to_underlying(CertificationType::kDevelopmentAndTest)) || + (cdContent.certificationType == to_underlying(CertificationType::kProvisional) && kEnableCdTestKeysForProvisionalCds); + ChipLogProgress(NotSpecified, "Certification type %u", cdContent.certificationType); + if (mCdKeysTrustStore.IsCdTestKey(kid) && !testKeyAllowedForCertificationType) + { + ChipLogError(NotSpecified, "Test key is disallowed for this certification type: %u", cdContent.certificationType); + return AttestationVerificationResult::kCertificationDeclarationNoCertificateFound; + } + return AttestationVerificationResult::kSuccess; } diff --git a/src/credentials/attestation_verifier/DeviceAttestationVerifier.h b/src/credentials/attestation_verifier/DeviceAttestationVerifier.h index 26e778b1361..a7bf34d098e 100644 --- a/src/credentials/attestation_verifier/DeviceAttestationVerifier.h +++ b/src/credentials/attestation_verifier/DeviceAttestationVerifier.h @@ -440,6 +440,9 @@ class DeviceAttestationVerifier CHIP_ERROR ValidateAttestationSignature(const Crypto::P256PublicKey & pubkey, const ByteSpan & attestationElements, const ByteSpan & attestationChallenge, const Crypto::P256ECDSASignature & signature); + // Defaults to true for now. Should be set to false after a notification period. + // https://github.com/project-chip/connectedhomeip/issues/42460 to track. + static constexpr bool kEnableCdTestKeysForProvisionalCds = true; // Default to support the "development" test key for legacy purposes (since the DefaultDACVerifier) // always supported development keys. bool mEnableCdTestKeySupport = true; diff --git a/src/credentials/tests/TestCommissionerDUTVectors.cpp b/src/credentials/tests/TestCommissionerDUTVectors.cpp index 7aa8a552ce9..6524e86a794 100644 --- a/src/credentials/tests/TestCommissionerDUTVectors.cpp +++ b/src/credentials/tests/TestCommissionerDUTVectors.cpp @@ -42,6 +42,8 @@ using namespace chip; using namespace chip::Crypto; using namespace chip::Credentials; +void RunCommissionerDUTVectorsTest(bool allowTestKeys); + static void OnAttestationInformationVerificationCallback(void * context, const DeviceAttestationVerifier::AttestationInfo & info, AttestationVerificationResult result) { @@ -57,11 +59,22 @@ struct TestCommissionerDUTVectors : public ::testing::Test }; TEST_F(TestCommissionerDUTVectors, TestCommissionerDUTVectors) +{ + RunCommissionerDUTVectorsTest(true); +} + +TEST_F(TestCommissionerDUTVectors, TestCommissionerDUTVectorsNoTestKeys) +{ + RunCommissionerDUTVectorsTest(false); +} + +void RunCommissionerDUTVectorsTest(bool allowTestKeys) { chip::Credentials::DeviceAttestationRevocationDelegate * kDeviceAttestationRevocationNotChecked = nullptr; DeviceAttestationVerifier * example_dac_verifier = GetDefaultDACVerifier(GetTestAttestationTrustStore(), kDeviceAttestationRevocationNotChecked); ASSERT_NE(example_dac_verifier, nullptr); + example_dac_verifier->EnableCdTestKeySupport(allowTestKeys); std::string dirPath("../../../../../credentials/development/commissioner_dut/"); DIR * dir = opendir(dirPath.c_str()); @@ -86,6 +99,7 @@ TEST_F(TestCommissionerDUTVectors, TestCommissionerDUTVectors) if (strstr(entry->d_name, "struct_dac_sig_curve_secp256k1")) continue; + ChipLogProgress(NotSpecified, "Testing case: %s", entry->d_name); std::string jsonFilePath = dirPath + std::string(entry->d_name) + std::string("/test_case_vector.json"); chip::Credentials::Examples::TestHarnessDACProvider dacProvider; @@ -173,7 +187,9 @@ TEST_F(TestCommissionerDUTVectors, TestCommissionerDUTVectors) isSuccessCase = true; } - if (isSuccessCase) + // Every example in the SDK uses test keys because we don't have official signers. Expect they will all fail if we disallow + // test keys + if (isSuccessCase && allowTestKeys) { EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); } diff --git a/src/crypto/CHIPCryptoPALPSA.cpp b/src/crypto/CHIPCryptoPALPSA.cpp index b53a588f34c..c63a48b565b 100644 --- a/src/crypto/CHIPCryptoPALPSA.cpp +++ b/src/crypto/CHIPCryptoPALPSA.cpp @@ -128,6 +128,7 @@ CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, c constexpr uint8_t kBlockSize = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES); size_t block_aligned_length = (plaintext_length / kBlockSize) * kBlockSize; size_t partial_block_length = plaintext_length % kBlockSize; + size_t ciphertext_length = 0; // Make sure the calculated block_aligned_length is compliant with PSA's output size requirements. VerifyOrReturnError(block_aligned_length == PSA_AEAD_UPDATE_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm, block_aligned_length), @@ -137,37 +138,45 @@ CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, c { status = psa_aead_update(&operation, plaintext, block_aligned_length, ciphertext, block_aligned_length, &out_length); VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); - - ciphertext += out_length; + VerifyOrReturnError(out_length <= block_aligned_length, CHIP_ERROR_INTERNAL); + ciphertext_length += out_length; } if (partial_block_length > 0) { - uint8_t temp_buffer[kBlockSize]; + uint8_t temp[kBlockSize] = { 0 }; size_t rounded_up_length = PSA_AEAD_UPDATE_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm, partial_block_length); - VerifyOrReturnError(rounded_up_length <= sizeof(temp_buffer), CHIP_ERROR_BUFFER_TOO_SMALL); + VerifyOrReturnError(rounded_up_length <= sizeof(temp), CHIP_ERROR_INTERNAL); out_length = 0; - status = psa_aead_update(&operation, plaintext + block_aligned_length, partial_block_length, &temp_buffer[0], - rounded_up_length, &out_length); + status = psa_aead_update(&operation, plaintext + block_aligned_length, partial_block_length, temp, rounded_up_length, + &out_length); VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); - VerifyOrReturnError(partial_block_length == out_length, CHIP_ERROR_INTERNAL); - memcpy(ciphertext, temp_buffer, partial_block_length); - - ciphertext += out_length; + VerifyOrReturnError(ciphertext_length + out_length <= plaintext_length, CHIP_ERROR_INTERNAL); + // Add the encrypted output, if any + memcpy(&ciphertext[ciphertext_length], temp, out_length); + ciphertext_length += out_length; } if (plaintext_length != 0) { - out_length = 0; - tag_out_length = 0; + uint8_t temp[kBlockSize] = { 0 }; - status = psa_aead_finish(&operation, ciphertext, PSA_AEAD_FINISH_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm), &out_length, tag, - tag_length, &tag_out_length); - } + // The finish output should fit in the temp buffer + size_t max_finish = PSA_AEAD_FINISH_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm); + VerifyOrReturnError(max_finish <= sizeof(temp), CHIP_ERROR_BUFFER_TOO_SMALL); + // The finish may return the last part of the ciphertext + status = psa_aead_finish(&operation, temp, max_finish, &out_length, tag, tag_length, &tag_out_length); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); + // For CCM encryption, the ciphertext and plaintext length are equal + VerifyOrReturnError((ciphertext_length + out_length) == plaintext_length, CHIP_ERROR_INTERNAL); + // Add the encrypted output, if any + memcpy(&ciphertext[ciphertext_length], temp, out_length); + ciphertext_length += out_length; + } else { out_length = 0; @@ -242,6 +251,8 @@ CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length, constexpr uint8_t kBlockSize = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES); size_t block_aligned_length = (ciphertext_length / kBlockSize) * kBlockSize; size_t partial_block_length = ciphertext_length % kBlockSize; + size_t plaintext_length = 0; + uint8_t temp[kBlockSize] = { 0 }; // Make sure the calculated block_aligned_length is compliant with PSA's output size requirements. VerifyOrReturnError(block_aligned_length == PSA_AEAD_UPDATE_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm, block_aligned_length), @@ -251,33 +262,42 @@ CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length, { status = psa_aead_update(&operation, ciphertext, block_aligned_length, plaintext, block_aligned_length, &out_length); VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); - - plaintext += out_length; + VerifyOrReturnError(out_length <= block_aligned_length, CHIP_ERROR_INTERNAL); + plaintext_length += out_length; } if (partial_block_length > 0) { - uint8_t temp_buffer[kBlockSize]; size_t rounded_up_length = PSA_AEAD_UPDATE_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm, partial_block_length); - - VerifyOrReturnError(rounded_up_length <= sizeof(temp_buffer), CHIP_ERROR_BUFFER_TOO_SMALL); + VerifyOrReturnError(rounded_up_length <= sizeof(temp), CHIP_ERROR_BUFFER_TOO_SMALL); out_length = 0; - status = psa_aead_update(&operation, ciphertext + block_aligned_length, partial_block_length, &temp_buffer[0], - rounded_up_length, &out_length); + status = psa_aead_update(&operation, ciphertext + block_aligned_length, partial_block_length, temp, rounded_up_length, + &out_length); VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); - VerifyOrReturnError(partial_block_length == out_length, CHIP_ERROR_INTERNAL); - memcpy(plaintext, &temp_buffer[0], partial_block_length); - - plaintext += out_length; + VerifyOrReturnError(plaintext_length + out_length <= ciphertext_length, CHIP_ERROR_INTERNAL); + // Add the decrypted output, if any + memcpy(&plaintext[plaintext_length], temp, out_length); + plaintext_length += out_length; } + // The finish output should fit in the temp buffer + size_t max_verify = PSA_AEAD_VERIFY_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm); + VerifyOrReturnError(max_verify <= sizeof(temp), CHIP_ERROR_BUFFER_TOO_SMALL); + if (ciphertext_length != 0) { out_length = 0; - status = psa_aead_verify(&operation, plaintext, PSA_AEAD_VERIFY_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm), &out_length, tag, - tag_length); + memset(temp, 0, sizeof(temp)); + + status = psa_aead_verify(&operation, temp, max_verify, &out_length, tag, tag_length); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); + // For CCM decryption, the ciphertext and plaintext length are equal + VerifyOrReturnError((plaintext_length + out_length) == ciphertext_length, CHIP_ERROR_INTERNAL); + // Add the decrypted output, if any + memcpy(&plaintext[plaintext_length], temp, out_length); + plaintext_length += out_length; } else { diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm index e4bf184f921..605cd2b1547 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm @@ -19017,6 +19017,46 @@ static id _Nullable DecodeAttributeValueForWebRTCTransportProviderCluster(Attrib newElement_0.audioStreamID = [NSNumber numberWithUnsignedShort:entry_0.audioStreamID.Value()]; } newElement_0.metadataEnabled = [NSNumber numberWithBool:entry_0.metadataEnabled]; + if (entry_0.videoStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_3 = [NSMutableArray new]; + auto iter_3 = entry_0.videoStreams.Value().begin(); + while (iter_3.Next()) { + auto & entry_3 = iter_3.GetValue(); + NSNumber * newElement_3; + newElement_3 = [NSNumber numberWithUnsignedShort:entry_3]; + [array_3 addObject:newElement_3]; + } + CHIP_ERROR err = iter_3.GetStatus(); + if (err != CHIP_NO_ERROR) { + *aError = err; + return nil; + } + newElement_0.videoStreams = array_3; + } + } else { + newElement_0.videoStreams = nil; + } + if (entry_0.audioStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_3 = [NSMutableArray new]; + auto iter_3 = entry_0.audioStreams.Value().begin(); + while (iter_3.Next()) { + auto & entry_3 = iter_3.GetValue(); + NSNumber * newElement_3; + newElement_3 = [NSNumber numberWithUnsignedShort:entry_3]; + [array_3 addObject:newElement_3]; + } + CHIP_ERROR err = iter_3.GetStatus(); + if (err != CHIP_NO_ERROR) { + *aError = err; + return nil; + } + newElement_0.audioStreams = array_3; + } + } else { + newElement_0.audioStreams = nil; + } newElement_0.fabricIndex = [NSNumber numberWithUnsignedChar:entry_0.fabricIndex]; [array_0 addObject:newElement_0]; } @@ -19072,6 +19112,46 @@ static id _Nullable DecodeAttributeValueForWebRTCTransportRequestorCluster(Attri newElement_0.audioStreamID = [NSNumber numberWithUnsignedShort:entry_0.audioStreamID.Value()]; } newElement_0.metadataEnabled = [NSNumber numberWithBool:entry_0.metadataEnabled]; + if (entry_0.videoStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_3 = [NSMutableArray new]; + auto iter_3 = entry_0.videoStreams.Value().begin(); + while (iter_3.Next()) { + auto & entry_3 = iter_3.GetValue(); + NSNumber * newElement_3; + newElement_3 = [NSNumber numberWithUnsignedShort:entry_3]; + [array_3 addObject:newElement_3]; + } + CHIP_ERROR err = iter_3.GetStatus(); + if (err != CHIP_NO_ERROR) { + *aError = err; + return nil; + } + newElement_0.videoStreams = array_3; + } + } else { + newElement_0.videoStreams = nil; + } + if (entry_0.audioStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_3 = [NSMutableArray new]; + auto iter_3 = entry_0.audioStreams.Value().begin(); + while (iter_3.Next()) { + auto & entry_3 = iter_3.GetValue(); + NSNumber * newElement_3; + newElement_3 = [NSNumber numberWithUnsignedShort:entry_3]; + [array_3 addObject:newElement_3]; + } + CHIP_ERROR err = iter_3.GetStatus(); + if (err != CHIP_NO_ERROR) { + *aError = err; + return nil; + } + newElement_0.audioStreams = array_3; + } + } else { + newElement_0.audioStreams = nil; + } newElement_0.fabricIndex = [NSNumber numberWithUnsignedChar:entry_0.fabricIndex]; [array_0 addObject:newElement_0]; } @@ -19267,6 +19347,60 @@ static id _Nullable DecodeAttributeValueForPushAVStreamTransportCluster(Attribut } else { newElement_0.transportOptions.expiryTime = nil; } + if (entry_0.transportOptions.Value().videoStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_5 = [NSMutableArray new]; + auto iter_5 = entry_0.transportOptions.Value().videoStreams.Value().begin(); + while (iter_5.Next()) { + auto & entry_5 = iter_5.GetValue(); + MTRPushAVStreamTransportClusterVideoStreamStruct * newElement_5; + newElement_5 = [MTRPushAVStreamTransportClusterVideoStreamStruct new]; + newElement_5.videoStreamName = AsString(entry_5.videoStreamName); + if (newElement_5.videoStreamName == nil) { + CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; + *aError = err; + return nil; + } + newElement_5.videoStreamID = [NSNumber numberWithUnsignedShort:entry_5.videoStreamID]; + [array_5 addObject:newElement_5]; + } + CHIP_ERROR err = iter_5.GetStatus(); + if (err != CHIP_NO_ERROR) { + *aError = err; + return nil; + } + newElement_0.transportOptions.videoStreams = array_5; + } + } else { + newElement_0.transportOptions.videoStreams = nil; + } + if (entry_0.transportOptions.Value().audioStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_5 = [NSMutableArray new]; + auto iter_5 = entry_0.transportOptions.Value().audioStreams.Value().begin(); + while (iter_5.Next()) { + auto & entry_5 = iter_5.GetValue(); + MTRPushAVStreamTransportClusterAudioStreamStruct * newElement_5; + newElement_5 = [MTRPushAVStreamTransportClusterAudioStreamStruct new]; + newElement_5.audioStreamName = AsString(entry_5.audioStreamName); + if (newElement_5.audioStreamName == nil) { + CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; + *aError = err; + return nil; + } + newElement_5.audioStreamID = [NSNumber numberWithUnsignedShort:entry_5.audioStreamID]; + [array_5 addObject:newElement_5]; + } + CHIP_ERROR err = iter_5.GetStatus(); + if (err != CHIP_NO_ERROR) { + *aError = err; + return nil; + } + newElement_0.transportOptions.audioStreams = array_5; + } + } else { + newElement_0.transportOptions.audioStreams = nil; + } } else { newElement_0.transportOptions = nil; } diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h index 039fb7708ca..e38c9fd847d 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h @@ -15622,7 +15622,7 @@ MTR_PROVISIONALLY_AVAILABLE /** * Command PlayChimeSound * - * + * This command will play the currently selected chime or the chime passed in. */ - (void)playChimeSoundWithParams:(MTRChimeClusterPlayChimeSoundParams * _Nullable)params completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; - (void)playChimeSoundWithCompletion:(MTRStatusCompletion)completion @@ -22120,6 +22120,7 @@ typedef NS_ENUM(uint8_t, MTRCameraAVStreamManagementAudioCodec) { typedef NS_ENUM(uint8_t, MTRCameraAVStreamManagementImageCodec) { MTRCameraAVStreamManagementImageCodecJPEG MTR_PROVISIONALLY_AVAILABLE = 0x00, + MTRCameraAVStreamManagementImageCodecHEIC MTR_PROVISIONALLY_AVAILABLE = 0x01, } MTR_PROVISIONALLY_AVAILABLE; typedef NS_ENUM(uint8_t, MTRCameraAVStreamManagementTriStateAuto) { @@ -22197,6 +22198,8 @@ typedef NS_ENUM(uint8_t, MTRPushAVStreamTransportStatusCode) { MTRPushAVStreamTransportStatusCodeInvalidOptions MTR_PROVISIONALLY_AVAILABLE = 0x09, MTRPushAVStreamTransportStatusCodeInvalidStreamUsage MTR_PROVISIONALLY_AVAILABLE = 0x0A, MTRPushAVStreamTransportStatusCodeInvalidTime MTR_PROVISIONALLY_AVAILABLE = 0x0B, + MTRPushAVStreamTransportStatusCodeInvalidPreRollLength MTR_PROVISIONALLY_AVAILABLE = 0x0C, + MTRPushAVStreamTransportStatusCodeDuplicateStreamValues MTR_PROVISIONALLY_AVAILABLE = 0x0D, } MTR_PROVISIONALLY_AVAILABLE; typedef NS_ENUM(uint8_t, MTRPushAVStreamTransportTransportStatus) { @@ -22214,6 +22217,7 @@ typedef NS_ENUM(uint8_t, MTRPushAVStreamTransportTriggerActivationReason) { MTRPushAVStreamTransportTriggerActivationReasonUserInitiated MTR_PROVISIONALLY_AVAILABLE = 0x00, MTRPushAVStreamTransportTriggerActivationReasonAutomation MTR_PROVISIONALLY_AVAILABLE = 0x01, MTRPushAVStreamTransportTriggerActivationReasonEmergency MTR_PROVISIONALLY_AVAILABLE = 0x02, + MTRPushAVStreamTransportTriggerActivationReasonDoorbellPressed MTR_PROVISIONALLY_AVAILABLE = 0x03, } MTR_PROVISIONALLY_AVAILABLE; typedef NS_OPTIONS(uint32_t, MTRPushAVStreamTransportFeature) { diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h index 236fd06703b..2f3d4e33a82 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h @@ -7884,6 +7884,9 @@ typedef NS_ENUM(uint32_t, MTREventIDType) { MTREventIDTypeClusterPushAVStreamTransportEventPushTransportBeginID MTR_PROVISIONALLY_AVAILABLE = 0x00000000, MTREventIDTypeClusterPushAVStreamTransportEventPushTransportEndID MTR_PROVISIONALLY_AVAILABLE = 0x00000001, + // Cluster Chime events + MTREventIDTypeClusterChimeEventChimeStartedPlayingID MTR_PROVISIONALLY_AVAILABLE = 0x00000000, + // Cluster CommissionerControl events MTREventIDTypeClusterCommissionerControlEventCommissioningRequestResultID MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x00000000, diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm b/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm index 04795a5305e..e5072e9df97 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm @@ -16236,6 +16236,11 @@ switch (eventID) { + // Cluster Chime events + case MTREventIDTypeClusterChimeEventChimeStartedPlayingID: + result = @"ChimeStartedPlaying"; + break; + default: result = [NSString stringWithFormat:@"", eventID]; break; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h index 7755a113e90..205589afffd 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h @@ -12307,6 +12307,10 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy) NSNumber * _Nullable metadataEnabled MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) MTRWebRTCTransportProviderClusterSFrameStruct * _Nullable sFrameConfig MTR_PROVISIONALLY_AVAILABLE; + +@property (nonatomic, copy) NSArray * _Nullable videoStreams MTR_PROVISIONALLY_AVAILABLE; + +@property (nonatomic, copy) NSArray * _Nullable audioStreams MTR_PROVISIONALLY_AVAILABLE; /** * Controls whether the command is a timed command (using Timed Invoke). * @@ -12380,6 +12384,10 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy) NSNumber * _Nullable metadataEnabled MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) MTRWebRTCTransportProviderClusterSFrameStruct * _Nullable sFrameConfig MTR_PROVISIONALLY_AVAILABLE; + +@property (nonatomic, copy) NSArray * _Nullable videoStreams MTR_PROVISIONALLY_AVAILABLE; + +@property (nonatomic, copy) NSArray * _Nullable audioStreams MTR_PROVISIONALLY_AVAILABLE; /** * Controls whether the command is a timed command (using Timed Invoke). * @@ -12887,6 +12895,8 @@ MTR_PROVISIONALLY_AVAILABLE MTR_PROVISIONALLY_AVAILABLE @interface MTRChimeClusterPlayChimeSoundParams : NSObject + +@property (nonatomic, copy) NSNumber * _Nullable chimeID 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 c2b628a1397..d5965a862e1 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm @@ -36805,6 +36805,10 @@ - (instancetype)init _metadataEnabled = nil; _sFrameConfig = nil; + + _videoStreams = nil; + + _audioStreams = nil; _timedInvokeTimeoutMs = nil; _serverSideProcessingTimeout = nil; } @@ -36823,6 +36827,8 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; other.iceTransportPolicy = self.iceTransportPolicy; other.metadataEnabled = self.metadataEnabled; other.sFrameConfig = self.sFrameConfig; + other.videoStreams = self.videoStreams; + other.audioStreams = self.audioStreams; other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; @@ -36831,7 +36837,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: streamUsage:%@; originatingEndpointID:%@; videoStreamID:%@; audioStreamID:%@; iceServers:%@; iceTransportPolicy:%@; metadataEnabled:%@; sFrameConfig:%@; >", NSStringFromClass([self class]), _streamUsage, _originatingEndpointID, _videoStreamID, _audioStreamID, _iceServers, _iceTransportPolicy, _metadataEnabled, _sFrameConfig]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: streamUsage:%@; originatingEndpointID:%@; videoStreamID:%@; audioStreamID:%@; iceServers:%@; iceTransportPolicy:%@; metadataEnabled:%@; sFrameConfig:%@; videoStreams:%@; audioStreams:%@; >", NSStringFromClass([self class]), _streamUsage, _originatingEndpointID, _videoStreamID, _audioStreamID, _iceServers, _iceTransportPolicy, _metadataEnabled, _sFrameConfig, _videoStreams, _audioStreams]; return descriptionString; } @@ -36953,6 +36959,62 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader definedValue_0.kid = AsByteSpan(self.sFrameConfig.kid); } } + { + if (self.videoStreams != nil) { + auto & definedValue_0 = encodableStruct.videoStreams.Emplace(); + { + using ListType_1 = std::remove_reference_t; + using ListMemberType_1 = ListMemberTypeGetter::Type; + if (self.videoStreams.count != 0) { + auto * listHolder_1 = new ListHolder(self.videoStreams.count); + if (listHolder_1 == nullptr || listHolder_1->mList == nullptr) { + return CHIP_ERROR_INVALID_ARGUMENT; + } + listFreer.add(listHolder_1); + for (size_t i_1 = 0; i_1 < self.videoStreams.count; ++i_1) { + auto element_1 = MTR_SAFE_CAST(self.videoStreams[i_1], NSNumber); + if (!element_1) { + // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.videoStreams[i_1], NSStringFromClass(NSNumber.class)); + return CHIP_ERROR_INVALID_ARGUMENT; + } + listHolder_1->mList[i_1] = element_1.unsignedShortValue; + } + definedValue_0 = ListType_1(listHolder_1->mList, self.videoStreams.count); + } else { + definedValue_0 = ListType_1(); + } + } + } + } + { + if (self.audioStreams != nil) { + auto & definedValue_0 = encodableStruct.audioStreams.Emplace(); + { + using ListType_1 = std::remove_reference_t; + using ListMemberType_1 = ListMemberTypeGetter::Type; + if (self.audioStreams.count != 0) { + auto * listHolder_1 = new ListHolder(self.audioStreams.count); + if (listHolder_1 == nullptr || listHolder_1->mList == nullptr) { + return CHIP_ERROR_INVALID_ARGUMENT; + } + listFreer.add(listHolder_1); + for (size_t i_1 = 0; i_1 < self.audioStreams.count; ++i_1) { + auto element_1 = MTR_SAFE_CAST(self.audioStreams[i_1], NSNumber); + if (!element_1) { + // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.audioStreams[i_1], NSStringFromClass(NSNumber.class)); + return CHIP_ERROR_INVALID_ARGUMENT; + } + listHolder_1->mList[i_1] = element_1.unsignedShortValue; + } + definedValue_0 = ListType_1(listHolder_1->mList, self.audioStreams.count); + } else { + definedValue_0 = ListType_1(); + } + } + } + } auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); if (buffer.IsNull()) { @@ -37139,6 +37201,10 @@ - (instancetype)init _metadataEnabled = nil; _sFrameConfig = nil; + + _videoStreams = nil; + + _audioStreams = nil; _timedInvokeTimeoutMs = nil; _serverSideProcessingTimeout = nil; } @@ -37159,6 +37225,8 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; other.iceTransportPolicy = self.iceTransportPolicy; other.metadataEnabled = self.metadataEnabled; other.sFrameConfig = self.sFrameConfig; + other.videoStreams = self.videoStreams; + other.audioStreams = self.audioStreams; other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; @@ -37167,7 +37235,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: webRTCSessionID:%@; sdp:%@; streamUsage:%@; originatingEndpointID:%@; videoStreamID:%@; audioStreamID:%@; iceServers:%@; iceTransportPolicy:%@; metadataEnabled:%@; sFrameConfig:%@; >", NSStringFromClass([self class]), _webRTCSessionID, _sdp, _streamUsage, _originatingEndpointID, _videoStreamID, _audioStreamID, _iceServers, _iceTransportPolicy, _metadataEnabled, _sFrameConfig]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: webRTCSessionID:%@; sdp:%@; streamUsage:%@; originatingEndpointID:%@; videoStreamID:%@; audioStreamID:%@; iceServers:%@; iceTransportPolicy:%@; metadataEnabled:%@; sFrameConfig:%@; videoStreams:%@; audioStreams:%@; >", NSStringFromClass([self class]), _webRTCSessionID, _sdp, _streamUsage, _originatingEndpointID, _videoStreamID, _audioStreamID, _iceServers, _iceTransportPolicy, _metadataEnabled, _sFrameConfig, _videoStreams, _audioStreams]; return descriptionString; } @@ -37300,6 +37368,62 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader definedValue_0.kid = AsByteSpan(self.sFrameConfig.kid); } } + { + if (self.videoStreams != nil) { + auto & definedValue_0 = encodableStruct.videoStreams.Emplace(); + { + using ListType_1 = std::remove_reference_t; + using ListMemberType_1 = ListMemberTypeGetter::Type; + if (self.videoStreams.count != 0) { + auto * listHolder_1 = new ListHolder(self.videoStreams.count); + if (listHolder_1 == nullptr || listHolder_1->mList == nullptr) { + return CHIP_ERROR_INVALID_ARGUMENT; + } + listFreer.add(listHolder_1); + for (size_t i_1 = 0; i_1 < self.videoStreams.count; ++i_1) { + auto element_1 = MTR_SAFE_CAST(self.videoStreams[i_1], NSNumber); + if (!element_1) { + // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.videoStreams[i_1], NSStringFromClass(NSNumber.class)); + return CHIP_ERROR_INVALID_ARGUMENT; + } + listHolder_1->mList[i_1] = element_1.unsignedShortValue; + } + definedValue_0 = ListType_1(listHolder_1->mList, self.videoStreams.count); + } else { + definedValue_0 = ListType_1(); + } + } + } + } + { + if (self.audioStreams != nil) { + auto & definedValue_0 = encodableStruct.audioStreams.Emplace(); + { + using ListType_1 = std::remove_reference_t; + using ListMemberType_1 = ListMemberTypeGetter::Type; + if (self.audioStreams.count != 0) { + auto * listHolder_1 = new ListHolder(self.audioStreams.count); + if (listHolder_1 == nullptr || listHolder_1->mList == nullptr) { + return CHIP_ERROR_INVALID_ARGUMENT; + } + listFreer.add(listHolder_1); + for (size_t i_1 = 0; i_1 < self.audioStreams.count; ++i_1) { + auto element_1 = MTR_SAFE_CAST(self.audioStreams[i_1], NSNumber); + if (!element_1) { + // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.audioStreams[i_1], NSStringFromClass(NSNumber.class)); + return CHIP_ERROR_INVALID_ARGUMENT; + } + listHolder_1->mList[i_1] = element_1.unsignedShortValue; + } + definedValue_0 = ListType_1(listHolder_1->mList, self.audioStreams.count); + } else { + definedValue_0 = ListType_1(); + } + } + } + } auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); if (buffer.IsNull()) { @@ -38339,6 +38463,60 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader auto & definedValue_1 = encodableStruct.transportOptions.expiryTime.Emplace(); definedValue_1 = self.transportOptions.expiryTime.unsignedIntValue; } + if (self.transportOptions.videoStreams != nil) { + auto & definedValue_1 = encodableStruct.transportOptions.videoStreams.Emplace(); + { + using ListType_2 = std::remove_reference_t; + using ListMemberType_2 = ListMemberTypeGetter::Type; + if (self.transportOptions.videoStreams.count != 0) { + auto * listHolder_2 = new ListHolder(self.transportOptions.videoStreams.count); + if (listHolder_2 == nullptr || listHolder_2->mList == nullptr) { + return CHIP_ERROR_INVALID_ARGUMENT; + } + listFreer.add(listHolder_2); + for (size_t i_2 = 0; i_2 < self.transportOptions.videoStreams.count; ++i_2) { + auto element_2 = MTR_SAFE_CAST(self.transportOptions.videoStreams[i_2], MTRPushAVStreamTransportClusterVideoStreamStruct); + if (!element_2) { + // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.transportOptions.videoStreams[i_2], NSStringFromClass(MTRPushAVStreamTransportClusterVideoStreamStruct.class)); + return CHIP_ERROR_INVALID_ARGUMENT; + } + listHolder_2->mList[i_2].videoStreamName = AsCharSpan(element_2.videoStreamName); + listHolder_2->mList[i_2].videoStreamID = element_2.videoStreamID.unsignedShortValue; + } + definedValue_1 = ListType_2(listHolder_2->mList, self.transportOptions.videoStreams.count); + } else { + definedValue_1 = ListType_2(); + } + } + } + if (self.transportOptions.audioStreams != nil) { + auto & definedValue_1 = encodableStruct.transportOptions.audioStreams.Emplace(); + { + using ListType_2 = std::remove_reference_t; + using ListMemberType_2 = ListMemberTypeGetter::Type; + if (self.transportOptions.audioStreams.count != 0) { + auto * listHolder_2 = new ListHolder(self.transportOptions.audioStreams.count); + if (listHolder_2 == nullptr || listHolder_2->mList == nullptr) { + return CHIP_ERROR_INVALID_ARGUMENT; + } + listFreer.add(listHolder_2); + for (size_t i_2 = 0; i_2 < self.transportOptions.audioStreams.count; ++i_2) { + auto element_2 = MTR_SAFE_CAST(self.transportOptions.audioStreams[i_2], MTRPushAVStreamTransportClusterAudioStreamStruct); + if (!element_2) { + // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.transportOptions.audioStreams[i_2], NSStringFromClass(MTRPushAVStreamTransportClusterAudioStreamStruct.class)); + return CHIP_ERROR_INVALID_ARGUMENT; + } + listHolder_2->mList[i_2].audioStreamName = AsCharSpan(element_2.audioStreamName); + listHolder_2->mList[i_2].audioStreamID = element_2.audioStreamID.unsignedShortValue; + } + definedValue_1 = ListType_2(listHolder_2->mList, self.transportOptions.audioStreams.count); + } else { + definedValue_1 = ListType_2(); + } + } + } } auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); @@ -38586,6 +38764,56 @@ - (CHIP_ERROR)_setFieldsFromDecodableStruct:(const chip::app::Clusters::PushAvSt } else { self.transportConfiguration.transportOptions.expiryTime = nil; } + if (decodableStruct.transportConfiguration.transportOptions.Value().videoStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_4 = [NSMutableArray new]; + auto iter_4 = decodableStruct.transportConfiguration.transportOptions.Value().videoStreams.Value().begin(); + while (iter_4.Next()) { + auto & entry_4 = iter_4.GetValue(); + MTRPushAVStreamTransportClusterVideoStreamStruct * newElement_4; + newElement_4 = [MTRPushAVStreamTransportClusterVideoStreamStruct new]; + newElement_4.videoStreamName = AsString(entry_4.videoStreamName); + if (newElement_4.videoStreamName == nil) { + CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; + return err; + } + newElement_4.videoStreamID = [NSNumber numberWithUnsignedShort:entry_4.videoStreamID]; + [array_4 addObject:newElement_4]; + } + CHIP_ERROR err = iter_4.GetStatus(); + if (err != CHIP_NO_ERROR) { + return err; + } + self.transportConfiguration.transportOptions.videoStreams = array_4; + } + } else { + self.transportConfiguration.transportOptions.videoStreams = nil; + } + if (decodableStruct.transportConfiguration.transportOptions.Value().audioStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_4 = [NSMutableArray new]; + auto iter_4 = decodableStruct.transportConfiguration.transportOptions.Value().audioStreams.Value().begin(); + while (iter_4.Next()) { + auto & entry_4 = iter_4.GetValue(); + MTRPushAVStreamTransportClusterAudioStreamStruct * newElement_4; + newElement_4 = [MTRPushAVStreamTransportClusterAudioStreamStruct new]; + newElement_4.audioStreamName = AsString(entry_4.audioStreamName); + if (newElement_4.audioStreamName == nil) { + CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; + return err; + } + newElement_4.audioStreamID = [NSNumber numberWithUnsignedShort:entry_4.audioStreamID]; + [array_4 addObject:newElement_4]; + } + CHIP_ERROR err = iter_4.GetStatus(); + if (err != CHIP_NO_ERROR) { + return err; + } + self.transportConfiguration.transportOptions.audioStreams = array_4; + } + } else { + self.transportConfiguration.transportOptions.audioStreams = nil; + } } else { self.transportConfiguration.transportOptions = nil; } @@ -38827,6 +39055,60 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader auto & definedValue_1 = encodableStruct.transportOptions.expiryTime.Emplace(); definedValue_1 = self.transportOptions.expiryTime.unsignedIntValue; } + if (self.transportOptions.videoStreams != nil) { + auto & definedValue_1 = encodableStruct.transportOptions.videoStreams.Emplace(); + { + using ListType_2 = std::remove_reference_t; + using ListMemberType_2 = ListMemberTypeGetter::Type; + if (self.transportOptions.videoStreams.count != 0) { + auto * listHolder_2 = new ListHolder(self.transportOptions.videoStreams.count); + if (listHolder_2 == nullptr || listHolder_2->mList == nullptr) { + return CHIP_ERROR_INVALID_ARGUMENT; + } + listFreer.add(listHolder_2); + for (size_t i_2 = 0; i_2 < self.transportOptions.videoStreams.count; ++i_2) { + auto element_2 = MTR_SAFE_CAST(self.transportOptions.videoStreams[i_2], MTRPushAVStreamTransportClusterVideoStreamStruct); + if (!element_2) { + // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.transportOptions.videoStreams[i_2], NSStringFromClass(MTRPushAVStreamTransportClusterVideoStreamStruct.class)); + return CHIP_ERROR_INVALID_ARGUMENT; + } + listHolder_2->mList[i_2].videoStreamName = AsCharSpan(element_2.videoStreamName); + listHolder_2->mList[i_2].videoStreamID = element_2.videoStreamID.unsignedShortValue; + } + definedValue_1 = ListType_2(listHolder_2->mList, self.transportOptions.videoStreams.count); + } else { + definedValue_1 = ListType_2(); + } + } + } + if (self.transportOptions.audioStreams != nil) { + auto & definedValue_1 = encodableStruct.transportOptions.audioStreams.Emplace(); + { + using ListType_2 = std::remove_reference_t; + using ListMemberType_2 = ListMemberTypeGetter::Type; + if (self.transportOptions.audioStreams.count != 0) { + auto * listHolder_2 = new ListHolder(self.transportOptions.audioStreams.count); + if (listHolder_2 == nullptr || listHolder_2->mList == nullptr) { + return CHIP_ERROR_INVALID_ARGUMENT; + } + listFreer.add(listHolder_2); + for (size_t i_2 = 0; i_2 < self.transportOptions.audioStreams.count; ++i_2) { + auto element_2 = MTR_SAFE_CAST(self.transportOptions.audioStreams[i_2], MTRPushAVStreamTransportClusterAudioStreamStruct); + if (!element_2) { + // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.transportOptions.audioStreams[i_2], NSStringFromClass(MTRPushAVStreamTransportClusterAudioStreamStruct.class)); + return CHIP_ERROR_INVALID_ARGUMENT; + } + listHolder_2->mList[i_2].audioStreamName = AsCharSpan(element_2.audioStreamName); + listHolder_2->mList[i_2].audioStreamID = element_2.audioStreamID.unsignedShortValue; + } + definedValue_1 = ListType_2(listHolder_2->mList, self.transportOptions.audioStreams.count); + } else { + definedValue_1 = ListType_2(); + } + } + } } auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); @@ -39360,6 +39642,56 @@ - (CHIP_ERROR)_setFieldsFromDecodableStruct:(const chip::app::Clusters::PushAvSt } else { newElement_0.transportOptions.expiryTime = nil; } + if (entry_0.transportOptions.Value().videoStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_5 = [NSMutableArray new]; + auto iter_5 = entry_0.transportOptions.Value().videoStreams.Value().begin(); + while (iter_5.Next()) { + auto & entry_5 = iter_5.GetValue(); + MTRPushAVStreamTransportClusterVideoStreamStruct * newElement_5; + newElement_5 = [MTRPushAVStreamTransportClusterVideoStreamStruct new]; + newElement_5.videoStreamName = AsString(entry_5.videoStreamName); + if (newElement_5.videoStreamName == nil) { + CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; + return err; + } + newElement_5.videoStreamID = [NSNumber numberWithUnsignedShort:entry_5.videoStreamID]; + [array_5 addObject:newElement_5]; + } + CHIP_ERROR err = iter_5.GetStatus(); + if (err != CHIP_NO_ERROR) { + return err; + } + newElement_0.transportOptions.videoStreams = array_5; + } + } else { + newElement_0.transportOptions.videoStreams = nil; + } + if (entry_0.transportOptions.Value().audioStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_5 = [NSMutableArray new]; + auto iter_5 = entry_0.transportOptions.Value().audioStreams.Value().begin(); + while (iter_5.Next()) { + auto & entry_5 = iter_5.GetValue(); + MTRPushAVStreamTransportClusterAudioStreamStruct * newElement_5; + newElement_5 = [MTRPushAVStreamTransportClusterAudioStreamStruct new]; + newElement_5.audioStreamName = AsString(entry_5.audioStreamName); + if (newElement_5.audioStreamName == nil) { + CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; + return err; + } + newElement_5.audioStreamID = [NSNumber numberWithUnsignedShort:entry_5.audioStreamID]; + [array_5 addObject:newElement_5]; + } + CHIP_ERROR err = iter_5.GetStatus(); + if (err != CHIP_NO_ERROR) { + return err; + } + newElement_0.transportOptions.audioStreams = array_5; + } + } else { + newElement_0.transportOptions.audioStreams = nil; + } } else { newElement_0.transportOptions = nil; } @@ -39382,6 +39714,8 @@ @implementation MTRChimeClusterPlayChimeSoundParams - (instancetype)init { if (self = [super init]) { + + _chimeID = nil; _timedInvokeTimeoutMs = nil; _serverSideProcessingTimeout = nil; } @@ -39392,6 +39726,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; { auto other = [[MTRChimeClusterPlayChimeSoundParams alloc] init]; + other.chimeID = self.chimeID; other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; @@ -39400,7 +39735,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: >", NSStringFromClass([self class])]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: chimeID:%@; >", NSStringFromClass([self class]), _chimeID]; return descriptionString; } @@ -39412,6 +39747,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader { chip::app::Clusters::Chime::Commands::PlayChimeSound::Type encodableStruct; ListFreer listFreer; + { + if (self.chimeID != nil) { + auto & definedValue_0 = encodableStruct.chimeID.Emplace(); + definedValue_0 = self.chimeID.unsignedCharValue; + } + } auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); if (buffer.IsNull()) { diff --git a/src/darwin/Framework/CHIP/zap-generated/MTREventTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/MTREventTLVValueDecoder.mm index 775796fa459..1c846589fe4 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTREventTLVValueDecoder.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTREventTLVValueDecoder.mm @@ -5242,6 +5242,20 @@ static id _Nullable DecodeEventPayloadForPushAVStreamTransportCluster(EventId aE } value.activationReason = memberValue; } while (0); + do { + NSNumber * _Nonnull memberValue; + memberValue = [NSNumber numberWithUnsignedChar:chip::to_underlying(cppValue.containerType)]; + value.containerType = memberValue; + } while (0); + do { + NSNumber * _Nullable memberValue; + if (cppValue.CMAFSessionNumber.HasValue()) { + memberValue = [NSNumber numberWithUnsignedLongLong:cppValue.CMAFSessionNumber.Value()]; + } else { + memberValue = nil; + } + value.cmafSessionNumber = memberValue; + } while (0); return value; } @@ -5259,6 +5273,20 @@ static id _Nullable DecodeEventPayloadForPushAVStreamTransportCluster(EventId aE memberValue = [NSNumber numberWithUnsignedShort:cppValue.connectionID]; value.connectionID = memberValue; } while (0); + do { + NSNumber * _Nonnull memberValue; + memberValue = [NSNumber numberWithUnsignedChar:chip::to_underlying(cppValue.containerType)]; + value.containerType = memberValue; + } while (0); + do { + NSNumber * _Nullable memberValue; + if (cppValue.CMAFSessionNumber.HasValue()) { + memberValue = [NSNumber numberWithUnsignedLongLong:cppValue.CMAFSessionNumber.Value()]; + } else { + memberValue = nil; + } + value.cmafSessionNumber = memberValue; + } while (0); return value; } @@ -5275,6 +5303,23 @@ static id _Nullable DecodeEventPayloadForChimeCluster(EventId aEventId, TLV::TLV { using namespace Clusters::Chime; switch (aEventId) { + case Events::ChimeStartedPlaying::Id: { + Events::ChimeStartedPlaying::DecodableType cppValue; + *aError = DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) { + return nil; + } + + __auto_type * value = [MTRChimeClusterChimeStartedPlayingEvent new]; + + do { + NSNumber * _Nonnull memberValue; + memberValue = [NSNumber numberWithUnsignedChar:cppValue.chimeID]; + value.chimeID = memberValue; + } while (0); + + return value; + } default: { // Not a known Chime event. break; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h index 6b9131f9415..848f6768f9a 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h @@ -119,6 +119,8 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy) NSNumber * _Nullable videoStreamID MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nullable audioStreamID MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nonnull metadataEnabled MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSArray * _Nullable videoStreams MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSArray * _Nullable audioStreams MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nonnull fabricIndex MTR_PROVISIONALLY_AVAILABLE; @end @@ -2502,6 +2504,18 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy) NSNumber * _Nullable sensitivity MTR_PROVISIONALLY_AVAILABLE; @end +MTR_PROVISIONALLY_AVAILABLE +@interface MTRPushAVStreamTransportClusterAudioStreamStruct : NSObject +@property (nonatomic, copy) NSString * _Nonnull audioStreamName MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull audioStreamID MTR_PROVISIONALLY_AVAILABLE; +@end + +MTR_PROVISIONALLY_AVAILABLE +@interface MTRPushAVStreamTransportClusterVideoStreamStruct : NSObject +@property (nonatomic, copy) NSString * _Nonnull videoStreamName MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull videoStreamID MTR_PROVISIONALLY_AVAILABLE; +@end + MTR_PROVISIONALLY_AVAILABLE @interface MTRPushAVStreamTransportClusterTransportTriggerOptionsStruct : NSObject @property (nonatomic, copy) NSNumber * _Nonnull triggerType MTR_PROVISIONALLY_AVAILABLE; @@ -2540,6 +2554,8 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy) NSNumber * _Nonnull ingestMethod MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) MTRPushAVStreamTransportClusterContainerOptionsStruct * _Nonnull containerOptions MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nullable expiryTime MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSArray * _Nullable videoStreams MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSArray * _Nullable audioStreams MTR_PROVISIONALLY_AVAILABLE; @end MTR_PROVISIONALLY_AVAILABLE @@ -2561,11 +2577,15 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy) NSNumber * _Nonnull connectionID MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nonnull triggerType MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nullable activationReason MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull containerType MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nullable cmafSessionNumber MTR_PROVISIONALLY_AVAILABLE; @end MTR_PROVISIONALLY_AVAILABLE @interface MTRPushAVStreamTransportClusterPushTransportEndEvent : NSObject @property (nonatomic, copy) NSNumber * _Nonnull connectionID MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull containerType MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nullable cmafSessionNumber MTR_PROVISIONALLY_AVAILABLE; @end MTR_PROVISIONALLY_AVAILABLE @@ -2574,6 +2594,11 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy) NSString * _Nonnull name MTR_PROVISIONALLY_AVAILABLE; @end +MTR_PROVISIONALLY_AVAILABLE +@interface MTRChimeClusterChimeStartedPlayingEvent : NSObject +@property (nonatomic, copy) NSNumber * _Nonnull chimeID MTR_PROVISIONALLY_AVAILABLE; +@end + MTR_PROVISIONALLY_AVAILABLE @interface MTRCommodityTariffClusterPeakPeriodStruct : NSObject @property (nonatomic, copy) NSNumber * _Nonnull severity MTR_PROVISIONALLY_AVAILABLE; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm index 4ca39e3f90d..5af6d190a24 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm @@ -455,6 +455,10 @@ - (instancetype)init _metadataEnabled = @(0); + _videoStreams = nil; + + _audioStreams = nil; + _fabricIndex = @(0); } return self; @@ -471,6 +475,8 @@ - (id)copyWithZone:(NSZone * _Nullable)zone other.videoStreamID = self.videoStreamID; other.audioStreamID = self.audioStreamID; other.metadataEnabled = self.metadataEnabled; + other.videoStreams = self.videoStreams; + other.audioStreams = self.audioStreams; other.fabricIndex = self.fabricIndex; return other; @@ -478,7 +484,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: id:%@; peerNodeID:%@; peerEndpointID:%@; streamUsage:%@; videoStreamID:%@; audioStreamID:%@; metadataEnabled:%@; fabricIndex:%@; >", NSStringFromClass([self class]), _id, _peerNodeID, _peerEndpointID, _streamUsage, _videoStreamID, _audioStreamID, _metadataEnabled, _fabricIndex]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: id:%@; peerNodeID:%@; peerEndpointID:%@; streamUsage:%@; videoStreamID:%@; audioStreamID:%@; metadataEnabled:%@; videoStreams:%@; audioStreams:%@; fabricIndex:%@; >", NSStringFromClass([self class]), _id, _peerNodeID, _peerEndpointID, _streamUsage, _videoStreamID, _audioStreamID, _metadataEnabled, _videoStreams, _audioStreams, _fabricIndex]; return descriptionString; } @@ -10545,6 +10551,66 @@ - (NSString *)description @end +@implementation MTRPushAVStreamTransportClusterAudioStreamStruct +- (instancetype)init +{ + if (self = [super init]) { + + _audioStreamName = @""; + + _audioStreamID = @(0); + } + return self; +} + +- (id)copyWithZone:(NSZone * _Nullable)zone +{ + auto other = [[MTRPushAVStreamTransportClusterAudioStreamStruct alloc] init]; + + other.audioStreamName = self.audioStreamName; + other.audioStreamID = self.audioStreamID; + + return other; +} + +- (NSString *)description +{ + NSString * descriptionString = [NSString stringWithFormat:@"<%@: audioStreamName:%@; audioStreamID:%@; >", NSStringFromClass([self class]), _audioStreamName, _audioStreamID]; + return descriptionString; +} + +@end + +@implementation MTRPushAVStreamTransportClusterVideoStreamStruct +- (instancetype)init +{ + if (self = [super init]) { + + _videoStreamName = @""; + + _videoStreamID = @(0); + } + return self; +} + +- (id)copyWithZone:(NSZone * _Nullable)zone +{ + auto other = [[MTRPushAVStreamTransportClusterVideoStreamStruct alloc] init]; + + other.videoStreamName = self.videoStreamName; + other.videoStreamID = self.videoStreamID; + + return other; +} + +- (NSString *)description +{ + NSString * descriptionString = [NSString stringWithFormat:@"<%@: videoStreamName:%@; videoStreamID:%@; >", NSStringFromClass([self class]), _videoStreamName, _videoStreamID]; + return descriptionString; +} + +@end + @implementation MTRPushAVStreamTransportClusterTransportTriggerOptionsStruct - (instancetype)init { @@ -10684,6 +10750,10 @@ - (instancetype)init _containerOptions = [MTRPushAVStreamTransportClusterContainerOptionsStruct new]; _expiryTime = nil; + + _videoStreams = nil; + + _audioStreams = nil; } return self; } @@ -10701,13 +10771,15 @@ - (id)copyWithZone:(NSZone * _Nullable)zone other.ingestMethod = self.ingestMethod; other.containerOptions = self.containerOptions; other.expiryTime = self.expiryTime; + other.videoStreams = self.videoStreams; + other.audioStreams = self.audioStreams; return other; } - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: streamUsage:%@; videoStreamID:%@; audioStreamID:%@; tlsEndpointID:%@; url:%@; triggerOptions:%@; ingestMethod:%@; containerOptions:%@; expiryTime:%@; >", NSStringFromClass([self class]), _streamUsage, _videoStreamID, _audioStreamID, _tlsEndpointID, _url, _triggerOptions, _ingestMethod, _containerOptions, _expiryTime]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: streamUsage:%@; videoStreamID:%@; audioStreamID:%@; tlsEndpointID:%@; url:%@; triggerOptions:%@; ingestMethod:%@; containerOptions:%@; expiryTime:%@; videoStreams:%@; audioStreams:%@; >", NSStringFromClass([self class]), _streamUsage, _videoStreamID, _audioStreamID, _tlsEndpointID, _url, _triggerOptions, _ingestMethod, _containerOptions, _expiryTime, _videoStreams, _audioStreams]; return descriptionString; } @@ -10789,6 +10861,10 @@ - (instancetype)init _triggerType = @(0); _activationReason = nil; + + _containerType = @(0); + + _cmafSessionNumber = nil; } return self; } @@ -10800,13 +10876,15 @@ - (id)copyWithZone:(NSZone * _Nullable)zone other.connectionID = self.connectionID; other.triggerType = self.triggerType; other.activationReason = self.activationReason; + other.containerType = self.containerType; + other.cmafSessionNumber = self.cmafSessionNumber; return other; } - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: connectionID:%@; triggerType:%@; activationReason:%@; >", NSStringFromClass([self class]), _connectionID, _triggerType, _activationReason]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: connectionID:%@; triggerType:%@; activationReason:%@; containerType:%@; cmafSessionNumber:%@; >", NSStringFromClass([self class]), _connectionID, _triggerType, _activationReason, _containerType, _cmafSessionNumber]; return descriptionString; } @@ -10818,6 +10896,10 @@ - (instancetype)init if (self = [super init]) { _connectionID = @(0); + + _containerType = @(0); + + _cmafSessionNumber = nil; } return self; } @@ -10827,13 +10909,15 @@ - (id)copyWithZone:(NSZone * _Nullable)zone auto other = [[MTRPushAVStreamTransportClusterPushTransportEndEvent alloc] init]; other.connectionID = self.connectionID; + other.containerType = self.containerType; + other.cmafSessionNumber = self.cmafSessionNumber; return other; } - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: connectionID:%@; >", NSStringFromClass([self class]), _connectionID]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: connectionID:%@; containerType:%@; cmafSessionNumber:%@; >", NSStringFromClass([self class]), _connectionID, _containerType, _cmafSessionNumber]; return descriptionString; } @@ -10869,6 +10953,33 @@ - (NSString *)description @end +@implementation MTRChimeClusterChimeStartedPlayingEvent +- (instancetype)init +{ + if (self = [super init]) { + + _chimeID = @(0); + } + return self; +} + +- (id)copyWithZone:(NSZone * _Nullable)zone +{ + auto other = [[MTRChimeClusterChimeStartedPlayingEvent alloc] init]; + + other.chimeID = self.chimeID; + + return other; +} + +- (NSString *)description +{ + NSString * descriptionString = [NSString stringWithFormat:@"<%@: chimeID:%@; >", NSStringFromClass([self class]), _chimeID]; + return descriptionString; +} + +@end + @implementation MTRCommodityTariffClusterPeakPeriodStruct - (instancetype)init { diff --git a/src/lib/core/CHIPConfig.h b/src/lib/core/CHIPConfig.h index 40fe55cbff8..6e5b21a081a 100644 --- a/src/lib/core/CHIPConfig.h +++ b/src/lib/core/CHIPConfig.h @@ -2023,6 +2023,17 @@ extern const char CHIP_NON_PRODUCTION_MARKER[]; #define CHIP_CONFIG_TLS_MAX_ROOT_PER_FABRIC_CERTS_TABLE_SIZE 5 #endif // CHIP_CONFIG_TLS_MAX_ROOT_PER_FABRIC_CERTS_TABLE_SIZE +/** + * @def CHIP_CONFIG_TLS_MAX_PROVISIONED_ENDPOINTS + * + * @brief The default maximum number of TLS endpoints that can be provisioned in the + * TLS Client Management cluster when using the code-driven implementation. The Matter spec + * requires this to be between 5 and 254. Applications can override this by providing a custom delegate. + */ +#ifndef CHIP_CONFIG_TLS_MAX_PROVISIONED_ENDPOINTS +#define CHIP_CONFIG_TLS_MAX_PROVISIONED_ENDPOINTS 5 +#endif // CHIP_CONFIG_TLS_MAX_PROVISIONED_ENDPOINTS + /** * @def CHIP_CONFIG_MAX_NUM_CAMERA_VIDEO_STREAMS * diff --git a/src/lib/dnssd/Advertiser_ImplMinimalMdns.cpp b/src/lib/dnssd/Advertiser_ImplMinimalMdns.cpp index eb0ab008b3a..b3865459f38 100644 --- a/src/lib/dnssd/Advertiser_ImplMinimalMdns.cpp +++ b/src/lib/dnssd/Advertiser_ImplMinimalMdns.cpp @@ -573,6 +573,8 @@ CHIP_ERROR AdvertiserMinMdns::Advertise(const OperationalAdvertisingParameters & AdvertiseRecords(BroadcastAdvertiseType::kStarted); + // This message is used as a marker for when the application process has started. + // It is watched for by the YAML test toolkit. See: scripts/tests/chiptest/test_definition.py ChipLogProgress(Discovery, "mDNS service published: %s.%s", StringOrNullMarker(instanceName.names[1]), StringOrNullMarker(instanceName.names[2])); @@ -779,6 +781,8 @@ CHIP_ERROR AdvertiserMinMdns::Advertise(const CommissionAdvertisingParameters & AdvertiseRecords(BroadcastAdvertiseType::kStarted); + // This message is used as a marker for when the application process has started. + // It is watched for by the YAML test toolkit. See: scripts/tests/chiptest/test_definition.py ChipLogProgress(Discovery, "mDNS service published: %s.%s", StringOrNullMarker(instanceName.names[1]), StringOrNullMarker(instanceName.names[2])); diff --git a/src/lib/dnssd/Discovery_ImplPlatform.cpp b/src/lib/dnssd/Discovery_ImplPlatform.cpp index bea88c0fa0d..7a6e43bc5fb 100644 --- a/src/lib/dnssd/Discovery_ImplPlatform.cpp +++ b/src/lib/dnssd/Discovery_ImplPlatform.cpp @@ -525,6 +525,8 @@ void DiscoveryImplPlatform::HandleDnssdPublish(void * context, const char * type { if (CHIP_NO_ERROR == error) { + // This message is used as a marker for when the application process has started. + // It is watched for by the YAML test toolkit. See: scripts/tests/chiptest/test_definition.py ChipLogProgress(Discovery, "mDNS service published: %s; instance name: %s", StringOrNullMarker(type), StringOrNullMarker(instanceName)); } diff --git a/src/lib/shell/commands/WiFi.cpp b/src/lib/shell/commands/WiFi.cpp index 98fdf274228..8e9eae33345 100644 --- a/src/lib/shell/commands/WiFi.cpp +++ b/src/lib/shell/commands/WiFi.cpp @@ -109,13 +109,22 @@ static CHIP_ERROR WiFiConnectHandler(int argc, char ** argv) VerifyOrReturnError(GetWiFiDriver() != nullptr, CHIP_ERROR_NOT_IMPLEMENTED); - /* Command accepts running with SSID and password as parameters */ - VerifyOrReturnError((argc == 2), CHIP_ERROR_INVALID_ARGUMENT); + /* Command accepts running with SSID and password (optional) as parameters */ + VerifyOrReturnError((argc == 1 || argc == 2), CHIP_ERROR_INVALID_ARGUMENT); - ByteSpan ssidSpan = ByteSpan(Uint8::from_const_char(argv[0]), strlen(argv[0])); - ByteSpan passwordSpan = ByteSpan(Uint8::from_const_char(argv[1]), strlen(argv[1])); - - VerifyOrReturnError(IsSpanUsable(ssidSpan) && IsSpanUsable(passwordSpan), CHIP_ERROR_INVALID_ARGUMENT); + ByteSpan ssidSpan = ByteSpan(Uint8::from_const_char(argv[0]), strlen(argv[0])); + VerifyOrReturnError(!ssidSpan.empty(), CHIP_ERROR_INVALID_ARGUMENT); + ByteSpan passwordSpan; + if (argc == 2) + { + passwordSpan = ByteSpan(Uint8::from_const_char(argv[1]), strlen(argv[1])); + VerifyOrReturnError(!passwordSpan.empty(), CHIP_ERROR_INVALID_ARGUMENT); + } + else + { + // If no password is provided, use an empty password + passwordSpan = ByteSpan(); + } ChipLogProgress(Shell, "Adding/Updating network %s", argv[0]); @@ -150,7 +159,7 @@ void RegisterWiFiCommands() { static constexpr Command subCommands[] = { { &WiFiModeHandler, "mode", "Get/Set wifi mode. Usage: wifi mode [disable|ap|sta]" }, - { &WiFiConnectHandler, "connect", "Connect to AP. Usage: wifi connect " }, + { &WiFiConnectHandler, "connect", "Connect to AP. Usage: wifi connect []" }, { &WiFiDisconnectHandler, "disconnect", "Disconnect device from AP. Usage: wifi disconnect" }, }; diff --git a/src/lib/support/CommonPersistentData.h b/src/lib/support/CommonPersistentData.h index 64056a69dbe..fc98a37f08a 100644 --- a/src/lib/support/CommonPersistentData.h +++ b/src/lib/support/CommonPersistentData.h @@ -31,9 +31,9 @@ inline constexpr uint8_t kdefaultUndefinedEntry = 0; /// @brief Generic class to implement storage of a list persistently /// @tparam EntryType : Type of entry depends on the stored data -/// @tparam kMaxSerializedSize : inherited from PersistentData class +/// @tparam kMaxSerializedSize : inherited from PersistableData template -struct StoredDataList : public PersistentData +struct StoredDataList : public PersistableData { static constexpr TLV::Tag TagFirstEntry() { return TLV::ContextTag(1); } static constexpr TLV::Tag TagEntryCount() { return TLV::ContextTag(2); } diff --git a/src/lib/support/PersistentData.h b/src/lib/support/PersistentData.h index 96c905b590b..69018b91eb1 100644 --- a/src/lib/support/PersistentData.h +++ b/src/lib/support/PersistentData.h @@ -19,9 +19,11 @@ #include #include #include +#include namespace chip { -/// @brief Data accessor allowing data to be persisted by PersistentStore to be accessed + +/// @brief Data that can be persisted via PersistentStorageDelegate in TLV format. struct DataAccessor { virtual ~DataAccessor() = default; @@ -29,72 +31,108 @@ struct DataAccessor virtual CHIP_ERROR Serialize(TLV::TLVWriter & writer) const = 0; virtual CHIP_ERROR Deserialize(TLV::TLVReader & reader) = 0; virtual void Clear() = 0; -}; -/// @brief Interface to PersistentStorageDelegate allowing storage of data of variable size such as TLV, delegating data access -/// to DataAccessor -/// @tparam kMaxSerializedSize size of the mBuffer necessary to retrieve an entry from the storage. Varies with the type of data -/// stored. Will be allocated on the stack so the implementation needs to be aware of this when choosing this value. -template -struct PersistentStore -{ - virtual ~PersistentStore() = default; + /// Non-virtual helper methods /// - CHIP_ERROR Save(const DataAccessor & persistent, PersistentStorageDelegate * storage) + CHIP_ERROR Save(PersistentStorageDelegate * storage, const MutableByteSpan & buffer) const { VerifyOrReturnError(nullptr != storage, CHIP_ERROR_INVALID_ARGUMENT); StorageKeyName key = StorageKeyName::Uninitialized(); - ReturnErrorOnFailure(persistent.UpdateKey(key)); + ReturnErrorOnFailure(this->UpdateKey(key)); // Serialize the data TLV::TLVWriter writer; - writer.Init(mBuffer, sizeof(mBuffer)); - - ReturnErrorOnFailure(persistent.Serialize(writer)); + writer.Init(buffer); + ReturnErrorOnFailure(this->Serialize(writer)); // Save serialized data - return storage->SyncSetKeyValue(key.KeyName(), mBuffer, static_cast(writer.GetLengthWritten())); + return storage->SyncSetKeyValue(key.KeyName(), buffer.data(), static_cast(writer.GetLengthWritten())); } - CHIP_ERROR Load(DataAccessor & persistent, PersistentStorageDelegate * storage) + CHIP_ERROR Load(PersistentStorageDelegate * storage, const MutableByteSpan & buffer) { VerifyOrReturnError(nullptr != storage, CHIP_ERROR_INVALID_ARGUMENT); StorageKeyName key = StorageKeyName::Uninitialized(); - - // Update storage key - ReturnErrorOnFailure(persistent.UpdateKey(key)); + ReturnErrorOnFailure(this->UpdateKey(key)); // Set data to defaults - persistent.Clear(); + this->Clear(); // Load the serialized data - uint16_t size = static_cast(sizeof(mBuffer)); - CHIP_ERROR err = storage->SyncGetKeyValue(key.KeyName(), mBuffer, size); + uint16_t size = (buffer.size() > UINT16_MAX) ? UINT16_MAX : static_cast(buffer.size()); + CHIP_ERROR err = storage->SyncGetKeyValue(key.KeyName(), buffer.data(), size); VerifyOrReturnError(CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND != err, CHIP_ERROR_NOT_FOUND); ReturnErrorOnFailure(err); // Decode serialized data TLV::TLVReader reader; - reader.Init(mBuffer, size); - return persistent.Deserialize(reader); + reader.Init(buffer.data(), size); + return this->Deserialize(reader); } - CHIP_ERROR Delete(DataAccessor & persistent, PersistentStorageDelegate * storage) + CHIP_ERROR Delete(PersistentStorageDelegate * storage) const { VerifyOrReturnError(nullptr != storage, CHIP_ERROR_INVALID_ARGUMENT); StorageKeyName key = StorageKeyName::Uninitialized(); - ReturnErrorOnFailure(persistent.UpdateKey(key)); + ReturnErrorOnFailure(this->UpdateKey(key)); return storage->SyncDeleteKeyValue(key.KeyName()); } +}; + +/// @brief A buffer to be used when loading or serializing persistent data +/// @tparam kMaxSerializedSize size of the buffer necessary to retrieve an entry from the storage. +/// +/// Note: Generic APIs that utilize a persistence buffer should prefer taking +/// a MutableByteSpan, to avoid unnecessarily templating on the buffer size. +template +struct PersistenceBuffer +{ + uint8_t mBuffer[kMaxSerializedSize]; + + // Returns a MutableByteSpan representing this buffer. + MutableByteSpan BufferSpan() { return MutableByteSpan(mBuffer); } +}; + +/// @brief A DataAccessor with a built-in buffer. +/// @tparam kMaxSerializedSize inherited from PersistenceBuffer +/// +/// Note: Unlike `PersistentData` (deprecated), this class does not make the Load/Save/Delete +/// methods virtual. PersistableData objects are not intended to be used polymorphically. +/// It also does not store a PersistentStorageDelegate pointer internally. +template +class PersistableData : public DataAccessor, protected PersistenceBuffer +{ +public: + CHIP_ERROR Save(PersistentStorageDelegate * storage) { return DataAccessor::Save(storage, this->BufferSpan()); } + CHIP_ERROR Load(PersistentStorageDelegate * storage) { return DataAccessor::Load(storage, this->BufferSpan()); } +}; + +///// Deprecated types retained for backward compatibility //////////////////// + +// Deprecated: use PersistenceBuffer and DataAccessor separately +template +struct PersistentStore : public PersistenceBuffer +{ + virtual ~PersistentStore() = default; + + CHIP_ERROR Save(const DataAccessor & persistent, PersistentStorageDelegate * storage) + { + return persistent.Save(storage, this->BufferSpan()); + } + + CHIP_ERROR Load(DataAccessor & persistent, PersistentStorageDelegate * storage) + { + return persistent.Load(storage, this->BufferSpan()); + } - uint8_t mBuffer[kMaxSerializedSize] = { 0 }; + CHIP_ERROR Delete(DataAccessor & persistent, PersistentStorageDelegate * storage) { return persistent.Delete(storage); } }; -/// @brief Combines PersistentStore and DataAccessor +// Deprecated: use PersistableData instead template struct PersistentData : PersistentStore, DataAccessor { diff --git a/src/platform/Ameba/ConnectivityManagerImpl.cpp b/src/platform/Ameba/ConnectivityManagerImpl.cpp index faf4e5d41d7..3c3f7b436cf 100644 --- a/src/platform/Ameba/ConnectivityManagerImpl.cpp +++ b/src/platform/Ameba/ConnectivityManagerImpl.cpp @@ -630,11 +630,6 @@ void ConnectivityManagerImpl::OnStationDisconnected() chip::to_underlying(chip::app::Clusters::WiFiNetworkDiagnostics::ConnectionStatusEnum::kNotConnected)); } - if (reason != RTW_NO_ERROR) - { - NetworkCommissioning::AmebaWiFiDriver::GetInstance().OnConnectWiFiNetworkFailed(reason); - } - UpdateInternetConnectivityState(); } diff --git a/src/platform/Ameba/NetworkCommissioningDriver.h b/src/platform/Ameba/NetworkCommissioningDriver.h index cb7db950536..52beb968cd7 100644 --- a/src/platform/Ameba/NetworkCommissioningDriver.h +++ b/src/platform/Ameba/NetworkCommissioningDriver.h @@ -26,7 +26,7 @@ namespace NetworkCommissioning { namespace { inline constexpr uint8_t kMaxWiFiNetworks = 1; inline constexpr uint8_t kWiFiScanNetworksTimeOutSeconds = 10; -inline constexpr uint8_t kWiFiConnectNetworkTimeoutSeconds = 20; +inline constexpr uint8_t kWiFiConnectNetworkTimeoutSeconds = 35; } // namespace class AmebaScanResponseIterator : public Iterator @@ -111,6 +111,7 @@ class AmebaWiFiDriver final : public WiFiDriver CHIP_ERROR ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, const char * key, uint8_t keyLen); void OnConnectWiFiNetwork(); void OnConnectWiFiNetworkFailed(uint16_t reason); + static void OnConnectWiFiNetworkFailedTimer(chip::System::Layer * aLayer, void * aAppState); void OnScanWiFiNetworkDone(); void OnNetworkStatusChange(); diff --git a/src/platform/Ameba/NetworkCommissioningWiFiDriver.cpp b/src/platform/Ameba/NetworkCommissioningWiFiDriver.cpp index 7edb1525c4d..eb6e2f53be4 100644 --- a/src/platform/Ameba/NetworkCommissioningWiFiDriver.cpp +++ b/src/platform/Ameba/NetworkCommissioningWiFiDriver.cpp @@ -124,6 +124,50 @@ Status AmebaWiFiDriver::ReorderNetwork(ByteSpan networkId, uint8_t index, Mutabl return Status::kSuccess; } +void AmebaWiFiDriver::OnConnectWiFiNetwork() +{ + if (mpConnectCallback) + { + DeviceLayer::SystemLayer().CancelTimer(OnConnectWiFiNetworkFailedTimer, nullptr); + mpConnectCallback->OnResult(Status::kSuccess, CharSpan(), 0); + mpConnectCallback = nullptr; + } +} + +void AmebaWiFiDriver::OnConnectWiFiNetworkFailed(uint16_t reason) +{ + if (mpConnectCallback) + { + Status status; + switch (reason) + { + case RTW_NONE_NETWORK: + status = Status::kNetworkNotFound; + break; + case RTW_CONNECT_FAIL: +#if defined(CONFIG_PLATFORM_8710C) + case RTW_4WAY_HANDSHAKE_TIMEOUT: +#endif + case RTW_WRONG_PASSWORD: + status = Status::kAuthFailure; + break; + case RTW_DHCP_FAIL: + case RTW_UNKNOWN: + default: + status = Status::kUnknownError; + break; + } + mpConnectCallback->OnResult(status, CharSpan(), 0); + mpConnectCallback = nullptr; + } +} + +void AmebaWiFiDriver::OnConnectWiFiNetworkFailedTimer(chip::System::Layer * aLayer, void * aAppState) +{ + matter_wifi_set_autoreconnect(0); + AmebaWiFiDriver::GetInstance().OnConnectWiFiNetworkFailed(RTW_CONNECT_FAIL); +} + CHIP_ERROR AmebaWiFiDriver::ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, const char * key, uint8_t keyLen) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -159,45 +203,11 @@ CHIP_ERROR AmebaWiFiDriver::ConnectWiFiNetwork(const char * ssid, uint8_t ssidLe ConnectivityMgrImpl().ChangeWiFiStationState(state); chip::DeviceLayer::Internal::AmebaUtils::WiFiConnect(ssid, key); }); -#endif - return err; -} - -void AmebaWiFiDriver::OnConnectWiFiNetwork() -{ - if (mpConnectCallback) - { - mpConnectCallback->OnResult(Status::kSuccess, CharSpan(), 0); - mpConnectCallback = nullptr; - } -} -void AmebaWiFiDriver::OnConnectWiFiNetworkFailed(uint16_t reason) -{ - if (mpConnectCallback) - { - Status status; - switch (reason) - { - case RTW_NONE_NETWORK: - status = Status::kNetworkNotFound; - break; - case RTW_CONNECT_FAIL: -#if defined(CONFIG_PLATFORM_8710C) - case RTW_4WAY_HANDSHAKE_TIMEOUT: + err = DeviceLayer::SystemLayer().StartTimer(static_cast(kWiFiConnectNetworkTimeoutSeconds * 1000), + OnConnectWiFiNetworkFailedTimer, nullptr); #endif - case RTW_WRONG_PASSWORD: - status = Status::kAuthFailure; - break; - case RTW_DHCP_FAIL: - case RTW_UNKNOWN: - default: - status = Status::kUnknownError; - break; - } - mpConnectCallback->OnResult(status, CharSpan(), 0); - mpConnectCallback = nullptr; - } + return err; } void AmebaWiFiDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * callback) diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn index 0ebb492b453..195118d71ec 100644 --- a/src/platform/BUILD.gn +++ b/src/platform/BUILD.gn @@ -235,12 +235,6 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { "CHIP_DEVICE_LAYER_TARGET=${nxp_device_layer}", "CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE=${chip_enable_ble}", ] - } else if (chip_device_platform == "nxp_zephyr") { - device_layer_target_define = "NXP_ZEPHYR" - defines += [ - "CHIP_DEVICE_LAYER_TARGET_NXP_ZEPHYR=1", - "CHIP_DEVICE_LAYER_TARGET=nxp/zephyr", - ] } else if (chip_device_platform == "telink") { device_layer_target_define = "TELINK" defines += [ "CHIP_DEVICE_LAYER_TARGET=telink" ] @@ -347,7 +341,6 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { "NRFCONNECT", "QPG", "NXP", - "NXP_ZEPHYR", "TELINK", "BL602", "BL616", @@ -598,8 +591,6 @@ if (chip_device_platform != "none") { _platform_target = "qpg" } else if (chip_device_platform == "nxp") { _platform_target = "nxp/${nxp_platform}:nxp_platform" - } else if (chip_device_platform == "nxp_zephyr") { - _platform_target = "nxp/zephyr:nxp_zephyr" } else if (chip_device_platform == "telink") { _platform_target = "telink" } else if (chip_device_platform == "tizen") { diff --git a/src/platform/ESP32/CHIPDevicePlatformConfig.h b/src/platform/ESP32/CHIPDevicePlatformConfig.h index 03103832a95..ae8acec4568 100644 --- a/src/platform/ESP32/CHIPDevicePlatformConfig.h +++ b/src/platform/ESP32/CHIPDevicePlatformConfig.h @@ -106,8 +106,17 @@ #define CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX #define CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN #define CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX +#ifdef CONFIG_CHIPOBLE_SINGLE_CONNECTION #define CHIP_DEVICE_CONFIG_CHIPOBLE_SINGLE_CONNECTION CONFIG_CHIPOBLE_SINGLE_CONNECTION +#else +#define CHIP_DEVICE_CONFIG_CHIPOBLE_SINGLE_CONNECTION 0 +#endif + +#ifdef CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART #define CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART +#else +#define CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART 0 +#endif #ifdef CONFIG_ENABLE_TEST_SETUP_PARAMS #define CHIP_DEVICE_CONFIG_ENABLE_TEST_SETUP_PARAMS 1 @@ -136,10 +145,22 @@ #define CHIP_DEVICE_CONFIG_CHIP_CONFIG_NAMESPACE_PARTITION CONFIG_CHIP_CONFIG_NAMESPACE_PARTITION_LABEL #define CHIP_DEVICE_CONFIG_CHIP_COUNTERS_NAMESPACE_PARTITION CONFIG_CHIP_COUNTERS_NAMESPACE_PARTITION_LABEL #define CHIP_DEVICE_CONFIG_CHIP_KVS_NAMESPACE_PARTITION CONFIG_CHIP_KVS_NAMESPACE_PARTITION_LABEL +#ifdef CONFIG_ENABLE_ESP32_DEVICE_INSTANCE_INFO_PROVIDER #define CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER CONFIG_ENABLE_ESP32_DEVICE_INSTANCE_INFO_PROVIDER +#else +#define CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER 0 +#endif #define CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS CONFIG_CHIP_DISCOVERY_TIMEOUT_SECS +#ifdef CONFIG_ENABLE_ESP32_BLE_CONTROLLER #define CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE CONFIG_ENABLE_ESP32_BLE_CONTROLLER +#else +#define CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE 0 +#endif +#ifdef CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART #define CHIP_DEVICE_CONFIG_ENABLE_PAIRING_AUTOSTART CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART +#else +#define CHIP_DEVICE_CONFIG_ENABLE_PAIRING_AUTOSTART 0 +#endif #ifdef CONFIG_ENABLE_BLE_EXT_ANNOUNCEMENT #define CHIP_DEVICE_CONFIG_EXT_ADVERTISING CONFIG_ENABLE_BLE_EXT_ANNOUNCEMENT diff --git a/src/platform/ESP32/CHIPPlatformConfig.h b/src/platform/ESP32/CHIPPlatformConfig.h index 5dc9bf1fde7..92dbcbdf317 100644 --- a/src/platform/ESP32/CHIPPlatformConfig.h +++ b/src/platform/ESP32/CHIPPlatformConfig.h @@ -158,3 +158,7 @@ #else #define CHIP_SYSTEM_CONFIG_POOL_USE_HEAP 0 #endif + +#ifdef CONFIG_MAX_LARGE_BUFFER_SIZE_BYTES +#define CHIP_SYSTEM_CONFIG_MAX_LARGE_BUFFER_SIZE_BYTES CONFIG_MAX_LARGE_BUFFER_SIZE_BYTES +#endif diff --git a/src/platform/ESP32/ESP32Utils.cpp b/src/platform/ESP32/ESP32Utils.cpp index bf6fd631769..70a20b98e25 100644 --- a/src/platform/ESP32/ESP32Utils.cpp +++ b/src/platform/ESP32/ESP32Utils.cpp @@ -248,9 +248,20 @@ CHIP_ERROR ESP32Utils::ClearWiFiStationProvision(void) { wifi_config_t stationConfig; + esp_err_t err = esp_wifi_disconnect(); + if (err != ESP_OK) + { + ChipLogProgress(DeviceLayer, "esp_wifi_disconnect() failed: %s", esp_err_to_name(err)); + // Does not return error here as we just call esp_wifi_disconnect() to ensure that the Wi-Fi is not connecting. + } // Clear the ESP WiFi station configuration. memset(&stationConfig, 0, sizeof(stationConfig)); - esp_wifi_set_config(WIFI_IF_STA, &stationConfig); + err = esp_wifi_set_config(WIFI_IF_STA, &stationConfig); + if (err != ESP_OK) + { + ChipLogError(DeviceLayer, "esp_wifi_set_config() failed: %s", esp_err_to_name(err)); + return MapError(err); + } return CHIP_NO_ERROR; } diff --git a/src/platform/ESP32/NetworkCommissioningDriver.cpp b/src/platform/ESP32/NetworkCommissioningDriver.cpp index 113f426aea6..ccd09021b4f 100644 --- a/src/platform/ESP32/NetworkCommissioningDriver.cpp +++ b/src/platform/ESP32/NetworkCommissioningDriver.cpp @@ -224,22 +224,14 @@ Status ESPWiFiDriver::ReorderNetwork(ByteSpan networkId, uint8_t index, MutableC CHIP_ERROR ESPWiFiDriver::ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, const char * key, uint8_t keyLen) { - // If device is already connected to WiFi, then disconnect the WiFi, - // clear the WiFi configurations and add the newly provided WiFi configurations. + // Clear the WiFi configurations and add the newly provided WiFi configurations. if (chip::DeviceLayer::Internal::ESP32Utils::IsStationProvisioned()) { - ChipLogProgress(DeviceLayer, "Disconnecting WiFi station interface"); - esp_err_t err = esp_wifi_disconnect(); - if (err != ESP_OK) - { - ChipLogError(DeviceLayer, "esp_wifi_disconnect() failed: %s", esp_err_to_name(err)); - return chip::DeviceLayer::Internal::ESP32Utils::MapError(err); - } CHIP_ERROR error = chip::DeviceLayer::Internal::ESP32Utils::ClearWiFiStationProvision(); if (error != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "ClearWiFiStationProvision failed: %" CHIP_ERROR_FORMAT, error.Format()); - return chip::DeviceLayer::Internal::ESP32Utils::MapError(err); + return error; } } @@ -260,7 +252,6 @@ CHIP_ERROR ESPWiFiDriver::ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, return chip::DeviceLayer::Internal::ESP32Utils::MapError(err); } - ReturnErrorOnFailure(ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Disabled)); return ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Enabled); } @@ -290,7 +281,23 @@ void ESPWiFiDriver::OnConnectWiFiNetworkFailed() { if (mpConnectCallback) { - mpConnectCallback->OnResult(Status::kNetworkNotFound, CharSpan(), 0); + Status status = Status::kOtherConnectionFailure; + switch (mLastDisconnectedReason) + { + case WIFI_REASON_AUTH_FAIL: + case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: + case WIFI_REASON_HANDSHAKE_TIMEOUT: + case WIFI_REASON_MIC_FAILURE: + case WIFI_REASON_CONNECTION_FAIL: + status = Status::kAuthFailure; + break; + case WIFI_REASON_NO_AP_FOUND: + status = Status::kNetworkNotFound; + break; + default: + break; + } + mpConnectCallback->OnResult(status, CharSpan(), 0); mpConnectCallback = nullptr; } } @@ -360,7 +367,7 @@ CHIP_ERROR ESPWiFiDriver::StartScanWiFiNetworks(ByteSpan ssid) } else { - err = esp_wifi_scan_start(NULL, false); + err = esp_wifi_scan_start(nullptr, false); } if (err != ESP_OK) { diff --git a/src/platform/ESP32/SystemPlatformConfig.h b/src/platform/ESP32/SystemPlatformConfig.h index 8606c505279..2b82d1ad073 100644 --- a/src/platform/ESP32/SystemPlatformConfig.h +++ b/src/platform/ESP32/SystemPlatformConfig.h @@ -47,3 +47,7 @@ struct ChipDeviceEvent; #ifndef CHIP_SYSTEM_CONFIG_NUM_TIMERS #define CHIP_SYSTEM_CONFIG_NUM_TIMERS CONFIG_NUM_TIMERS #endif // CHIP_SYSTEM_CONFIG_NUM_TIMERS + +#ifdef CONFIG_USE_LWIP_PBUF_RAM_PACKETBUFFER +#define CHIP_SYSTEM_CONFIG_PACKETBUFFER_LWIP_PBUF_RAM CONFIG_USE_LWIP_PBUF_RAM_PACKETBUFFER +#endif // CONFIG_USE_LWIP_PBUF_RAM_PACKETBUFFER diff --git a/src/platform/Zephyr/BUILD.gn b/src/platform/Zephyr/BUILD.gn index 024ae636c83..23f1a81f71e 100644 --- a/src/platform/Zephyr/BUILD.gn +++ b/src/platform/Zephyr/BUILD.gn @@ -36,9 +36,9 @@ static_library("Zephyr") { "ConfigurationManagerImpl.h", "ConnectivityManagerImpl.cpp", "ConnectivityManagerImpl.h", + "DeviceInstanceInfoProviderImpl.cpp", "DiagnosticDataProviderImpl.cpp", "DiagnosticDataProviderImpl.h", - "DiagnosticDataProviderImplGetter.cpp", "InetPlatformConfig.h", "InetUtils.cpp", "KeyValueStoreManagerImpl.cpp", @@ -77,10 +77,34 @@ static_library("Zephyr") { } } + if (chip_enable_wifi) { + sources += [ + "wifi/ConnectivityManagerImplWiFi.cpp", + "wifi/ConnectivityManagerImplWiFi.h", + "wifi/DiagnosticDataProviderImplWiFi.cpp", + "wifi/DiagnosticDataProviderImplWiFi.h", + "wifi/WiFiManager.cpp", + "wifi/WiFiManager.h", + "wifi/ZephyrWifiDriver.cpp", + "wifi/ZephyrWifiDriver.h", + ] + } else { + # Non-WiFi builds use the base diagnostic provider getter. + # Wi-Fi implementation provides its own. + sources += [ "DiagnosticDataProviderImplGetter.cpp" ] + } + if (chip_malloc_sys_heap) { sources += [ "SysHeapMalloc.cpp" ] } + if (chip_enable_ota_requestor) { + sources += [ + "OTAImageProcessorImpl.cpp", + "OTAImageProcessorImpl.h", + ] + } + cflags = [ "-Wconversion" ] } diff --git a/src/platform/Zephyr/CHIPDevicePlatformConfig.h b/src/platform/Zephyr/CHIPDevicePlatformConfig.h index 3c855a74374..47eeae2b2ca 100644 --- a/src/platform/Zephyr/CHIPDevicePlatformConfig.h +++ b/src/platform/Zephyr/CHIPDevicePlatformConfig.h @@ -31,10 +31,26 @@ #define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID CONFIG_CHIP_DEVICE_VENDOR_ID #endif +#ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME +#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME CONFIG_CHIP_DEVICE_VENDOR_NAME +#endif + #ifndef CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID #define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID CONFIG_CHIP_DEVICE_PRODUCT_ID #endif +#ifndef CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME +#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME CONFIG_CHIP_DEVICE_PRODUCT_NAME +#endif + +#ifndef CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION +#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION CONFIG_CHIP_DEVICE_HARDWARE_VERSION +#endif + +#ifndef CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING +#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING CONFIG_CHIP_DEVICE_HARDWARE_VERSION_STRING +#endif + #ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION #define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION CONFIG_CHIP_DEVICE_SOFTWARE_VERSION #endif @@ -43,8 +59,33 @@ #define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING CONFIG_CHIP_DEVICE_SOFTWARE_VERSION_STRING #endif -#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION 0 -#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP 0 +#ifndef CHIP_DEVICE_CONFIG_TEST_MANUFACTURING_DATE +#define CHIP_DEVICE_CONFIG_TEST_MANUFACTURING_DATE CONFIG_CHIP_DEVICE_MANUFACTURING_DATE +#endif + +#ifndef CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER +#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER CONFIG_CHIP_DEVICE_SERIAL_NUMBER +#endif + +#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR +#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR CONFIG_CHIP_DEVICE_DISCRIMINATOR +#endif + +#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE +#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE +#endif + +#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT +#define CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT CONFIG_CHIP_DEVICE_SPAKE2_IT +#endif + +#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT +#define CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT CONFIG_CHIP_DEVICE_SPAKE2_SALT +#endif + +#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER +#define CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER CONFIG_CHIP_DEVICE_SPAKE2_TEST_VERIFIER +#endif // Check if Zephyr app use NET_L2_OPENTHREAD #ifndef CHIP_DEVICE_CONFIG_ENABLE_THREAD @@ -72,6 +113,23 @@ #define CHIP_DEVICE_CONFIG_ENABLE_WIFI 0 #endif // CONFIG_WIFI #endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI + +#ifndef CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION +#ifdef CONFIG_CHIP_ENABLE_WIFI_STATION +#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION 1 +#else +#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION 0 +#endif // CONFIG_CHIP_ENABLE_WIFI_STATION +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION + +#ifndef CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP +#ifdef CONFIG_CHIP_ENABLE_WIFI_AP +#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP 1 +#else +#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP 0 +#endif // CONFIG_CHIP_ENABLE_WIFI_AP +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP + // Check if Zephyr app use NET_L2_ETHERNET #ifndef CHIP_DEVICE_CONFIG_ENABLE_ETHERNET @@ -121,13 +179,17 @@ // ========== Platform-specific Configuration Overrides ========= #ifndef CHIP_DEVICE_CONFIG_CHIP_TASK_PRIORITY -#define CHIP_DEVICE_CONFIG_CHIP_TASK_PRIORITY (K_PRIO_PREEMPT(1)) +#define CHIP_DEVICE_CONFIG_CHIP_TASK_PRIORITY (K_PRIO_PREEMPT(CONFIG_CHIP_TASK_PRIORITY)) #endif // CHIP_DEVICE_CONFIG_CHIP_TASK_PRIORITY #ifndef CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE -#define CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE 8192 +#define CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE CONFIG_CHIP_TASK_STACK_SIZE #endif // CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE +#ifndef CHIP_DEVICE_CONFIG_MAX_EVENT_QUEUE_SIZE +#define CHIP_DEVICE_CONFIG_MAX_EVENT_QUEUE_SIZE CONFIG_MAX_EVENT_QUEUE_SIZE +#endif // CHIP_DEVICE_CONFIG_MAX_EVENT_QUEUE_SIZE + #define CHIP_DEVICE_CONFIG_ENABLE_WIFI_TELEMETRY 0 #define CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY 0 #define CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY_FULL 0 @@ -150,9 +212,25 @@ #ifdef CONFIG_CHIP_ENABLE_ICD_SUPPORT #define CHIP_DEVICE_CONFIG_ENABLE_SED 1 +#ifdef CONFIG_CHIP_THREAD_SSED #define CHIP_DEVICE_CONFIG_THREAD_SSED CONFIG_CHIP_THREAD_SSED +#else +#define CHIP_DEVICE_CONFIG_THREAD_SSED 0 +#endif // CONFIG_CHIP_THREAD_SSED #endif // CONFIG_CHIP_ENABLE_ICD_SUPPORT +#ifndef CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL +#ifdef CONFIG_CHIP_ICD_SLOW_POLL_INTERVAL +#define CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL chip::System::Clock::Milliseconds32(CONFIG_CHIP_ICD_SLOW_POLL_INTERVAL) +#endif // CONFIG_CHIP_ICD_SLOW_POLL_INTERVAL +#endif // CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL + +#ifndef CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL +#ifdef CONFIG_CHIP_ICD_FAST_POLLING_INTERVAL +#define CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL chip::System::Clock::Milliseconds32(CONFIG_CHIP_ICD_FAST_POLLING_INTERVAL) +#endif // CONFIG_CHIP_ICD_FAST_POLLING_INTERVAL +#endif // CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL + #ifdef CONFIG_CHIP_COMMISSIONABLE_DEVICE_TYPE #define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONABLE_DEVICE_TYPE 1 #endif // CONFIG_CHIP_COMMISSIONABLE_DEVICE_TYPE @@ -170,3 +248,7 @@ #endif // CONFIG_CHIP_BLE_EXT_ADVERTISING #define CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS (CONFIG_CHIP_BLE_ADVERTISING_DURATION * 60) + +#ifndef CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID_LENGTH +#define CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID_LENGTH ((sizeof(CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID) - 1) / 2) +#endif // CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID_LENGTH diff --git a/src/platform/Zephyr/CHIPPlatformConfig.h b/src/platform/Zephyr/CHIPPlatformConfig.h index aabad7a57a2..ccf4cec776e 100644 --- a/src/platform/Zephyr/CHIPPlatformConfig.h +++ b/src/platform/Zephyr/CHIPPlatformConfig.h @@ -23,6 +23,10 @@ #pragma once +#ifdef CONFIG_CHIP_CRYPTO_PSA +#include +#endif + // ==================== General Platform Adaptations ==================== #define CHIP_CONFIG_ABORT() abort() @@ -32,6 +36,13 @@ #define CHIP_CONFIG_LIFETIIME_PERSISTED_COUNTER_KEY "rc" +// ==================== Security Adaptations ==================== + +#ifdef CONFIG_CHIP_CRYPTO_PSA +#define CHIP_CONFIG_SHA256_CONTEXT_SIZE sizeof(psa_hash_operation_t) +#define CHIP_CONFIG_SHA256_CONTEXT_ALIGN psa_hash_operation_t +#endif + // ==================== General Configuration Overrides ==================== #ifndef CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS @@ -46,6 +57,31 @@ #define CHIP_LOG_FILTERING 0 #endif // CHIP_LOG_FILTERING +#ifdef CONFIG_CHIP_LOG_SIZE_OPTIMIZATION +// Disable some of the too detailed log modules to save flash +#define CHIP_CONFIG_LOG_MODULE_ExchangeManager_DETAIL 0 +#define CHIP_CONFIG_LOG_MODULE_Crypto_DETAIL 0 +#define CHIP_CONFIG_LOG_MODULE_Crypto_PROGRESS 0 +#define CHIP_CONFIG_LOG_MODULE_BDX_DETAIL 0 +#define CHIP_CONFIG_LOG_MODULE_BDX_PROGRESS 0 +#define CHIP_CONFIG_LOG_MODULE_EventLogging_DETAIL 0 +#define CHIP_CONFIG_LOG_MODULE_EventLogging_PROGRESS 0 +#define CHIP_CONFIG_LOG_MODULE_SetupPayload_DETAIL 0 +#define CHIP_CONFIG_LOG_MODULE_SetupPayload_PROGRESS 0 +#define CHIP_CONFIG_LOG_MODULE_CASESessionManager_DETAIL 0 +#define CHIP_CONFIG_LOG_MODULE_CASESessionManager_PROGRESS 0 +#define CHIP_CONFIG_LOG_MODULE_DataManagement_DETAIL 0 +#define CHIP_CONFIG_LOG_MODULE_FabricProvisioning_DETAIL 0 +#define CHIP_CONFIG_LOG_MODULE_chipSystemLayer_DETAIL 0 +#define CHIP_CONFIG_LOG_MODULE_chipSystemLayer_PROGRESS 0 +#define CHIP_CONFIG_LOG_MODULE_Zcl_DETAIL 0 +#define CHIP_CONFIG_LOG_MODULE_SecureChannel_DETAIL 0 +#define CHIP_CONFIG_LOG_MODULE_Ble_DETAIL 0 +#define CHIP_CONFIG_LOG_MODULE_AppServer_DETAIL 0 +#define CHIP_CONFIG_LOG_MODULE_Support_DETAIL 0 +#define CHIP_CONFIG_LOG_MODULE_Support_PROGRESS 0 +#endif + #ifndef CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS #define CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS 1 #endif // CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS @@ -58,3 +94,40 @@ #define CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKET_EXTENSIONS 0 #endif + +// Set MRP retry intervals for Thread and Wi-Fi to test-proven values. +#ifndef CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL +#ifdef CONFIG_CHIP_MRP_LOCAL_ACTIVE_RETRY_INTERVAL +#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL chip::System::Clock::Milliseconds32(CONFIG_CHIP_MRP_LOCAL_ACTIVE_RETRY_INTERVAL) +#endif // CONFIG_CHIP_MRP_LOCAL_ACTIVE_RETRY_INTERVAL +#endif // CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL + +#ifndef CHIP_CONFIG_MRP_LOCAL_IDLE_RETRY_INTERVAL +#ifdef CONFIG_CHIP_MRP_LOCAL_IDLE_RETRY_INTERVAL +#define CHIP_CONFIG_MRP_LOCAL_IDLE_RETRY_INTERVAL chip::System::Clock::Milliseconds32(CONFIG_CHIP_MRP_LOCAL_IDLE_RETRY_INTERVAL) +#endif // CONFIG_CHIP_MRP_LOCAL_IDLE_RETRY_INTERVAL +#endif // CHIP_CONFIG_MRP_LOCAL_IDLE_RETRY_INTERVAL + +#ifndef CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC +#ifdef CONFIG_CHIP_ICD_IDLE_MODE_DURATION +#define CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC CONFIG_CHIP_ICD_IDLE_MODE_DURATION +#endif // CONFIG_CHIP_ICD_IDLE_MODE_DURATION +#endif // CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC + +#ifndef CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS +#ifdef CONFIG_CHIP_ICD_ACTIVE_MODE_DURATION +#define CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS CONFIG_CHIP_ICD_ACTIVE_MODE_DURATION +#endif // CONFIG_CHIP_ICD_ACTIVE_MODE_DURATION +#endif // CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS + +#ifndef CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS +#ifdef CONFIG_CHIP_ICD_ACTIVE_MODE_THRESHOLD +#define CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS CONFIG_CHIP_ICD_ACTIVE_MODE_THRESHOLD +#endif // CONFIG_CHIP_ICD_ACTIVE_MODE_THRESHOLD +#endif // CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS + +#ifndef CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC +#ifdef CONFIG_CHIP_ICD_CLIENTS_PER_FABRIC +#define CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC CONFIG_CHIP_ICD_CLIENTS_PER_FABRIC +#endif // CONFIG_CHIP_ICD_CLIENTS_PER_FABRIC +#endif // CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC diff --git a/src/platform/Zephyr/ConnectivityManagerImpl.h b/src/platform/Zephyr/ConnectivityManagerImpl.h index 0a607701570..7542846b6c4 100644 --- a/src/platform/Zephyr/ConnectivityManagerImpl.h +++ b/src/platform/Zephyr/ConnectivityManagerImpl.h @@ -33,7 +33,12 @@ #else #include #endif + +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI +#include +#else #include +#endif #include @@ -65,7 +70,11 @@ class ConnectivityManagerImpl final : public ConnectivityManager, #else public Internal::GenericConnectivityManagerImpl_NoThread, #endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI + public ConnectivityManagerImplWiFi +#else public Internal::GenericConnectivityManagerImpl_NoWiFi +#endif { // Allow the ConnectivityManager interface class to delegate method calls to // the implementation methods provided by this class. diff --git a/src/platform/nxp/zephyr/DeviceInstanceInfoProviderImpl.cpp b/src/platform/Zephyr/DeviceInstanceInfoProviderImpl.cpp similarity index 97% rename from src/platform/nxp/zephyr/DeviceInstanceInfoProviderImpl.cpp rename to src/platform/Zephyr/DeviceInstanceInfoProviderImpl.cpp index 52d0fc65ad1..78326a03f13 100644 --- a/src/platform/nxp/zephyr/DeviceInstanceInfoProviderImpl.cpp +++ b/src/platform/Zephyr/DeviceInstanceInfoProviderImpl.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2024 Project CHIP Authors + * Copyright (c) 2025 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/platform/nxp/zephyr/DeviceInstanceInfoProviderImpl.h b/src/platform/Zephyr/DeviceInstanceInfoProviderImpl.h similarity index 93% rename from src/platform/nxp/zephyr/DeviceInstanceInfoProviderImpl.h rename to src/platform/Zephyr/DeviceInstanceInfoProviderImpl.h index 31cc98bfaa2..e30b9f90f52 100644 --- a/src/platform/nxp/zephyr/DeviceInstanceInfoProviderImpl.h +++ b/src/platform/Zephyr/DeviceInstanceInfoProviderImpl.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2024 Project CHIP Authors + * Copyright (c) 2025 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,8 +18,8 @@ #pragma once +#include #include -#include namespace chip { namespace DeviceLayer { diff --git a/src/platform/nxp/zephyr/ota/OTAImageProcessorImpl.cpp b/src/platform/Zephyr/OTAImageProcessorImpl.cpp similarity index 91% rename from src/platform/nxp/zephyr/ota/OTAImageProcessorImpl.cpp rename to src/platform/Zephyr/OTAImageProcessorImpl.cpp index dfaa5ee5a05..279cae475ff 100644 --- a/src/platform/nxp/zephyr/ota/OTAImageProcessorImpl.cpp +++ b/src/platform/Zephyr/OTAImageProcessorImpl.cpp @@ -22,19 +22,14 @@ #include #include #include -#include #include -static struct stream_flash_ctx stream; - #ifdef CONFIG_CHIP_OTA_REQUEST_UPGRADE_PERMANENT #define UPDATE_TYPE BOOT_UPGRADE_PERMANENT #else #define UPDATE_TYPE BOOT_UPGRADE_TEST #endif -static constexpr uint16_t deltaRebootDelayMs = 200; - static chip::OTAImageProcessorImpl gImageProcessor; namespace chip { @@ -54,7 +49,8 @@ CHIP_ERROR OTAImageProcessorImpl::PrepareDownload() { VerifyOrReturnError(mDownloader != nullptr, CHIP_ERROR_INCORRECT_STATE); - return DeviceLayer::SystemLayer().ScheduleLambda([this] { mDownloader->OnPreparedForDownload(PrepareDownloadImpl()); }); + return DeviceLayer::SystemLayer().ScheduleLambda( + [this] { TEMPORARY_RETURN_IGNORED mDownloader->OnPreparedForDownload(PrepareDownloadImpl()); }); } CHIP_ERROR OTAImageProcessorImpl::PrepareDownloadImpl() @@ -71,7 +67,7 @@ CHIP_ERROR OTAImageProcessorImpl::PrepareDownloadImpl() return System::MapErrorZephyr(-EFAULT); } - int err = stream_flash_init(&stream, flash_dev, mBuffer, sizeof(mBuffer), FIXED_PARTITION_OFFSET(slot1_partition), + int err = stream_flash_init(&mStream, flash_dev, mBuffer, sizeof(mBuffer), FIXED_PARTITION_OFFSET(slot1_partition), FIXED_PARTITION_SIZE(slot1_partition), NULL); if (err) @@ -84,7 +80,7 @@ CHIP_ERROR OTAImageProcessorImpl::PrepareDownloadImpl() CHIP_ERROR OTAImageProcessorImpl::Finalize() { - int err = stream_flash_buffered_write(&stream, NULL, 0, true); + int err = stream_flash_buffered_write(&mStream, NULL, 0, true); if (err) { @@ -117,7 +113,7 @@ CHIP_ERROR OTAImageProcessorImpl::Apply() */ ChipLogProgress(SoftwareUpdate, "Restarting device, will reboot in %d seconds ...", mDelayBeforeRebootSec); return SystemLayer().StartTimer( - System::Clock::Milliseconds32(mDelayBeforeRebootSec * 1000 + deltaRebootDelayMs), + System::Clock::Milliseconds32(mDelayBeforeRebootSec * 1000 + kDeltaRebootDelayMs), [](System::Layer *, void * /* context */) { k_msleep(CHIP_DEVICE_CONFIG_SERVER_SHUTDOWN_ACTIONS_SLEEP_MS); sys_reboot(SYS_REBOOT_WARM); @@ -141,7 +137,7 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & aBlock) if (error == CHIP_NO_ERROR) { - error = System::MapErrorZephyr(stream_flash_buffered_write(&stream, aBlock.data(), aBlock.size(), false)); + error = System::MapErrorZephyr(stream_flash_buffered_write(&mStream, aBlock.data(), aBlock.size(), false)); mParams.downloadedBytes += aBlock.size(); } @@ -151,7 +147,7 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & aBlock) { ChipLogDetail(SoftwareUpdate, "Downloaded %u/%u bytes", static_cast(mParams.downloadedBytes), static_cast(mParams.totalFileBytes)); - mDownloader->FetchNextData(); + TEMPORARY_RETURN_IGNORED mDownloader->FetchNextData(); } else { diff --git a/src/platform/nxp/zephyr/ota/OTAImageProcessorImpl.h b/src/platform/Zephyr/OTAImageProcessorImpl.h similarity index 92% rename from src/platform/nxp/zephyr/ota/OTAImageProcessorImpl.h rename to src/platform/Zephyr/OTAImageProcessorImpl.h index b369d29007c..bba0f9b9972 100644 --- a/src/platform/nxp/zephyr/ota/OTAImageProcessorImpl.h +++ b/src/platform/Zephyr/OTAImageProcessorImpl.h @@ -20,6 +20,8 @@ #include #include +#include + namespace chip { class OTADownloader; @@ -51,6 +53,8 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface OTADownloader * mDownloader = nullptr; OTAImageHeaderParser mHeaderParser; uint8_t mBuffer[kBufferSize]; + struct stream_flash_ctx mStream; + static constexpr uint16_t kDeltaRebootDelayMs = 200; }; } // namespace chip diff --git a/src/platform/Zephyr/SystemPlatformConfig.h b/src/platform/Zephyr/SystemPlatformConfig.h index 0ea9af8c3b0..42a96d857eb 100644 --- a/src/platform/Zephyr/SystemPlatformConfig.h +++ b/src/platform/Zephyr/SystemPlatformConfig.h @@ -47,4 +47,20 @@ struct ChipDeviceEvent; #define CHIP_SYSTEM_CONFIG_USE_LWIP 0 #define CHIP_SYSTEM_CONFIG_USE_SOCKETS 1 +#ifndef CHIP_SYSTEM_CONFIG_THREAD_LOCAL_STORAGE +#ifdef CONFIG_CHIP_SYSTEM_THREAD_LOCAL_STORAGE +#define CHIP_SYSTEM_CONFIG_THREAD_LOCAL_STORAGE CONFIG_CHIP_SYSTEM_THREAD_LOCAL_STORAGE +#else +#define CHIP_SYSTEM_CONFIG_THREAD_LOCAL_STORAGE 0 +#endif // CONFIG_CHIP_SYSTEM_THREAD_LOCAL_STORAGE +#endif // CHIP_SYSTEM_CONFIG_THREAD_LOCAL_STORAGE + +#ifndef CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKET_EXTENSIONS +#ifdef CONFIG_CHIP_SYSTEM_USE_ZEPHYR_SOCKET_EXTENSIONS +#define CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKET_EXTENSIONS CONFIG_CHIP_SYSTEM_USE_ZEPHYR_SOCKET_EXTENSIONS +#else +#define CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKET_EXTENSIONS 0 +#endif // CONFIG_CHIP_SYSTEM_USE_ZEPHYR_SOCKET_EXTENSIONS +#endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKET_EXTENSIONS + // ========== Platform-specific Configuration Overrides ========= diff --git a/src/platform/Zephyr/wifi/DiagnosticDataProviderImplWiFi.cpp b/src/platform/Zephyr/wifi/DiagnosticDataProviderImplWiFi.cpp new file mode 100644 index 00000000000..979ba9eae25 --- /dev/null +++ b/src/platform/Zephyr/wifi/DiagnosticDataProviderImplWiFi.cpp @@ -0,0 +1,168 @@ +/* + * + * Copyright (c) 2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Provides an implementation of Wi-Fi network diagnostics methods of the DiagnosticDataProvider object. + */ + +#include +#include +#include + +namespace chip { +namespace DeviceLayer { + +DiagnosticDataProvider & GetDiagnosticDataProviderImpl() +{ + return DiagnosticDataProviderImplWiFi::GetDefaultInstance(); +} + +DiagnosticDataProviderImplWiFi & DiagnosticDataProviderImplWiFi::GetDefaultInstance() +{ + static DiagnosticDataProviderImplWiFi sInstance; + return sInstance; +} + +CHIP_ERROR DiagnosticDataProviderImplWiFi::GetWiFiBssId(MutableByteSpan & value) +{ + WiFiManager::WiFiInfo info; + ReturnErrorOnFailure(WiFiManager::Instance().GetWiFiInfo(info)); + VerifyOrReturnError(sizeof(info.mBssId) >= value.size(), CHIP_ERROR_BUFFER_TOO_SMALL); + + memcpy(value.data(), info.mBssId, sizeof(info.mBssId)); + value.reduce_size(sizeof(info.mBssId)); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR +DiagnosticDataProviderImplWiFi::GetWiFiSecurityType(app::Clusters::WiFiNetworkDiagnostics::SecurityTypeEnum & securityType) +{ + using app::Clusters::WiFiNetworkDiagnostics::SecurityTypeEnum; + + WiFiManager::WiFiInfo info; + ReturnErrorOnFailure(WiFiManager::Instance().GetWiFiInfo(info)); + securityType = info.mSecurityType; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImplWiFi::GetWiFiVersion(app::Clusters::WiFiNetworkDiagnostics::WiFiVersionEnum & wiFiVersion) +{ + WiFiManager::WiFiInfo info; + ReturnErrorOnFailure(WiFiManager::Instance().GetWiFiInfo(info)); + wiFiVersion = info.mWiFiVersion; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImplWiFi::GetWiFiChannelNumber(uint16_t & channelNumber) +{ + WiFiManager::WiFiInfo info; + ReturnErrorOnFailure(WiFiManager::Instance().GetWiFiInfo(info)); + channelNumber = info.mChannel; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImplWiFi::GetWiFiRssi(int8_t & rssi) +{ + WiFiManager::WiFiInfo info; + ReturnErrorOnFailure(WiFiManager::Instance().GetWiFiInfo(info)); + rssi = info.mRssi; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImplWiFi::GetWiFiCurrentMaxRate(uint64_t & currentMaxRate) +{ + WiFiManager::WiFiInfo info; + ReturnErrorOnFailure(WiFiManager::Instance().GetWiFiInfo(info)); + // mCurrentPhyRate Value in Mbps + currentMaxRate = info.mCurrentPhyRate * 1000000; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImplWiFi::GetWiFiBeaconLostCount(uint32_t & beaconLostCount) +{ + WiFiManager::NetworkStatistics stats; + ReturnErrorOnFailure(WiFiManager::Instance().GetNetworkStatistics(stats)); + beaconLostCount = stats.mBeaconsLostCount; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImplWiFi::GetWiFiBeaconRxCount(uint32_t & beaconRxCount) +{ + WiFiManager::NetworkStatistics stats; + ReturnErrorOnFailure(WiFiManager::Instance().GetNetworkStatistics(stats)); + beaconRxCount = stats.mBeaconsSuccessCount; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImplWiFi::GetWiFiPacketMulticastRxCount(uint32_t & packetMulticastRxCount) +{ + WiFiManager::NetworkStatistics stats; + ReturnErrorOnFailure(WiFiManager::Instance().GetNetworkStatistics(stats)); + packetMulticastRxCount = stats.mPacketMulticastRxCount; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImplWiFi::GetWiFiPacketMulticastTxCount(uint32_t & packetMulticastTxCount) +{ + WiFiManager::NetworkStatistics stats; + ReturnErrorOnFailure(WiFiManager::Instance().GetNetworkStatistics(stats)); + packetMulticastTxCount = stats.mPacketMulticastTxCount; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImplWiFi::GetWiFiPacketUnicastRxCount(uint32_t & packetUnicastRxCount) +{ + WiFiManager::NetworkStatistics stats; + ReturnErrorOnFailure(WiFiManager::Instance().GetNetworkStatistics(stats)); + packetUnicastRxCount = stats.mPacketUnicastRxCount; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImplWiFi::GetWiFiPacketUnicastTxCount(uint32_t & packetUnicastTxCount) +{ + WiFiManager::NetworkStatistics stats; + ReturnErrorOnFailure(WiFiManager::Instance().GetNetworkStatistics(stats)); + packetUnicastTxCount = stats.mPacketUnicastTxCount; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImplWiFi::GetWiFiOverrunCount(uint64_t & overrunCount) +{ + WiFiManager::NetworkStatistics stats; + ReturnErrorOnFailure(WiFiManager::Instance().GetNetworkStatistics(stats)); + overrunCount = static_cast(stats.mOverRunCount); + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImplWiFi::ResetWiFiNetworkDiagnosticsCounts() +{ + net_if * iface = InetUtils::GetWiFiInterface(); + VerifyOrReturnError(iface != nullptr, INET_ERROR_UNKNOWN_INTERFACE); + + if (net_mgmt(NET_REQUEST_STATS_RESET_WIFI, iface, NULL, 0)) + { + ChipLogError(DeviceLayer, "WiFi statistics reset failed"); + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/zephyr/DiagnosticDataProviderImplNxp.h b/src/platform/Zephyr/wifi/DiagnosticDataProviderImplWiFi.h similarity index 78% rename from src/platform/nxp/zephyr/DiagnosticDataProviderImplNxp.h rename to src/platform/Zephyr/wifi/DiagnosticDataProviderImplWiFi.h index 1844a71562f..69c05cce1ea 100644 --- a/src/platform/nxp/zephyr/DiagnosticDataProviderImplNxp.h +++ b/src/platform/Zephyr/wifi/DiagnosticDataProviderImplWiFi.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2024-2025 Project CHIP Authors + * Copyright (c) 2025 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,8 +17,7 @@ /** * @file - * Provides an implementation of the DiagnosticDataProvider object - * for NXP Zephyr platform. + * Provides an implementation of Wi-Fi network diagnostics methods of the DiagnosticDataProvider object. */ #pragma once @@ -28,10 +27,16 @@ namespace chip { namespace DeviceLayer { -class DiagnosticDataProviderImplNxp : public DiagnosticDataProviderImpl +/** + * Concrete implementation of the DiagnosticDataProvider with WiFi network diagnostics support for Zephyr platforms. + */ +class DiagnosticDataProviderImplWiFi : public DiagnosticDataProviderImpl { public: -#ifdef CONFIG_WIFI_NXP + static DiagnosticDataProviderImplWiFi & GetDefaultInstance(); + + // ===== WiFi Network Diagnostics Methods ===== + CHIP_ERROR GetWiFiBssId(MutableByteSpan & value) override; CHIP_ERROR GetWiFiSecurityType(app::Clusters::WiFiNetworkDiagnostics::SecurityTypeEnum & securityType) override; CHIP_ERROR GetWiFiVersion(app::Clusters::WiFiNetworkDiagnostics::WiFiVersionEnum & wiFiVersion) override; @@ -46,15 +51,10 @@ class DiagnosticDataProviderImplNxp : public DiagnosticDataProviderImpl CHIP_ERROR GetWiFiCurrentMaxRate(uint64_t & currentMaxRate) override; CHIP_ERROR GetWiFiOverrunCount(uint64_t & overrunCount) override; CHIP_ERROR ResetWiFiNetworkDiagnosticsCounts() override; -#endif - - static DiagnosticDataProviderImplNxp & GetDefaultInstance(); private: - DiagnosticDataProviderImplNxp() = default; + DiagnosticDataProviderImplWiFi() = default; }; -DiagnosticDataProvider & GetDiagnosticDataProviderImpl(); - } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/device.gni b/src/platform/device.gni index fcb60bd4a6f..5b7b3f88b11 100644 --- a/src/platform/device.gni +++ b/src/platform/device.gni @@ -179,8 +179,6 @@ if (chip_device_platform == "cc13x4_26x4") { import("//build_overrides/nxp_sdk.gni") import("${nxp_sdk_build_root}/nxp_sdk.gni") _chip_device_layer = "nxp/${nxp_platform}" -} else if (chip_device_platform == "nxp_zephyr") { - _chip_device_layer = "nxp/zephyr" } else if (chip_device_platform == "telink") { _chip_device_layer = "telink" } else if (chip_device_platform == "psoc6") { @@ -276,14 +274,13 @@ assert( chip_device_platform == "realtek_bee" || chip_device_platform == "realtek_zephyr" || chip_device_platform == "nrfconnect" || chip_device_platform == "nxp" || - chip_device_platform == "nxp_zephyr" || chip_device_platform == "qpg" || - chip_device_platform == "telink" || chip_device_platform == "psoc6" || - chip_device_platform == "android" || chip_device_platform == "ameba" || - chip_device_platform == "cyw30739" || chip_device_platform == "webos" || - chip_device_platform == "zephyr" || chip_device_platform == "beken" || - chip_device_platform == "bl602" || chip_device_platform == "bl616" || - chip_device_platform == "bl702" || chip_device_platform == "bl702l" || - chip_device_platform == "mt793x" || chip_device_platform == "SiWx917" || - chip_device_platform == "asr" || chip_device_platform == "stm32" || - chip_device_platform == "nuttx", + chip_device_platform == "qpg" || chip_device_platform == "telink" || + chip_device_platform == "psoc6" || chip_device_platform == "android" || + chip_device_platform == "ameba" || chip_device_platform == "cyw30739" || + chip_device_platform == "webos" || chip_device_platform == "zephyr" || + chip_device_platform == "beken" || chip_device_platform == "bl602" || + chip_device_platform == "bl616" || chip_device_platform == "bl702" || + chip_device_platform == "bl702l" || chip_device_platform == "mt793x" || + chip_device_platform == "SiWx917" || chip_device_platform == "asr" || + chip_device_platform == "stm32" || chip_device_platform == "nuttx", "Please select a valid value for chip_device_platform") diff --git a/src/platform/logging/BUILD.gn b/src/platform/logging/BUILD.gn index a49a5511d0c..ffb4c400896 100644 --- a/src/platform/logging/BUILD.gn +++ b/src/platform/logging/BUILD.gn @@ -41,8 +41,6 @@ group("default") { deps += [ "${chip_root}/src/platform/webos:logging" ] } else if (chip_device_platform == "zephyr") { deps += [ "${chip_root}/src/platform/Zephyr:logging" ] - } else if (chip_device_platform == "nxp_zephyr") { - deps += [ "${chip_root}/src/platform/nxp/zephyr:logging" ] } else if (chip_device_platform == "nrfconnect") { deps += [ "${chip_root}/src/platform/nrfconnect:logging" ] } else if (chip_device_platform == "telink") { diff --git a/src/platform/nxp/common/ConnectivityManagerImpl.cpp b/src/platform/nxp/common/ConnectivityManagerImpl.cpp index 162450ca0a9..e3e9a3dc222 100644 --- a/src/platform/nxp/common/ConnectivityManagerImpl.cpp +++ b/src/platform/nxp/common/ConnectivityManagerImpl.cpp @@ -399,6 +399,7 @@ void ConnectivityManagerImpl::ProcessWlanEvent(enum wlan_event_reason wlanEvent) { sInstance._SetWiFiStationState(kWiFiStationState_Connecting_Succeeded); sInstance._SetWiFiStationState(kWiFiStationState_Connected); + NetworkCommissioning::NXPWiFiDriver::GetInstance().OnNetworkStatusChange(); NetworkCommissioning::NXPWiFiDriver::GetInstance().OnConnectWiFiNetwork(NetworkCommissioning::Status::kSuccess, CharSpan(), wlanEvent); sInstance.OnStationConnected(); diff --git a/src/platform/nxp/common/DnssdImplBr.cpp b/src/platform/nxp/common/DnssdImplBr.cpp index 0598fe09841..3f41043df73 100644 --- a/src/platform/nxp/common/DnssdImplBr.cpp +++ b/src/platform/nxp/common/DnssdImplBr.cpp @@ -88,12 +88,16 @@ struct mDnsQueryCtx mDnsQueryCtx(void * context, DnsBrowseCallback aBrowseCallback) { + link.next = nullptr; + link.list = nullptr; matterCtx = context; mDnsBrowseCallback = aBrowseCallback; error = CHIP_NO_ERROR; } mDnsQueryCtx(void * context, DnsResolveCallback aResolveCallback) { + link.next = nullptr; + link.list = nullptr; matterCtx = context; mDnsResolveCallback = aResolveCallback; error = CHIP_NO_ERROR; @@ -127,6 +131,7 @@ static void DispatchBrowse(intptr_t context); static void DispatchTxtResolve(intptr_t context); static void DispatchAddressResolve(intptr_t context); static void DispatchResolve(intptr_t context); +static void DispatchResolveSrp(intptr_t context); static void DispatchResolveError(intptr_t context); static void HandleResolveCleanup(mDnsQueryCtx & resolveContext, ResolveStep stepType); @@ -186,7 +191,6 @@ void NxpChipDnssdShutdown() // Stop all browse operations and clean the browse list otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); mDnsQueryCtx * pQueryContext = reinterpret_cast(LIST_GetHead(&mBrowseList)); - ; while (pQueryContext) { @@ -247,7 +251,9 @@ CHIP_ERROR NxpChipDnssdRemoveServices() if ((0 == strcmp(mServiceList[mServiceListFreeIndex]->mHostName, hostName)) && ((0 == strcmp(mServiceList[mServiceListFreeIndex]->mServiceType, "_matter._tcp")) || - (0 == strcmp(mServiceList[mServiceListFreeIndex]->mServiceType, "_matterc._udp")))) + (0 == strcmp(mServiceList[mServiceListFreeIndex]->mServiceType, "_matterc._udp"))) && + (mServiceList[mServiceListFreeIndex]->mTtl > 0)) + // if mTtl = 0 , the service is already in the removal process but not yet removed { mServiceListFreeIndex++; } @@ -609,7 +615,7 @@ CHIP_ERROR ResolveBySrp(otInstance * thrInstancePtr, char * serviceName, mDnsQue error = FromSrpCacheToMdnsData(service, host, mdnsReq, context->mMdnsService, context->mServiceTxtEntry); if (error == CHIP_NO_ERROR) { - DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolve, reinterpret_cast(context)); + DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolveSrp, reinterpret_cast(context)); } break; } @@ -878,7 +884,8 @@ static void OtTxtCallback(otInstance * aInstance, const otMdnsTxtResult * aResul if (alloc.AnyAllocFailed()) { - bSendDispatch = false; + bSendDispatch = false; + pResolveContext->error = CHIP_ERROR_NO_MEMORY; } else { @@ -992,6 +999,24 @@ static void DispatchResolve(intptr_t context) Platform::Delete(pResolveContext); } +static void DispatchResolveSrp(intptr_t context) +{ + mDnsQueryCtx * pResolveContext = reinterpret_cast(context); + Dnssd::DnssdService & service = pResolveContext->mMdnsService; + Span ipAddrs; + + // Address resolver was not started and the resolve context was not added to the resolve list + // when the result came directly from SRP. + + if (service.mAddress.has_value()) + { + ipAddrs = Span(&*service.mAddress, 1); + } + + pResolveContext->mDnsResolveCallback(pResolveContext->matterCtx, &service, ipAddrs, pResolveContext->error); + Platform::Delete(pResolveContext); +} + static void DispatchResolveError(intptr_t context) { mDnsQueryCtx * pResolveContext = reinterpret_cast(context); @@ -1021,7 +1046,11 @@ static void HandleResolveCleanup(mDnsQueryCtx & resolveContext, ResolveStep step break; } - DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolve, reinterpret_cast(&resolveContext)); + // In this case the resolve operation could not be completed successfully so we need to call + // DispatchResolveError to handle the Matter callback with an error case. No IP address is reported and + // the address resolve operation doesn’t need to be stopped again as was not started in the first place + // or it's already handled by HandleResolveCleanup. + DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolveError, reinterpret_cast(&resolveContext)); } static mDnsQueryCtx * GetResolveElement(const char * aName, NameType aType) diff --git a/src/platform/nxp/common/Ethernet/NxpEthDriver.cpp b/src/platform/nxp/common/Ethernet/NxpEthDriver.cpp index 038f8ff2675..c145eec310d 100644 --- a/src/platform/nxp/common/Ethernet/NxpEthDriver.cpp +++ b/src/platform/nxp/common/Ethernet/NxpEthDriver.cpp @@ -64,12 +64,39 @@ void NxpEthDriver::eth_netif_ext_status_callback(struct netif * netif, netif_nsc { ChipLogError(DeviceLayer, "Failed to schedule work: %" CHIP_ERROR_FORMAT, err.Format()); } + SystemLayer().ScheduleLambda([]() { NxpEthDriver::Instance().OnNetworkStatusChange(); }); + } +} + +void NxpEthDriver::OnNetworkStatusChange() +{ + ChipLogProgress(NetworkProvisioning, "NxpEthDriver::OnNetworkStatusChange\r\n"); + VerifyOrReturn(mpStatusChangeCallback != nullptr); + NetworkIterator * networkIterator = GetNetworks(); + + if (networkIterator != nullptr) + { + EthernetNetworkIterator * ethIterator = static_cast(networkIterator); + + if (ethIterator->interfaceNameLen) + { + mpStatusChangeCallback->OnNetworkingStatusChange( + Status::kSuccess, MakeOptional(ByteSpan(ethIterator->interfaceName, ethIterator->interfaceNameLen)), NullOptional); + } + else + { + mpStatusChangeCallback->OnNetworkingStatusChange( + Status::kUnknownError, MakeOptional(ByteSpan(ethIterator->interfaceName, ethIterator->interfaceNameLen)), + NullOptional); + } + networkIterator->Release(); } } CHIP_ERROR NxpEthDriver::Init(NetworkStatusChangeCallback * networkStatusChangeCallback) { err_t err; + mpStatusChangeCallback = networkStatusChangeCallback; ethernetif_config_t enet_config = { .phyHandle = &phyHandle, .phyAddr = EXAMPLE_PHY_ADDRESS, diff --git a/src/platform/nxp/common/Ethernet/NxpEthDriver.h b/src/platform/nxp/common/Ethernet/NxpEthDriver.h index b368255b397..0a59c207e1e 100644 --- a/src/platform/nxp/common/Ethernet/NxpEthDriver.h +++ b/src/platform/nxp/common/Ethernet/NxpEthDriver.h @@ -76,11 +76,13 @@ class NxpEthDriver final : public EthernetDriver } private: + void OnNetworkStatusChange(); static void print_ip_addresses(struct netif * netif); static void eth_netif_ext_status_callback(struct netif * netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t * args); phy_handle_t phyHandle; struct netif netif_app; + NetworkStatusChangeCallback * mpStatusChangeCallback = nullptr; }; } // namespace NetworkCommissioning diff --git a/src/platform/nxp/common/NXPConfig.cpp b/src/platform/nxp/common/NXPConfig.cpp index 029c5e17663..dc91b0cf1b1 100644 --- a/src/platform/nxp/common/NXPConfig.cpp +++ b/src/platform/nxp/common/NXPConfig.cpp @@ -565,7 +565,7 @@ bool NXPConfig::ValidConfigKey(Key key) { // Returns true if the key is in the valid CHIP Config PDM key range. - if ((key >= kMinConfigKey_ChipFactory) && (key <= kMaxConfigKey_KVS)) + if ((key >= kMinConfigKey_ChipFactory) && (key <= kMaxConfigKey_App)) { return true; } diff --git a/src/platform/nxp/common/NXPConfig.h b/src/platform/nxp/common/NXPConfig.h index 7de3beab2b3..1ed9c451d17 100644 --- a/src/platform/nxp/common/NXPConfig.h +++ b/src/platform/nxp/common/NXPConfig.h @@ -81,6 +81,8 @@ class NXPConfig * runtime. Retained during factory reset. */ static constexpr uint8_t kFileId_KVS = CATEGORY_BASE + 3; /**< Category containing KVS set at runtime. * Cleared during factory reset. */ + static constexpr uint8_t kFileId_App = CATEGORY_BASE + 4; /**< Category containing custom application values set at runtime. + * Cleared during factory reset. */ using Key = uint16_t; @@ -146,6 +148,9 @@ class NXPConfig static constexpr Key kConfigKey_GroupKeyMax = config_key(kFileId_ChipConfig, 0x1E); ; // Allows 16 Group Keys to be created. + // Application Custom Keys + static constexpr Key kConfigKey_AppOTADone = config_key(kFileId_App, 0x00); + // Set key id limits for each group. static constexpr Key kMinConfigKey_ChipFactory = config_key(kFileId_ChipFactory, 0x00); static constexpr Key kMaxConfigKey_ChipFactory = config_key(kFileId_ChipFactory, 0x08); @@ -155,6 +160,8 @@ class NXPConfig static constexpr Key kMaxConfigKey_ChipCounter = config_key(kFileId_ChipCounter, 0x1F); // Allows 32 Counters to be created. static constexpr Key kMinConfigKey_KVS = config_key(kFileId_KVS, 0x00); static constexpr Key kMaxConfigKey_KVS = config_key(kFileId_KVS, 0xFF); + static constexpr Key kMinConfigKey_App = config_key(kFileId_App, 0x00); + static constexpr Key kMaxConfigKey_App = config_key(kFileId_App, 0xFF); static CHIP_ERROR Init(void); diff --git a/src/platform/nxp/common/NXPConfigKS.cpp b/src/platform/nxp/common/NXPConfigKS.cpp index 930f07fe354..95c273a87a2 100644 --- a/src/platform/nxp/common/NXPConfigKS.cpp +++ b/src/platform/nxp/common/NXPConfigKS.cpp @@ -450,7 +450,7 @@ bool NXPConfig::ValidConfigKey(Key key) { // Returns true if the key is in the valid CHIP Config PDM key range. - if ((key >= kMinConfigKey_ChipFactory) && (key <= kMaxConfigKey_KVS)) + if ((key >= kMinConfigKey_ChipFactory) && (key <= kMaxConfigKey_App)) { return true; } diff --git a/src/platform/nxp/common/NXPConfigNVS.cpp b/src/platform/nxp/common/NXPConfigNVS.cpp index b18863ed31a..1e7930a81bb 100644 --- a/src/platform/nxp/common/NXPConfigNVS.cpp +++ b/src/platform/nxp/common/NXPConfigNVS.cpp @@ -397,7 +397,7 @@ CHIP_ERROR NXPConfig::FactoryResetConfig(void) bool NXPConfig::ValidConfigKey(Key key) { // Returns true if the key is in the valid CHIP Config PDM key range. - return (key >= kMinConfigKey_ChipFactory) && (key <= kMaxConfigKey_KVS); + return (key >= kMinConfigKey_ChipFactory) && (key <= kMaxConfigKey_App); } void NXPConfig::RunConfigUnitTest(void) {} diff --git a/src/platform/nxp/common/NetworkCommissioningDriver.h b/src/platform/nxp/common/NetworkCommissioningDriver.h index 0210853d5d4..95fd7c30ad9 100644 --- a/src/platform/nxp/common/NetworkCommissioningDriver.h +++ b/src/platform/nxp/common/NetworkCommissioningDriver.h @@ -72,6 +72,7 @@ class NXPWiFiDriver final : public WiFiDriver Status ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText) override; void ConnectNetwork(ByteSpan networkId, ConnectCallback * callback) override; CHIP_ERROR ConnectWiFiStagedNetwork(); + void OnNetworkStatusChange(); /* Returns the network SSID. User needs to allocate a buffer of size >= DeviceLayer::Internal::kMaxWiFiSSIDLength. * ssid - pointer to the returned SSID @@ -104,6 +105,7 @@ class NXPWiFiDriver final : public WiFiDriver private: bool NetworkMatch(const WiFiNetwork & network, ByteSpan networkId); CHIP_ERROR StartScanWiFiNetworks(ByteSpan ssid); + CHIP_ERROR GetConnectedNetwork(Network & network); WiFiNetworkIterator mWiFiIterator = WiFiNetworkIterator(this); WiFiNetwork mSavedNetwork; diff --git a/src/platform/nxp/common/NetworkCommissioningWiFiDriver.cpp b/src/platform/nxp/common/NetworkCommissioningWiFiDriver.cpp index dc3e91564af..dcc848a46c5 100644 --- a/src/platform/nxp/common/NetworkCommissioningWiFiDriver.cpp +++ b/src/platform/nxp/common/NetworkCommissioningWiFiDriver.cpp @@ -80,7 +80,9 @@ CHIP_ERROR NXPWiFiDriver::Init(NetworkStatusChangeCallback * networkStatusChange err = PersistedStorage::KeyValueStoreMgr().Get(kWiFiCredentialsKeyName, mSavedNetwork.credentials, sizeof(mSavedNetwork.credentials), &credentialsLen); - if (err != CHIP_NO_ERROR) + /* Password could be empty, do not return error if key not found, + password is written in flash before SSID, if SSID is present but not password, it is not an error */ + if (err != CHIP_NO_ERROR && err != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) { ChipLogProgress(DeviceLayer, "WiFi network credentials not retrieved from persisted storage: %" CHIP_ERROR_FORMAT, err.Format()); @@ -117,9 +119,9 @@ void NXPWiFiDriver::Shutdown() CHIP_ERROR NXPWiFiDriver::CommitConfiguration() { - ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiSSIDKeyName, mStagingNetwork.ssid, mStagingNetwork.ssidLen)); ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiCredentialsKeyName, mStagingNetwork.credentials, mStagingNetwork.credentialsLen)); + ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiSSIDKeyName, mStagingNetwork.ssid, mStagingNetwork.ssidLen)); mSavedNetwork = mStagingNetwork; return CHIP_NO_ERROR; @@ -145,6 +147,9 @@ CHIP_ERROR NXPWiFiDriver::RevertConfiguration() /* Reset mStagingNetwork as it may have been updated during add/update network operation */ mStagingNetwork = mSavedNetwork; + // succeed right away if we are already connected + VerifyOrReturnError(!is_sta_connected(), CHIP_NO_ERROR); + // succeed right away if no saved network VerifyOrReturnError(mStagingNetwork.ssidLen > 0, CHIP_NO_ERROR); // Connect to saved network @@ -240,6 +245,32 @@ void NXPWiFiDriver::OnConnectWiFiNetwork(Status commissioningError, CharSpan deb } } +void NXPWiFiDriver::OnNetworkStatusChange() +{ + ChipLogProgress(NetworkProvisioning, "NXPWiFiDriver::OnNetworkStatusChange\r\n"); + Network configuredNetwork; + + VerifyOrReturn(mpStatusChangeCallback != nullptr); + CHIP_ERROR err = GetConnectedNetwork(configuredNetwork); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Failed to get configured network when updating network status: %s", err.AsString()); + return; + } + + if (configuredNetwork.networkIDLen) + { + mpStatusChangeCallback->OnNetworkingStatusChange( + Status::kSuccess, MakeOptional(ByteSpan(configuredNetwork.networkID, configuredNetwork.networkIDLen)), NullOptional); + } + else + { + mpStatusChangeCallback->OnNetworkingStatusChange( + Status::kUnknownError, MakeOptional(ByteSpan(configuredNetwork.networkID, configuredNetwork.networkIDLen)), + NullOptional); + } +} + void NXPWiFiDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * callback) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -448,7 +479,7 @@ uint32_t NXPWiFiDriver::GetSupportedWiFiBandsMask() const return bands; } -static CHIP_ERROR GetConnectedNetwork(Network & network) +CHIP_ERROR NXPWiFiDriver::GetConnectedNetwork(Network & network) { struct wlan_network wlan_network; int result; @@ -490,7 +521,7 @@ bool NXPWiFiDriver::WiFiNetworkIterator::Next(Network & item) mExhausted = true; Network connectedNetwork; - CHIP_ERROR err = GetConnectedNetwork(connectedNetwork); + CHIP_ERROR err = mDriver->GetConnectedNetwork(connectedNetwork); if (err == CHIP_NO_ERROR) { diff --git a/src/platform/nxp/common/factory_data/legacy/FactoryDataDriver.cpp b/src/platform/nxp/common/factory_data/legacy/FactoryDataDriver.cpp index a8529dc9f3f..cae3c0de829 100644 --- a/src/platform/nxp/common/factory_data/legacy/FactoryDataDriver.cpp +++ b/src/platform/nxp/common/factory_data/legacy/FactoryDataDriver.cpp @@ -61,7 +61,7 @@ CHIP_ERROR FactoryDataDriver::UpdateValueInRam(uint8_t tag, ByteSpan & newValue) header->size = header->size - oldLength + newLength; uint8_t sha256Output[chip::Crypto::kSHA256_Hash_Length] = { 0 }; - chip::Crypto::Hash_SHA256(data, header->size, sha256Output); + ReturnErrorOnFailure(chip::Crypto::Hash_SHA256(data, header->size, sha256Output)); memcpy(header->hash, sha256Output, sizeof(header->hash)); ChipLogProgress(DeviceLayer, "Value at tag %d updated successfully.", tag); diff --git a/src/platform/nxp/common/factory_data/legacy/FactoryDataProviderImpl.cpp b/src/platform/nxp/common/factory_data/legacy/FactoryDataProviderImpl.cpp index e594e195224..28ad8e7362a 100644 --- a/src/platform/nxp/common/factory_data/legacy/FactoryDataProviderImpl.cpp +++ b/src/platform/nxp/common/factory_data/legacy/FactoryDataProviderImpl.cpp @@ -150,7 +150,7 @@ CHIP_ERROR FactoryDataProviderImpl::SSS_Sign(uint8_t * digest, Crypto::P256ECDSA VerifyOrExit(res == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); res = sss_sscp_asymmetric_sign_digest(&asyc, digest, Crypto::kP256_PrivateKey_Length, signature.Bytes(), &signatureSize); VerifyOrExit(res == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - signature.SetLength(signatureSize); + error = signature.SetLength(signatureSize); exit: sss_sscp_asymmetric_context_free(&asyc); diff --git a/src/platform/nxp/common/ota/OTAFirmwareProcessor.cpp b/src/platform/nxp/common/ota/OTAFirmwareProcessor.cpp index db2b419aa92..bc3546b9134 100644 --- a/src/platform/nxp/common/ota/OTAFirmwareProcessor.cpp +++ b/src/platform/nxp/common/ota/OTAFirmwareProcessor.cpp @@ -68,8 +68,6 @@ CHIP_ERROR OTAFirmwareProcessor::Clear() CHIP_ERROR OTAFirmwareProcessor::ProcessInternal(ByteSpan & block) { otaResult_t status; - static uint32_t ulEraseLen = 0; - static uint32_t ulCrtAddr = 0; if (!mDescriptorProcessed) { @@ -102,22 +100,11 @@ CHIP_ERROR OTAFirmwareProcessor::ProcessInternal(ByteSpan & block) OTATlvProcessor::vOtaProcessInternalEncryption(mBlock); #endif - ulCrtAddr += block.size(); - - if (ulCrtAddr >= ulEraseLen) - { - ulEraseLen += 0x1000; // flash sector size - - status = OTA_MakeHeadRoomForNextBlock(block.size(), OTAImageProcessorImpl::FetchNextData, 0); - if (gOtaSuccess_c != status) - { - ChipLogError(SoftwareUpdate, "Failed to make room for next block. Status: %d", status); - return CHIP_ERROR_OTA_PROCESSOR_MAKE_ROOM; - } - } - else + status = OTA_MakeHeadRoomForNextBlock(block.size(), OTAImageProcessorImpl::FetchNextData, 0); + if (gOtaSuccess_c != status) { - OTAImageProcessorImpl::FetchNextData(0); + ChipLogError(SoftwareUpdate, "Failed to make room for next block. Status: %d", status); + return CHIP_ERROR_OTA_PROCESSOR_MAKE_ROOM; } #if OTA_ENCRYPTION_ENABLE diff --git a/src/platform/nxp/mcxw71/ConfigurationManagerImpl.cpp b/src/platform/nxp/mcxw71/ConfigurationManagerImpl.cpp index 526d8a69c77..f774675d588 100644 --- a/src/platform/nxp/mcxw71/ConfigurationManagerImpl.cpp +++ b/src/platform/nxp/mcxw71/ConfigurationManagerImpl.cpp @@ -63,10 +63,20 @@ CHIP_ERROR ConfigurationManagerImpl::DetermineBootReason(uint32_t reason) { bootReason = BootReasonType::kSoftwareReset; #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - OtaImgState_t img_state = OTA_GetImgState(); - if (img_state == OtaImgState_RunCandidate) + CHIP_ERROR err = CHIP_NO_ERROR; + bool otaDone = false; + + err = ReadConfigValue(NXPConfig::kConfigKey_AppOTADone, otaDone); + if (err != CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) + { + SuccessOrLog(err, DeviceLayer, "Failed to read OTA completion flag"); + } + + if (otaDone) { bootReason = BootReasonType::kSoftwareUpdateCompleted; + ReturnErrorAndLogOnFailure(WriteConfigValue(NXPConfig::kConfigKey_AppOTADone, false), DeviceLayer, + "Failed to store OTA completion flag"); } #endif } @@ -84,7 +94,9 @@ CHIP_ERROR ConfigurationManagerImpl::DetermineBootReason(uint32_t reason) CHIP_ERROR ConfigurationManagerImpl::StoreSoftwareUpdateCompleted() { - /* Empty implementation*/ + ReturnErrorAndLogOnFailure(WriteConfigValue(NXPConfig::kConfigKey_AppOTADone, true), DeviceLayer, + "Failed to store OTA completion flag"); + return CHIP_NO_ERROR; } diff --git a/src/platform/nxp/mcxw71/K32W1Config.cpp b/src/platform/nxp/mcxw71/K32W1Config.cpp index cc02aef47bc..f854d8b34cf 100644 --- a/src/platform/nxp/mcxw71/K32W1Config.cpp +++ b/src/platform/nxp/mcxw71/K32W1Config.cpp @@ -417,7 +417,7 @@ CHIP_ERROR NXPConfig::MapRamStorageStatus(rsError rsStatus) bool NXPConfig::ValidConfigKey(Key key) { // Returns true if the key is in the valid CHIP Config PDM key range. - if ((key >= kMinConfigKey_ChipFactory) && (key <= kMaxConfigKey_KVSValue)) + if ((key >= kMinConfigKey_ChipFactory) && (key <= kMaxConfigKey_App)) { return true; } diff --git a/src/platform/nxp/mcxw71/K32W1Config.h b/src/platform/nxp/mcxw71/K32W1Config.h index ceeae82a8dc..65f797047c7 100644 --- a/src/platform/nxp/mcxw71/K32W1Config.h +++ b/src/platform/nxp/mcxw71/K32W1Config.h @@ -63,6 +63,8 @@ class NXPConfig * Cleared during factory reset. */ static constexpr uint8_t kFileId_KVSValue = 0x05; /**< Category containing KVS values set at runtime. * Cleared during factory reset. */ + static constexpr uint8_t kFileId_App = 0x06; /**< Category containing custom application values set at runtime. + * Cleared during factory reset. */ using Key = uint16_t; @@ -98,6 +100,9 @@ class NXPConfig static constexpr Key kCounterKey_TotalOperationalHours = K32WConfigKey(kFileId_ChipCounter, 0x02); static constexpr Key kCounterKey_BootReason = K32WConfigKey(kFileId_ChipCounter, 0x03); + // Application Custom Keys + static constexpr Key kConfigKey_AppOTADone = K32WConfigKey(kFileId_App, 0x00); + // Set key id limits for each group. static constexpr Key kMinConfigKey_ChipFactory = K32WConfigKey(kFileId_ChipFactory, 0x00); static constexpr Key kMaxConfigKey_ChipFactory = K32WConfigKey(kFileId_ChipFactory, 0xFF); @@ -109,6 +114,8 @@ class NXPConfig static constexpr Key kMaxConfigKey_KVSKey = K32WConfigKey(kFileId_KVSKey, 0xFF); static constexpr Key kMinConfigKey_KVSValue = K32WConfigKey(kFileId_KVSValue, 0x00); static constexpr Key kMaxConfigKey_KVSValue = K32WConfigKey(kFileId_KVSValue, 0xFF); + static constexpr Key kMinConfigKey_App = K32WConfigKey(kFileId_App, 0x00); + static constexpr Key kMaxConfigKey_App = K32WConfigKey(kFileId_App, 0xFF); static CHIP_ERROR Init(void); diff --git a/src/platform/nxp/zephyr/BLEManagerImpl.h b/src/platform/nxp/zephyr/BLEManagerImpl.h deleted file mode 100644 index bb3e7405153..00000000000 --- a/src/platform/nxp/zephyr/BLEManagerImpl.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * - * Copyright (c) 2024 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Provides an implementation of the BLEManager singleton object - * for the Zephyr platforms. - */ - -#pragma once - -#include diff --git a/src/platform/nxp/zephyr/BUILD.gn b/src/platform/nxp/zephyr/BUILD.gn deleted file mode 100644 index cd1511dfefa..00000000000 --- a/src/platform/nxp/zephyr/BUILD.gn +++ /dev/null @@ -1,136 +0,0 @@ -# Copyright (c) 2024 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") - -import("${chip_root}/src/platform/device.gni") -import("${chip_root}/src/platform/nxp/zephyr/args.gni") - -assert(chip_device_platform == "nxp_zephyr") - -static_library("nxp_zephyr") { - defines = [] - sources = [ - "../../SingletonConfigurationManager.cpp", - "../../Zephyr/ConfigurationManagerImpl.cpp", - "../../Zephyr/DiagnosticDataProviderImpl.cpp", - "../../Zephyr/DiagnosticDataProviderImpl.h", - "../../Zephyr/KeyValueStoreManagerImpl.cpp", - "../../Zephyr/PlatformManagerImpl.cpp", - "../../Zephyr/SysHeapMalloc.h", - "../../Zephyr/SystemTimeSupport.cpp", - "../../Zephyr/ZephyrConfig.cpp", - "../../Zephyr/ZephyrConfig.h", - "../common/CHIPDeviceNXPPlatformDefaultConfig.h", - "../common/CHIPNXPPlatformDefaultConfig.h", - "CHIPDevicePlatformConfig.h", - "CHIPDevicePlatformEvent.h", - "CHIPPlatformConfig.h", - "ConfigurationManagerImpl.h", - "ConnectivityManagerImpl.cpp", - "ConnectivityManagerImpl.h", - "DiagnosticDataProviderImplNxp.cpp", - "DiagnosticDataProviderImplNxp.h", - "InetPlatformConfig.h", - "KeyValueStoreManagerImpl.h", - "PlatformManagerImpl.h", - "SystemPlatformConfig.h", - ] - - public = [ - "${chip_root}/src/credentials/CHIPCert.h", - "${chip_root}/src/credentials/CertificationDeclaration.h", - "${chip_root}/src/credentials/DeviceAttestationCredsProvider.h", - "${chip_root}/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h", - "${chip_root}/src/credentials/attestation_verifier/DeviceAttestationVerifier.h", - "${chip_root}/src/credentials/examples/DeviceAttestationCredsExample.h", - "${chip_root}/src/credentials/examples/ExampleDACs.h", - "${chip_root}/src/credentials/examples/ExamplePAI.h", - ] - - public_deps = [ "${chip_root}/src/platform:platform_base" ] - deps = [ - "${chip_root}/src/app:app_config", - "${chip_root}/src/app/common:ids", - "${chip_root}/src/platform/logging:headers", - ] - - if (chip_enable_factory_data) { - sources += [ - "../common/factory_data/legacy/FactoryDataProvider.cpp", - "../common/factory_data/legacy/FactoryDataProvider.h", - "FactoryDataProviderImpl.cpp", - "FactoryDataProviderImpl.h", - ] - } else { - sources += [ - "DeviceInstanceInfoProviderImpl.cpp", - "DeviceInstanceInfoProviderImpl.h", - ] - } - if (chip_config_network_layer_ble) { - sources += [ - "../../Zephyr/BLEAdvertisingArbiter.cpp", - "../../Zephyr/BLEAdvertisingArbiter.h", - "../../Zephyr/BLEManagerImpl.cpp", - "BLEManagerImpl.h", - "BlePlatformConfig.h", - ] - } - if (chip_enable_wifi) { - sources += [ - "../../Zephyr/wifi/ConnectivityManagerImplWiFi.cpp", - "../../Zephyr/wifi/ConnectivityManagerImplWiFi.h", - "../../Zephyr/wifi/WiFiManager.cpp", - "../../Zephyr/wifi/WiFiManager.h", - "../../Zephyr/wifi/ZephyrWifiDriver.cpp", - "../../Zephyr/wifi/ZephyrWifiDriver.h", - ] - } - if (chip_enable_ethernet) { - sources += [ - "Ethernet/ConnectivityManagerImplEth.cpp", - "Ethernet/ConnectivityManagerImplEth.h", - "Ethernet/EthManager.cpp", - "Ethernet/EthManager.h", - "Ethernet/NxpEthDriver.cpp", - "Ethernet/NxpEthDriver.h", - ] - } - if (chip_enable_ota_requestor) { - sources += [ - "ota/OTAImageProcessorImpl.cpp", - "ota/OTAImageProcessorImpl.h", - ] - } - if (chip_enable_wifi || chip_enable_ethernet) { - sources += [ - "../../Zephyr/InetUtils.cpp", - "../../Zephyr/InetUtils.h", - ] - } - if (chip_malloc_sys_heap) { - sources += [ "../../Zephyr/SysHeapMalloc.cpp" ] - } - - cflags = [ "-Wconversion" ] -} - -source_set("logging") { - deps = [ - "${chip_root}/src/platform:platform_base", - "${chip_root}/src/platform/logging:headers", - ] - sources = [ "../../Zephyr/Logging.cpp" ] -} diff --git a/src/platform/nxp/zephyr/BlePlatformConfig.h b/src/platform/nxp/zephyr/BlePlatformConfig.h deleted file mode 100644 index 35c31253622..00000000000 --- a/src/platform/nxp/zephyr/BlePlatformConfig.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * - * Copyright (c) 2024 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Platform-specific configuration overrides for the CHIP BLE - * Layer on Zephyr platform. - * - */ - -#pragma once - -#include diff --git a/src/platform/nxp/zephyr/CHIPDevicePlatformConfig.h b/src/platform/nxp/zephyr/CHIPDevicePlatformConfig.h deleted file mode 100644 index 30ecb9d3482..00000000000 --- a/src/platform/nxp/zephyr/CHIPDevicePlatformConfig.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * - * Copyright (c) 2024 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Platform-specific configuration overrides for the chip Device Layer - * on Zephyr platform. - */ - -#pragma once - -#include "autoconf.h" - -// ==================== Platform Adaptations ==================== - -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID CONFIG_CHIP_DEVICE_VENDOR_ID -#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME CONFIG_CHIP_DEVICE_VENDOR_NAME -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID CONFIG_CHIP_DEVICE_PRODUCT_ID -#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME CONFIG_CHIP_DEVICE_PRODUCT_NAME -#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION CONFIG_CHIP_DEVICE_HARDWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING CONFIG_CHIP_DEVICE_HARDWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION CONFIG_CHIP_DEVICE_SOFTWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING CONFIG_CHIP_DEVICE_SOFTWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_TEST_MANUFACTURING_DATE CONFIG_CHIP_DEVICE_MANUFACTURING_DATE -#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER CONFIG_CHIP_DEVICE_SERIAL_NUMBER -#define CHIP_DEVICE_CONFIG_DEVICE_TYPE CONFIG_CHIP_DEVICE_TYPE -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR CONFIG_CHIP_DEVICE_DISCRIMINATOR -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE -#define CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT CONFIG_CHIP_DEVICE_SPAKE2_IT -#define CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT CONFIG_CHIP_DEVICE_SPAKE2_SALT -#define CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER CONFIG_CHIP_DEVICE_SPAKE2_TEST_VERIFIER - -#ifdef CONFIG_NET_L2_OPENTHREAD -#define CHIP_DEVICE_CONFIG_ENABLE_THREAD CONFIG_NET_L2_OPENTHREAD -#else -#define CHIP_DEVICE_CONFIG_ENABLE_THREAD 0 -#endif - -#ifdef CONFIG_CHIP_WIFI -#define CHIP_DEVICE_CONFIG_ENABLE_WIFI CONFIG_CHIP_WIFI -#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION 1 -#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP 0 -#else -#define CHIP_DEVICE_CONFIG_ENABLE_WIFI 0 -#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION 0 -#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP 0 -#endif - -#ifdef CONFIG_CHIP_ETHERNET -#define CHIP_DEVICE_CONFIG_ENABLE_ETHERNET CONFIG_CHIP_ETHERNET -#else -#define CHIP_DEVICE_CONFIG_ENABLE_ETHERNET 0 -#endif - -#ifdef CONFIG_BT -#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE CONFIG_BT -#else -#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 0 -#endif - -// ========== Platform-specific Configuration ========= - -// These are configuration options that are unique to Zephyr platforms. -// These can be overridden by the application as needed. - -#ifndef CHIP_DEVICE_CONFIG_SETTINGS_KEY -/// Key for all Matter persistent data stored using the Zephyr Settings API -#define CHIP_DEVICE_CONFIG_SETTINGS_KEY "mt" -#endif // CHIP_DEVICE_CONFIG_SETTINGS_KEY - -#ifndef CHIP_DEVICE_CONFIG_SERVER_SHUTDOWN_ACTIONS_SLEEP_MS -/// Time to sleep after running server shutdown actions to let lower layers complete the actions. -/// This may include transmitting packets created by the actions. -#define CHIP_DEVICE_CONFIG_SERVER_SHUTDOWN_ACTIONS_SLEEP_MS 500 -#endif // CHIP_DEVICE_CONFIG_SERVER_SHUTDOWN_ACTIONS_SLEEP_MS - -#ifndef CHIP_DEVICE_CONFIG_HEAP_STATISTICS_MALLINFO -#if !defined(CONFIG_CHIP_MALLOC_SYS_HEAP) && defined(CONFIG_NEWLIB_LIBC) -/// Use mallinfo() to obtain the heap usage statistics exposed by SoftwareDiagnostics cluster attributes. -#define CHIP_DEVICE_CONFIG_HEAP_STATISTICS_MALLINFO 1 -#else -#define CHIP_DEVICE_CONFIG_HEAP_STATISTICS_MALLINFO 0 -#endif // !defined(CONFIG_CHIP_MALLOC_SYS_HEAP) && defined(CONFIG_NEWLIB_LIBC) -#endif // CHIP_DEVICE_CONFIG_HEAP_STATISTICS_MALLINFO - -#ifndef CHIP_DEVICE_BLE_ADVERTISING_PRIORITY -/// Priority of the Matter BLE advertising when there are multiple application -/// components that compete for the BLE advertising. -#define CHIP_DEVICE_BLE_ADVERTISING_PRIORITY 0 -#endif // CHIP_DEVICE_BLE_ADVERTISING_PRIORITY - -// ========== Platform-specific Configuration Overrides ========= - -#ifndef CHIP_DEVICE_CONFIG_CHIP_TASK_PRIORITY -#define CHIP_DEVICE_CONFIG_CHIP_TASK_PRIORITY (K_PRIO_PREEMPT(5)) -#endif // CHIP_DEVICE_CONFIG_CHIP_TASK_PRIORITY - -#ifndef CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE -#define CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE 8192 -#endif // CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE - -#define CHIP_DEVICE_CONFIG_MAX_EVENT_QUEUE_SIZE 64 - -#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_TELEMETRY 0 -#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY 0 -#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY_FULL 0 - -#define CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART 0 - -#ifndef CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART -#define CHIP_DEVICE_CONFIG_ENABLE_PAIRING_AUTOSTART 0 -#else -#define CHIP_DEVICE_CONFIG_ENABLE_PAIRING_AUTOSTART CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART -#endif // CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART - -#ifdef CONFIG_CHIP_ENABLE_DNSSD_SRP -#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT 1 -#ifdef CONFIG_CHIP_ENABLE_DNS_CLIENT -#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT 1 -#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_COMMISSIONABLE_DISCOVERY 1 -#endif // CONFIG_CHIP_ENABLE_DNS_CLIENT -#endif // CONFIG_CHIP_ENABLE_DNSSD_SRP - -#if defined(CONFIG_CHIP_ENABLE_ICD_SUPPORT) && defined(CONFIG_CHIP_THREAD_SSED) -#define CHIP_DEVICE_CONFIG_THREAD_SSED CONFIG_CHIP_THREAD_SSED -#else -#define CHIP_DEVICE_CONFIG_THREAD_SSED 0 -#endif // defined(CONFIG_CHIP_ENABLE_ICD_SUPPORT) && defined(CONFIG_CHIP_THREAD_SSED) - -#ifndef CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL -#ifdef CONFIG_CHIP_ICD_SLOW_POLL_INTERVAL -#define CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL chip::System::Clock::Milliseconds32(CONFIG_CHIP_ICD_SLOW_POLL_INTERVAL) -#endif // CONFIG_CHIP_ICD_SLOW_POLL_INTERVAL -#endif // CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL - -#ifndef CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL -#ifdef CONFIG_CHIP_ICD_FAST_POLLING_INTERVAL -#define CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL chip::System::Clock::Milliseconds32(CONFIG_CHIP_ICD_FAST_POLLING_INTERVAL) -#endif // CONFIG_CHIP_ICD_FAST_POLLING_INTERVAL -#endif // CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL - -#ifdef CONFIG_CHIP_COMMISSIONABLE_DEVICE_TYPE -#define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONABLE_DEVICE_TYPE 1 -#endif // CONFIG_CHIP_COMMISSIONABLE_DEVICE_TYPE - -#ifdef CONFIG_CHIP_EXTENDED_DISCOVERY -#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1 -#endif // CONFIG_CHIP_EXTENDED_DISCOVERY - -#ifndef CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID_LENGTH -#ifdef CONFIG_CHIP_FACTORY_DATA -// UID will be copied from the externally programmed factory data, so we don't know the actual length and we need to assume some max -// boundary. -#define CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID_LENGTH CONFIG_CHIP_FACTORY_DATA_ROTATING_DEVICE_UID_MAX_LEN -#else -// UID will be copied from hex encoded Kconfig option, so we may calculate its length in bytes by subtracting null terminator and -// dividing size by 2. -#define CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID_LENGTH ((sizeof(CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID) - 1) / 2) -#endif // CONFIG_CHIP_FACTORY_DATA -#endif // CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID_LENGTH - -#include diff --git a/src/platform/nxp/zephyr/CHIPDevicePlatformEvent.h b/src/platform/nxp/zephyr/CHIPDevicePlatformEvent.h deleted file mode 100644 index 3b38a1d75cc..00000000000 --- a/src/platform/nxp/zephyr/CHIPDevicePlatformEvent.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * - * Copyright (c) 2024 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Defines platform-specific event types and data for the chip - * Device Layer on Zephyr platforms. - */ - -#pragma once - -#include diff --git a/src/platform/nxp/zephyr/CHIPPlatformConfig.h b/src/platform/nxp/zephyr/CHIPPlatformConfig.h deleted file mode 100644 index d5ed1717bd6..00000000000 --- a/src/platform/nxp/zephyr/CHIPPlatformConfig.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * - * Copyright (c) 2024 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Platform-specific configuration overrides for CHIP on - * Zephyr platform. - */ - -#pragma once - -#ifdef CONFIG_CHIP_CRYPTO_PSA -#include -#endif - -// ==================== General Platform Adaptations ==================== - -#define CHIP_CONFIG_ABORT() abort() - -#define CHIP_CONFIG_PERSISTED_STORAGE_KEY_TYPE const char * -#define CHIP_CONFIG_PERSISTED_STORAGE_MAX_KEY_LENGTH 2 - -#define CHIP_CONFIG_LIFETIIME_PERSISTED_COUNTER_KEY "rc" - -// ==================== Security Adaptations ==================== - -#ifdef CONFIG_CHIP_CRYPTO_PSA -#define CHIP_CONFIG_SHA256_CONTEXT_SIZE sizeof(psa_hash_operation_t) -#define CHIP_CONFIG_SHA256_CONTEXT_ALIGN psa_hash_operation_t -#elif defined(CONFIG_CC3XX_BACKEND) -// Size of the statically allocated context for SHA256 operations in CryptoPAL -// determined empirically. -#define CHIP_CONFIG_SHA256_CONTEXT_SIZE 244 -#else -#define CHIP_CONFIG_SHA256_CONTEXT_SIZE 208 -#endif - -// ==================== General Configuration Overrides ==================== - -#ifndef CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS -#define CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS 8 -#endif // CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS - -#ifndef CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS -#define CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS 8 -#endif // CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS - -#ifndef CHIP_LOG_FILTERING -#define CHIP_LOG_FILTERING 0 -#endif // CHIP_LOG_FILTERING - -#ifndef CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS -#define CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS 1 -#endif // CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS - -#ifndef CHIP_CONFIG_MAX_FABRICS -#define CHIP_CONFIG_MAX_FABRICS 5 -#endif - -#ifdef CONFIG_CHIP_LOG_SIZE_OPTIMIZATION -// Disable some of the too detailed log modules to save flash -#define CHIP_CONFIG_LOG_MODULE_ExchangeManager_DETAIL 0 -#define CHIP_CONFIG_LOG_MODULE_Crypto_DETAIL 0 -#define CHIP_CONFIG_LOG_MODULE_Crypto_PROGRESS 0 -#define CHIP_CONFIG_LOG_MODULE_BDX_DETAIL 0 -#define CHIP_CONFIG_LOG_MODULE_BDX_PROGRESS 0 -#define CHIP_CONFIG_LOG_MODULE_EventLogging_DETAIL 0 -#define CHIP_CONFIG_LOG_MODULE_EventLogging_PROGRESS 0 -#define CHIP_CONFIG_LOG_MODULE_SetupPayload_DETAIL 0 -#define CHIP_CONFIG_LOG_MODULE_SetupPayload_PROGRESS 0 -#define CHIP_CONFIG_LOG_MODULE_CASESessionManager_DETAIL 0 -#define CHIP_CONFIG_LOG_MODULE_CASESessionManager_PROGRESS 0 -#define CHIP_CONFIG_LOG_MODULE_DataManagement_DETAIL 0 -#define CHIP_CONFIG_LOG_MODULE_FabricProvisioning_DETAIL 0 -#define CHIP_CONFIG_LOG_MODULE_chipSystemLayer_DETAIL 0 -#define CHIP_CONFIG_LOG_MODULE_chipSystemLayer_PROGRESS 0 -#define CHIP_CONFIG_LOG_MODULE_Zcl_DETAIL 0 -#define CHIP_CONFIG_LOG_MODULE_SecureChannel_DETAIL 0 -#define CHIP_CONFIG_LOG_MODULE_Ble_DETAIL 0 -#define CHIP_CONFIG_LOG_MODULE_AppServer_DETAIL 0 -#define CHIP_CONFIG_LOG_MODULE_Support_DETAIL 0 -#define CHIP_CONFIG_LOG_MODULE_Support_PROGRESS 0 -#endif - -// Set MRP retry intervals for Thread and Wi-Fi to test-proven values. -#ifndef CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL -#if CHIP_ENABLE_OPENTHREAD -#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (800_ms32) -#else -#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32) -#endif // CHIP_ENABLE_OPENTHREAD -#endif // CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL - -#ifndef CHIP_CONFIG_MRP_LOCAL_IDLE_RETRY_INTERVAL -#if CHIP_ENABLE_OPENTHREAD -#define CHIP_CONFIG_MRP_LOCAL_IDLE_RETRY_INTERVAL (800_ms32) -#else -#define CHIP_CONFIG_MRP_LOCAL_IDLE_RETRY_INTERVAL (2000_ms32) -#endif // CHIP_ENABLE_OPENTHREAD -#endif // CHIP_CONFIG_MRP_LOCAL_IDLE_RETRY_INTERVAL - -#ifndef CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC -#ifdef CONFIG_CHIP_ICD_IDLE_MODE_DURATION -#define CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC CONFIG_CHIP_ICD_IDLE_MODE_DURATION -#endif // CONFIG_CHIP_ICD_IDLE_MODE_DURATION -#endif // CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC - -#ifndef CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS -#ifdef CONFIG_CHIP_ICD_ACTIVE_MODE_DURATION -#define CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS CONFIG_CHIP_ICD_ACTIVE_MODE_DURATION -#endif // CONFIG_CHIP_ICD_ACTIVE_MODE_DURATION -#endif // CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS - -#ifndef CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS -#ifdef CONFIG_CHIP_ICD_ACTIVE_MODE_THRESHOLD -#define CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS CONFIG_CHIP_ICD_ACTIVE_MODE_THRESHOLD -#endif // CONFIG_CHIP_ICD_ACTIVE_MODE_THRESHOLD -#endif // CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS - -#ifndef CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC -#ifdef CONFIG_CHIP_ICD_CLIENTS_PER_FABRIC -#define CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC CONFIG_CHIP_ICD_CLIENTS_PER_FABRIC -#endif // CONFIG_CHIP_ICD_CLIENTS_PER_FABRIC -#endif // CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC - -#include -#include diff --git a/src/platform/nxp/zephyr/ConfigurationManagerImpl.h b/src/platform/nxp/zephyr/ConfigurationManagerImpl.h deleted file mode 100644 index 846671b64b1..00000000000 --- a/src/platform/nxp/zephyr/ConfigurationManagerImpl.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * - * Copyright (c) 2024 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Provides an implementation of the ConfigurationManager object - * for Zephyr platforms. - */ - -#pragma once - -#include diff --git a/src/platform/nxp/zephyr/ConnectivityManagerImpl.cpp b/src/platform/nxp/zephyr/ConnectivityManagerImpl.cpp deleted file mode 100644 index 33cdbcd9e47..00000000000 --- a/src/platform/nxp/zephyr/ConnectivityManagerImpl.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* - * - * Copyright (c) 2024 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include -#include -#include -#include -#include - -#ifndef CONFIG_ARCH_POSIX -#include -#endif - -#include - -#if INET_CONFIG_ENABLE_TCP_ENDPOINT -#include -#endif - -#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE -#include -#endif - -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD -#include -#include -#endif - -using namespace ::chip::Inet; -using namespace ::chip::DeviceLayer::Internal; - -namespace chip { -namespace DeviceLayer { - -namespace { -CHIP_ERROR JoinLeaveMulticastGroup(net_if * iface, const Inet::IPAddress & address, - UDPEndPointImplSockets::MulticastOperation operation) -{ -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD - if (net_if_l2(iface) == &NET_L2_GET_NAME(OPENTHREAD)) - { - const otIp6Address otAddress = ToOpenThreadIP6Address(address); - const auto handler = operation == UDPEndPointImplSockets::MulticastOperation::kJoin ? otIp6SubscribeMulticastAddress - : otIp6UnsubscribeMulticastAddress; - otError error; - - ThreadStackMgr().LockThreadStack(); - error = handler(openthread_get_default_instance(), &otAddress); - ThreadStackMgr().UnlockThreadStack(); - - return MapOpenThreadError(error); - } -#endif - -#if CHIP_DEVICE_CONFIG_ENABLE_WIFI || CHIP_DEVICE_CONFIG_ENABLE_ETHERNET - // The following code should also be valid for other interface types, such as Ethernet, - // but they are not officially supported, so for now enable it for Wi-Fi only. - const in6_addr in6Addr = InetUtils::ToZephyrAddr(address); - - if (operation == UDPEndPointImplSockets::MulticastOperation::kJoin) - { - net_if_mcast_addr * maddr = net_if_ipv6_maddr_add(iface, &in6Addr); - - if (maddr && !net_if_ipv6_maddr_is_joined(maddr)) - { - net_if_ipv6_maddr_join(iface, maddr); - } - } - else if (operation == UDPEndPointImplSockets::MulticastOperation::kLeave) - { - VerifyOrReturnError(net_if_ipv6_maddr_rm(iface, &in6Addr), CHIP_ERROR_INVALID_ADDRESS); - } - else - { - return CHIP_ERROR_INCORRECT_STATE; - } -#endif - - return CHIP_NO_ERROR; -} -} // namespace - -ConnectivityManagerImpl ConnectivityManagerImpl::sInstance; - -CHIP_ERROR ConnectivityManagerImpl::_Init() -{ -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD - GenericConnectivityManagerImpl_Thread::_Init(); -#endif - -#if CHIP_DEVICE_CONFIG_ENABLE_WIFI - ReturnErrorOnFailure(InitWiFi()); -#elif CHIP_DEVICE_CONFIG_ENABLE_ETHERNET - ReturnErrorOnFailure(InitEth()); -#endif - -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD || CHIP_DEVICE_CONFIG_ENABLE_WIFI || CHIP_DEVICE_CONFIG_ENABLE_ETHERNET - UDPEndPointImplSockets::SetMulticastGroupHandler( - [](InterfaceId interfaceId, const IPAddress & address, UDPEndPointImplSockets::MulticastOperation operation) { - if (interfaceId.IsPresent()) - { - net_if * iface = InetUtils::GetInterface(interfaceId); - VerifyOrReturnError(iface != nullptr, INET_ERROR_UNKNOWN_INTERFACE); - - return JoinLeaveMulticastGroup(iface, address, operation); - } - - // If the interface is not specified, join or leave the multicast group on all interfaces. - for (int i = 1; net_if * iface = net_if_get_by_index(i); i++) - { - ReturnErrorOnFailure(JoinLeaveMulticastGroup(iface, address, operation)); - } - - return CHIP_NO_ERROR; - }); -#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD || CHIP_DEVICE_CONFIG_ENABLE_WIFI - - return CHIP_NO_ERROR; -} - -void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) -{ - // Forward the event to the generic base classes as needed. -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD - GenericConnectivityManagerImpl_Thread::_OnPlatformEvent(event); -#endif -} - -} // namespace DeviceLayer -} // namespace chip diff --git a/src/platform/nxp/zephyr/ConnectivityManagerImpl.h b/src/platform/nxp/zephyr/ConnectivityManagerImpl.h deleted file mode 100644 index 96c0fe303d3..00000000000 --- a/src/platform/nxp/zephyr/ConnectivityManagerImpl.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * - * Copyright (c) 2024 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include -#include -#if INET_CONFIG_ENABLE_TCP_ENDPOINT -#include -#endif -#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE -#include -#else -#include -#endif - -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD -#include -#else -#include -#endif - -#if CHIP_DEVICE_CONFIG_ENABLE_WIFI -#include -#else -#include -#endif - -#if CHIP_DEVICE_CONFIG_ENABLE_ETHERNET -#include "Ethernet/ConnectivityManagerImplEth.h" -#endif - -#include - -namespace chip { -namespace Inet { -class IPAddress; -} // namespace Inet -} // namespace chip - -namespace chip { -namespace DeviceLayer { - -/** - * Concrete implementation of the ConnectivityManager singleton object for Zephyr platforms. - */ -class ConnectivityManagerImpl final : public ConnectivityManager, - public Internal::GenericConnectivityManagerImpl, - public Internal::GenericConnectivityManagerImpl_UDP, -#if INET_CONFIG_ENABLE_TCP_ENDPOINT - public Internal::GenericConnectivityManagerImpl_TCP, -#endif -#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE - public Internal::GenericConnectivityManagerImpl_BLE, -#else - public Internal::GenericConnectivityManagerImpl_NoBLE, -#endif -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD - public Internal::GenericConnectivityManagerImpl_Thread, -#else - public Internal::GenericConnectivityManagerImpl_NoThread, -#endif -#if CHIP_DEVICE_CONFIG_ENABLE_ETHERNET - public ConnectivityManagerImplEth, -#endif -#if CHIP_DEVICE_CONFIG_ENABLE_WIFI - public ConnectivityManagerImplWiFi -#else - public Internal::GenericConnectivityManagerImpl_NoWiFi -#endif -{ - // Allow the ConnectivityManager interface class to delegate method calls to - // the implementation methods provided by this class. - friend class ConnectivityManager; - -private: - // ===== Members that implement the ConnectivityManager abstract interface. - - CHIP_ERROR _Init(void); - void _OnPlatformEvent(const ChipDeviceEvent * event); - - // ===== Members for internal use by the following friends. - - friend ConnectivityManager & ConnectivityMgr(void); - friend ConnectivityManagerImpl & ConnectivityMgrImpl(void); - - static ConnectivityManagerImpl sInstance; -}; - -/** - * Returns the public interface of the ConnectivityManager singleton object. - * - * chip applications should use this to access features of the ConnectivityManager object - * that are common to all platforms. - */ -inline ConnectivityManager & ConnectivityMgr(void) -{ - return ConnectivityManagerImpl::sInstance; -} - -/** - * Returns the platform-specific implementation of the ConnectivityManager singleton object. - * - * chip applications can use this to gain access to features of the ConnectivityManager - * that are specific to the NXP platform. - */ -inline ConnectivityManagerImpl & ConnectivityMgrImpl(void) -{ - return ConnectivityManagerImpl::sInstance; -} - -} // namespace DeviceLayer -} // namespace chip diff --git a/src/platform/nxp/zephyr/DiagnosticDataProviderImplNxp.cpp b/src/platform/nxp/zephyr/DiagnosticDataProviderImplNxp.cpp deleted file mode 100644 index e1f8b0534ec..00000000000 --- a/src/platform/nxp/zephyr/DiagnosticDataProviderImplNxp.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * - * Copyright (c) 2024-2025 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Provides an implementation of the DiagnosticDataProvider object - * for NXP Zephyr platform. - */ - -#include "DiagnosticDataProviderImplNxp.h" - -#ifdef CONFIG_WIFI_NXP -#include -#include -#endif - -namespace chip { -namespace DeviceLayer { - -DiagnosticDataProvider & GetDiagnosticDataProviderImpl() -{ - return DiagnosticDataProviderImplNxp::GetDefaultInstance(); -} - -DiagnosticDataProviderImplNxp & DiagnosticDataProviderImplNxp::GetDefaultInstance() -{ - static DiagnosticDataProviderImplNxp sInstance; - return sInstance; -} - -#ifdef CONFIG_WIFI_NXP -CHIP_ERROR DiagnosticDataProviderImplNxp::GetWiFiBssId(MutableByteSpan & value) -{ - WiFiManager::WiFiInfo info; - ReturnErrorOnFailure(WiFiManager::Instance().GetWiFiInfo(info)); - VerifyOrReturnError(sizeof(info.mBssId) < value.size(), CHIP_ERROR_BUFFER_TOO_SMALL); - - memcpy(value.data(), info.mBssId, sizeof(info.mBssId)); - value.reduce_size(sizeof(info.mBssId)); - - return CHIP_NO_ERROR; -} - -CHIP_ERROR -DiagnosticDataProviderImplNxp::GetWiFiSecurityType(app::Clusters::WiFiNetworkDiagnostics::SecurityTypeEnum & securityType) -{ - using app::Clusters::WiFiNetworkDiagnostics::SecurityTypeEnum; - - WiFiManager::WiFiInfo info; - CHIP_ERROR err = WiFiManager::Instance().GetWiFiInfo(info); - securityType = info.mSecurityType; - return err; -} - -CHIP_ERROR DiagnosticDataProviderImplNxp::GetWiFiVersion(app::Clusters::WiFiNetworkDiagnostics::WiFiVersionEnum & wiFiVersion) -{ - WiFiManager::WiFiInfo info; - CHIP_ERROR err = WiFiManager::Instance().GetWiFiInfo(info); - wiFiVersion = info.mWiFiVersion; - return err; -} - -CHIP_ERROR DiagnosticDataProviderImplNxp::GetWiFiChannelNumber(uint16_t & channelNumber) -{ - WiFiManager::WiFiInfo info; - CHIP_ERROR err = WiFiManager::Instance().GetWiFiInfo(info); - channelNumber = info.mChannel; - return err; -} - -CHIP_ERROR DiagnosticDataProviderImplNxp::GetWiFiRssi(int8_t & rssi) -{ - WiFiManager::WiFiInfo info; - CHIP_ERROR err = WiFiManager::Instance().GetWiFiInfo(info); - rssi = info.mRssi; - return err; -} - -CHIP_ERROR DiagnosticDataProviderImplNxp::GetWiFiCurrentMaxRate(uint64_t & currentMaxRate) -{ - WiFiManager::WiFiInfo info; - CHIP_ERROR err = WiFiManager::Instance().GetWiFiInfo(info); - // mCurrentPhyRate Value in MB - currentMaxRate = info.mCurrentPhyRate * 1000000; - return err; -} - -CHIP_ERROR DiagnosticDataProviderImplNxp::GetWiFiBeaconLostCount(uint32_t & beaconLostCount) -{ - WiFiManager::NetworkStatistics stats; - CHIP_ERROR err = WiFiManager::Instance().GetNetworkStatistics(stats); - beaconLostCount = stats.mBeaconsLostCount; - return err; -} - -CHIP_ERROR DiagnosticDataProviderImplNxp::GetWiFiBeaconRxCount(uint32_t & beaconRxCount) -{ - WiFiManager::NetworkStatistics stats; - CHIP_ERROR err = WiFiManager::Instance().GetNetworkStatistics(stats); - beaconRxCount = stats.mBeaconsSuccessCount; - return err; -} - -CHIP_ERROR DiagnosticDataProviderImplNxp::GetWiFiPacketMulticastRxCount(uint32_t & packetMulticastRxCount) -{ - WiFiManager::NetworkStatistics stats; - CHIP_ERROR err = WiFiManager::Instance().GetNetworkStatistics(stats); - packetMulticastRxCount = stats.mPacketMulticastRxCount; - return err; -} - -CHIP_ERROR DiagnosticDataProviderImplNxp::GetWiFiPacketMulticastTxCount(uint32_t & packetMulticastTxCount) -{ - WiFiManager::NetworkStatistics stats; - CHIP_ERROR err = WiFiManager::Instance().GetNetworkStatistics(stats); - packetMulticastTxCount = stats.mPacketMulticastTxCount; - return err; -} - -CHIP_ERROR DiagnosticDataProviderImplNxp::GetWiFiPacketUnicastRxCount(uint32_t & packetUnicastRxCount) -{ - WiFiManager::NetworkStatistics stats; - CHIP_ERROR err = WiFiManager::Instance().GetNetworkStatistics(stats); - packetUnicastRxCount = stats.mPacketUnicastRxCount; - return err; -} - -CHIP_ERROR DiagnosticDataProviderImplNxp::GetWiFiPacketUnicastTxCount(uint32_t & packetUnicastTxCount) -{ - WiFiManager::NetworkStatistics stats; - CHIP_ERROR err = WiFiManager::Instance().GetNetworkStatistics(stats); - packetUnicastTxCount = stats.mPacketUnicastTxCount; - return err; -} - -CHIP_ERROR DiagnosticDataProviderImplNxp::GetWiFiOverrunCount(uint64_t & overrunCount) -{ - WiFiManager::NetworkStatistics stats; - CHIP_ERROR err = WiFiManager::Instance().GetNetworkStatistics(stats); - overrunCount = static_cast(stats.mOverRunCount); - return err; -} - -CHIP_ERROR DiagnosticDataProviderImplNxp::ResetWiFiNetworkDiagnosticsCounts() -{ - net_if * iface = InetUtils::GetWiFiInterface(); - VerifyOrReturnError(iface != nullptr, INET_ERROR_UNKNOWN_INTERFACE); - - if (net_mgmt(NET_REQUEST_STATS_RESET_WIFI, iface, NULL, 0)) - { - ChipLogError(DeviceLayer, "WiFi statistics reset failed"); - return CHIP_ERROR_INTERNAL; - } - - return CHIP_NO_ERROR; -} -#endif - -} // namespace DeviceLayer -} // namespace chip diff --git a/src/platform/nxp/zephyr/FactoryDataProviderImpl.cpp b/src/platform/nxp/zephyr/FactoryDataProviderImpl.cpp index 1cb6fcdc1ef..6b1e347a284 100644 --- a/src/platform/nxp/zephyr/FactoryDataProviderImpl.cpp +++ b/src/platform/nxp/zephyr/FactoryDataProviderImpl.cpp @@ -19,7 +19,7 @@ /* Includes */ /* -------------------------------------------------------------------------- */ -#include "FactoryDataProviderImpl.h" +#include /* mbedtls */ #include "mbedtls/aes.h" @@ -101,8 +101,8 @@ CHIP_ERROR FactoryDataProviderImpl::SignWithDacKey(const ByteSpan & digestToSign Crypto::P256ECDSASignature signature; Crypto::P256Keypair keypair; - VerifyOrReturnError(IsSpanUsable(outSignBuffer), CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(IsSpanUsable(digestToSign), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(!outSignBuffer.empty(), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(!digestToSign.empty(), CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(outSignBuffer.size() >= signature.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL); // In a non-exemplary implementation, the public key is not needed here. It is used here merely because diff --git a/src/platform/nxp/zephyr/InetPlatformConfig.h b/src/platform/nxp/zephyr/InetPlatformConfig.h deleted file mode 100644 index 644cdea6b20..00000000000 --- a/src/platform/nxp/zephyr/InetPlatformConfig.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * - * Copyright (c) 2024 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Platform-specific configuration overrides for the CHIP Inet - * Layer on Zephyr platform. - * - */ - -#pragma once - -#include diff --git a/src/platform/nxp/zephyr/SystemPlatformConfig.h b/src/platform/nxp/zephyr/SystemPlatformConfig.h deleted file mode 100644 index c111745cf2d..00000000000 --- a/src/platform/nxp/zephyr/SystemPlatformConfig.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * - * Copyright (c) 2024 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Platform-specific configuration overrides for the CHIP System - * Layer on Zephyr platform. - * - */ - -#pragma once - -#include - -#define CHIP_SYSTEM_CONFIG_THREAD_LOCAL_STORAGE 0 -#define CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKET_EXTENSIONS 0 diff --git a/src/platform/nxp/zephyr/args.gni b/src/platform/nxp/zephyr/args.gni deleted file mode 100644 index e24f997ccdf..00000000000 --- a/src/platform/nxp/zephyr/args.gni +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2024 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -declare_args() { - chip_malloc_sys_heap = false - - # Enable factory data support - chip_enable_factory_data = false -} diff --git a/src/python_testing/MinimalRepresentation.py b/src/python_testing/MinimalRepresentation.py index d69f921b36d..9c1dbb5f327 100644 --- a/src/python_testing/MinimalRepresentation.py +++ b/src/python_testing/MinimalRepresentation.py @@ -19,7 +19,7 @@ from TC_DeviceConformance import DeviceConformanceTests -from matter.testing.conformance import ConformanceDecision +from matter.testing.conformance import ConformanceAssessmentData, ConformanceDecision from matter.testing.global_attribute_ids import GlobalAttributeIds from matter.testing.matter_testing import MatterBaseTest, async_test_body, default_matter_test_main from matter.tlv import uint @@ -62,12 +62,14 @@ def GenerateMinimals(self, ignore_in_progress: bool, is_ci: bool) -> dict[uint, all_command_list = cluster[GlobalAttributeIds.ACCEPTED_COMMAND_LIST_ID] + \ cluster[GlobalAttributeIds.GENERATED_COMMAND_LIST_ID] accepted_command_list = cluster[GlobalAttributeIds.ACCEPTED_COMMAND_LIST_ID] + revision = cluster[GlobalAttributeIds.CLUSTER_REVISION_ID] + conformance_assessment_data = ConformanceAssessmentData(feature_map, attribute_list, all_command_list, revision) # All optional features feature_masks = [1 << i for i in range(32) if feature_map & (1 << i)] for f in feature_masks: xml_feature = self.xml_clusters[cluster_id].features[f] - conformance_decision = xml_feature.conformance(feature_map, attribute_list, all_command_list) + conformance_decision = xml_feature.conformance(conformance_assessment_data) if conformance_decision == ConformanceDecision.OPTIONAL: minimal.feature_masks.append(f) @@ -79,7 +81,7 @@ def GenerateMinimals(self, ignore_in_progress: bool, is_ci: bool) -> dict[uint, minimal.attribute_ids.append(attribute_id) continue xml_attribute = self.xml_clusters[cluster_id].attributes[attribute_id] - conformance_decision = xml_attribute.conformance(feature_map, attribute_list, all_command_list) + conformance_decision = xml_attribute.conformance(conformance_assessment_data) if conformance_decision == ConformanceDecision.OPTIONAL: minimal.attribute_ids.append(attribute_id) @@ -91,7 +93,7 @@ def GenerateMinimals(self, ignore_in_progress: bool, is_ci: bool) -> dict[uint, minimal.attribute_ids.append(command_id) continue xml_command = self.xml_clusters[cluster_id].accepted_commands[command_id] - conformance_decision = xml_command.conformance(feature_map, attribute_list, all_command_list) + conformance_decision = xml_command.conformance(conformance_assessment_data) if conformance_decision == ConformanceDecision.OPTIONAL: minimal.command_ids.append(command_id) diff --git a/src/python_testing/TC_ACL_2_10.py b/src/python_testing/TC_ACL_2_10.py index bcd8ba6c4cf..389b33d3a5a 100644 --- a/src/python_testing/TC_ACL_2_10.py +++ b/src/python_testing/TC_ACL_2_10.py @@ -21,7 +21,7 @@ # factory-reset: true # quiet: true # app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json -# app-ready-pattern: "Server initialization complete" +# app-ready-pattern: "APP STATUS: Starting event loop" # script-args: > # --storage-path admin_storage.json # --commissioning-method on-network @@ -32,10 +32,8 @@ # --endpoint 0 # === END CI TEST ARGUMENTS === - import logging import random -import time from mobly import asserts @@ -226,38 +224,7 @@ async def test_TC_ACL_2_10(self): self.step(9) # Reboot DUT # Check if restart flag file is available (indicates test runner supports app restart) - restart_flag_file = self.get_restart_flag_file() - - if not restart_flag_file: - # No restart flag file: ask user to manually reboot - self.wait_for_user_input(prompt_msg="Reboot the DUT. Press Enter when ready.\n") - - # After manual reboot, expire previous sessions so that we can re-establish connections - logging.info("Expiring sessions after manual device reboot") - self.th1.ExpireSessions(self.dut_node_id) - self.th2.ExpireSessions(self.dut_node_id) - logging.info("Manual device reboot completed") - - else: - try: - # Create the restart flag file to signal the test runner - with open(restart_flag_file, "w") as f: - f.write("restart") - logging.info("Created restart flag file to signal app restart") - - # The test runner will automatically wait for the app-ready-pattern before continuing - # Waiting 1 second after the app-ready-pattern is detected as we need to wait a tad longer for the app to be ready and stable, otherwise TH2 connection fails later on in test step 14. - time.sleep(1) - - # Expire sessions and re-establish connections - self.th1.ExpireSessions(self.dut_node_id) - self.th2.ExpireSessions(self.dut_node_id) - - logging.info("App restart completed successfully") - - except Exception as e: - logging.error(f"Failed to restart app: {e}") - asserts.fail(f"App restart failed: {e}") + await self.request_device_reboot() self.step(10) # TH1 reads DUT Endpoint 0 AccessControl cluster ACL attribute diff --git a/src/python_testing/TC_AVSM_2_18.py b/src/python_testing/TC_AVSM_2_18.py new file mode 100644 index 00000000000..2755d7be532 --- /dev/null +++ b/src/python_testing/TC_AVSM_2_18.py @@ -0,0 +1,227 @@ +# +# Copyright (c) 2025 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. + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${CAMERA_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# app-ready-pattern: "APP STATUS: Starting event loop" +# 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 +# --endpoint 1 +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import logging + +from mobly import asserts +from TC_AVSMTestBase import AVSMTestBase + +import matter.clusters as Clusters +from matter.testing.decorators import has_feature, run_if_endpoint_matches +from matter.testing.matter_testing import MatterBaseTest +from matter.testing.runner import TestStep, default_matter_test_main + +log = logging.getLogger(__name__) + + +class TC_AVSM_2_18(MatterBaseTest, AVSMTestBase): + + def desc_TC_AVSM_2_18(self) -> str: + return "[TC-AVSM-2.18] Validate persistence of allocated video streams with DUT" + + def steps_TC_AVSM_2_18(self) -> list[TestStep]: + return [ + TestStep(1, "Commissioning, already done", is_commissioning=True), + TestStep(2, "TH reads FeatureMap attribute from CameraAVStreamManagement Cluster on DUT. Verify F_VDO is supported."), + TestStep(3, "TH reads AllocatedVideoStreams attribute from CameraAVStreamManagement Cluster on DUT. Verify the number of allocated video streams in the list is 0."), + TestStep(4, "TH reads StreamUsagePriorities attribute from CameraAVStreamManagement Cluster on DUT. Store this value in aStreamUsagePriorities."), + TestStep(5, "TH reads RateDistortionTradeOffPoints attribute from CameraAVStreamManagement Cluster on DUT. Store this value in aRateDistortionTradeOffPoints."), + TestStep(6, "TH reads MinViewportResolution attribute from CameraAVStreamManagement Cluster on DUT. Store this value in aMinViewportResolution."), + TestStep(7, "TH reads VideoSensorParams attribute from CameraAVStreamManagement Cluster on DUT. Store this value in aVideoSensorParams."), + TestStep(8, "TH reads MaxEncodedPixelrate attribute from CameraAVStreamManagement Cluster on DUT. Store this value in aMaxEncodedPixelRate."), + TestStep(9, "If F_WMARK is supported, TH sets it's local aWatermark to True, otherwise this is Null."), + TestStep(10, "If F_OSD is supported, TH sets its local aOSD to True, otherwise this is Null."), + TestStep(11, "TH sets StreamUsage from aStreamUsagePriorities. TH sets VideoCodec, MinResolution, MaxResolution, MinBitRate, MaxBitRate conforming with aRateDistortionTradeOffPoints. TH sets MinFrameRate, MaxFrameRate conforming with aVideoSensorParams. TH sets the KeyFrameInterval = 4000. TH sets WatermarkEnabled to aWatermark, TH also sets OSDEnabled to aOSD. TH sends the VideoStreamAllocate command with these arguments."), + TestStep(12, "TH reads AllocatedVideoStreams attribute from CameraAVStreamManagement Cluster on DUT. Verify the number of allocated video streams in the list is 1."), + TestStep(13, "TH reboots the DUT."), + TestStep(14, "TH waits for the DUT to come back online."), + TestStep(15, "TH reads AllocatedVideoStreams attribute from CameraAVStreamManagement Cluster on DUT. Verify the number of allocated video streams in the list is 1 and the stream info is identical to what was provided in step 11."), + TestStep(16, "TH sends the VideoStreamDeallocate command with VideoStreamID set to myStreamID."), + TestStep(17, "TH reads AllocatedVideoStreams attribute from CameraAVStreamManagement Cluster on DUT. Verify the number of allocated video streams in the list is 0."), + TestStep(18, "TH reboots the DUT."), + TestStep(19, "TH waits for the DUT to come back online."), + TestStep(20, "TH reads AllocatedVideoStreams attribute from CameraAVStreamManagement Cluster on DUT. Verify the number of allocated video streams in the list is 0."), + ] + + def pics_TC_AVSM_2_18(self) -> list[str]: + return ["AVSM.S", "AVSM.S.F_VDO"] + + @run_if_endpoint_matches( + has_feature(Clusters.CameraAvStreamManagement, Clusters.CameraAvStreamManagement.Bitmaps.Feature.kVideo) + ) + async def test_TC_AVSM_2_18(self): + endpoint = self.get_endpoint() + cluster = Clusters.CameraAvStreamManagement + attr = Clusters.CameraAvStreamManagement.Attributes + commands = Clusters.CameraAvStreamManagement.Commands + + self.step(1) + + self.step(2) + feature_map = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.FeatureMap) + has_f_vdo = (feature_map & cluster.Bitmaps.Feature.kVideo) != 0 + asserts.assert_true(has_f_vdo, "FeatureMap F_VDO is not set") + + self.step(3) + allocated_video_streams = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedVideoStreams) + asserts.assert_equal(len(allocated_video_streams), 0, "AllocatedVideoStreams should be empty") + + self.step(4) + stream_usage_priorities = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.StreamUsagePriorities) + asserts.assert_greater(len(stream_usage_priorities), 0, "StreamUsagePriorities should not be empty") + + self.step(5) + rate_distortion_trade_off_points = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.RateDistortionTradeOffPoints) + asserts.assert_greater(len(rate_distortion_trade_off_points), 0, "RateDistortionTradeOffPoints should not be empty") + + self.step(6) + min_viewport_resolution = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.MinViewportResolution) + log.info(f"Rx'd MinViewportResolution: {min_viewport_resolution}") + + self.step(7) + video_sensor_params = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.VideoSensorParams) + log.info(f"Rx'd VideoSensorParams: {video_sensor_params}") + + self.step(8) + max_encoded_pixel_rate = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.MaxEncodedPixelRate) + log.info(f"Rx'd MaxEncodedPixelRate: {max_encoded_pixel_rate}") + + self.step(9) + has_f_wmark = (feature_map & cluster.Bitmaps.Feature.kWatermark) != 0 + watermark_enabled = True if has_f_wmark else None + + self.step(10) + has_f_osd = (feature_map & cluster.Bitmaps.Feature.kOnScreenDisplay) != 0 + osd_enabled = True if has_f_osd else None + + self.step(11) + # Select valid parameters based on device capabilities + stream_usage = stream_usage_priorities[0] + trade_off_point = rate_distortion_trade_off_points[0] + video_codec = trade_off_point.codec + min_resolution = min_viewport_resolution + min_bit_rate = trade_off_point.minBitRate + max_bit_rate = trade_off_point.minBitRate + min_frame_rate = 30 + max_frame_rate = video_sensor_params.maxFPS + key_frame_interval = 4000 + + cmd = commands.VideoStreamAllocate( + streamUsage=stream_usage, + videoCodec=video_codec, + minFrameRate=min_frame_rate, + maxFrameRate=max_frame_rate, + minResolution=min_resolution, + maxResolution=cluster.Structs.VideoResolutionStruct( + width=video_sensor_params.sensorWidth, height=video_sensor_params.sensorHeight + ), + minBitRate=min_bit_rate, + maxBitRate=max_bit_rate, + keyFrameInterval=key_frame_interval, + watermarkEnabled=watermark_enabled, + OSDEnabled=osd_enabled + ) + + resp = await self.send_single_cmd(endpoint=endpoint, cmd=cmd) + my_stream_id = resp.videoStreamID + asserts.assert_is_not_none(my_stream_id, "VideoStreamID should not be None") + + # Store the allocated stream info for comparison after reboot + allocated_stream_info = cluster.Structs.VideoStreamStruct( + videoStreamID=my_stream_id, + streamUsage=stream_usage, + videoCodec=video_codec, + minResolution=min_resolution, + maxResolution=cluster.Structs.VideoResolutionStruct( + width=video_sensor_params.sensorWidth, height=video_sensor_params.sensorHeight + ), + minBitRate=min_bit_rate, + maxBitRate=max_bit_rate, + minFrameRate=min_frame_rate, + maxFrameRate=max_frame_rate, + keyFrameInterval=key_frame_interval, + watermarkEnabled=watermark_enabled, + OSDEnabled=osd_enabled, + referenceCount=0 + ) + + self.step(12) + allocated_video_streams = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedVideoStreams) + asserts.assert_equal(len(allocated_video_streams), 1, "AllocatedVideoStreams should have 1 entry") + + self.step(13) + await self.request_device_reboot() + self.step(14) + # Wait for device to be online is handled by request_device_reboot + + self.step(15) + allocated_video_streams = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedVideoStreams) + asserts.assert_equal(len(allocated_video_streams), 1, "AllocatedVideoStreams should have 1 entry after reboot") + # Compare the structs, fields should be the same, except referenceCount, which is not persisted + retrieved_stream = allocated_video_streams[0] + asserts.assert_equal(retrieved_stream.videoStreamID, allocated_stream_info.videoStreamID, "videoStreamID mismatch") + asserts.assert_equal(retrieved_stream.streamUsage, allocated_stream_info.streamUsage, "streamUsage mismatch") + asserts.assert_equal(retrieved_stream.videoCodec, allocated_stream_info.videoCodec, "videoCodec mismatch") + asserts.assert_equal(retrieved_stream.minResolution, allocated_stream_info.minResolution, "minResolution mismatch") + asserts.assert_equal(retrieved_stream.maxResolution, allocated_stream_info.maxResolution, "maxResolution mismatch") + asserts.assert_equal(retrieved_stream.minBitRate, allocated_stream_info.minBitRate, "minBitRate mismatch") + asserts.assert_equal(retrieved_stream.maxBitRate, allocated_stream_info.maxBitRate, "maxBitRate mismatch") + asserts.assert_equal(retrieved_stream.minFrameRate, allocated_stream_info.minFrameRate, "minFrameRate mismatch") + asserts.assert_equal(retrieved_stream.maxFrameRate, allocated_stream_info.maxFrameRate, "maxFrameRate mismatch") + asserts.assert_equal(retrieved_stream.keyFrameInterval, allocated_stream_info.keyFrameInterval, "keyFrameInterval mismatch") + asserts.assert_equal(retrieved_stream.watermarkEnabled, allocated_stream_info.watermarkEnabled, "watermarkEnabled mismatch") + asserts.assert_equal(retrieved_stream.OSDEnabled, allocated_stream_info.OSDEnabled, "OSDEnabled mismatch") + + self.step(16) + await self.send_single_cmd(cmd=commands.VideoStreamDeallocate(videoStreamID=my_stream_id), endpoint=endpoint) + + self.step(17) + allocated_video_streams = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedVideoStreams) + asserts.assert_equal(len(allocated_video_streams), 0, "AllocatedVideoStreams should be empty after deallocate") + + self.step(18) + await self.request_device_reboot() + self.step(19) + + self.step(20) + allocated_video_streams = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedVideoStreams) + asserts.assert_equal(len(allocated_video_streams), 0, "AllocatedVideoStreams should be empty after reboot") + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_AVSM_2_19.py b/src/python_testing/TC_AVSM_2_19.py new file mode 100644 index 00000000000..b8a0adaf472 --- /dev/null +++ b/src/python_testing/TC_AVSM_2_19.py @@ -0,0 +1,181 @@ +# +# Copyright (c) 2025 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. + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${CAMERA_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# app-ready-pattern: "APP STATUS: Starting event loop" +# 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 +# --endpoint 1 +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import logging + +from mobly import asserts +from TC_AVSMTestBase import AVSMTestBase + +import matter.clusters as Clusters +from matter.testing.decorators import has_feature, run_if_endpoint_matches +from matter.testing.matter_testing import MatterBaseTest +from matter.testing.runner import TestStep, default_matter_test_main + +log = logging.getLogger(__name__) + + +class TC_AVSM_2_19(MatterBaseTest, AVSMTestBase): + + def desc_TC_AVSM_2_19(self) -> str: + return "[TC-AVSM-2.19] Validate persistence of allocated audio streams with DUT" + + def steps_TC_AVSM_2_19(self) -> list[TestStep]: + return [ + TestStep(1, "Commissioning, already done", is_commissioning=True), + TestStep(2, "TH reads FeatureMap attribute from CameraAVStreamManagement Cluster on DUT. Verify F_ADO is supported."), + TestStep(3, "TH reads AllocatedAudioStreams attribute from CameraAVStreamManagement Cluster on DUT. Verify the number of allocated audio streams in the list is 0."), + TestStep(4, "TH reads MicrophoneCapabilities attribute from CameraAVStreamManagement Cluster on DUT. Store this value in aMicrophoneCapabilities."), + TestStep(5, "The TH selects a value for BitRate depending on the first codec in aMicrophoneCapabilities.supportedCodecs. Store this value in aBitRate"), + TestStep(6, "TH reads StreamUsagePriorities attribute from CameraAVStreamManagement Cluster on DUT. Store this value in aStreamUsagePriorities."), + TestStep(7, "TH sends the AudioStreamAllocate command with valid values of AudioCodec, ChannelCount, SampleRate and BitDepth from aMicrophoneCapabilities, a StreamUsage from aStreamUsagePriorities and aBitRate set as above."), + TestStep(8, "TH reads AllocatedAudioStreams attribute from CameraAVStreamManagement Cluster on DUT. Verify the number of allocated audio streams in the list is 1."), + TestStep(9, "TH reboots the DUT."), + TestStep(10, "TH waits for the DUT to come back online."), + TestStep(11, "TH reads AllocatedAudioStreams attribute from CameraAVStreamManagement Cluster on DUT. Verify the number of allocated audio streams in the list is 1 and the stream info is identical to what was provided in step 7."), + TestStep(12, "TH sends the AudioStreamDeallocate command with AudioStreamID set to myStreamID."), + TestStep(13, "TH reads AllocatedAudioStreams attribute from CameraAVStreamManagement Cluster on DUT. Verify the number of allocated audio streams in the list is 0."), + TestStep(14, "TH reboots the DUT."), + TestStep(15, "TH waits for the DUT to come back online."), + TestStep(16, "TH reads AllocatedAudioStreams attribute from CameraAVStreamManagement Cluster on DUT. Verify the number of allocated audio streams in the list is 0."), + ] + + def pics_TC_AVSM_2_19(self) -> list[str]: + return ["AVSM.S", "AVSM.S.F_ADO"] + + @run_if_endpoint_matches( + has_feature(Clusters.CameraAvStreamManagement, Clusters.CameraAvStreamManagement.Bitmaps.Feature.kAudio) + ) + async def test_TC_AVSM_2_19(self): + endpoint = self.get_endpoint() + cluster = Clusters.CameraAvStreamManagement + attr = Clusters.CameraAvStreamManagement.Attributes + commands = Clusters.CameraAvStreamManagement.Commands + + self.step(1) + + self.step(2) + feature_map = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.FeatureMap) + has_f_ado = (feature_map & cluster.Bitmaps.Feature.kAudio) != 0 + asserts.assert_true(has_f_ado, "FeatureMap F_ADO is not set") + + self.step(3) + allocated_audio_streams = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedAudioStreams) + asserts.assert_equal(len(allocated_audio_streams), 0, "AllocatedAudioStreams should be empty") + + self.step(4) + microphone_capabilities = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.MicrophoneCapabilities) + asserts.assert_greater(len(microphone_capabilities.supportedCodecs), 0, + "MicrophoneCapabilities.supportedCodecs should not be empty") + + self.step(5) + first_codec = microphone_capabilities.supportedCodecs[0] + bit_rate = 30000 if first_codec == cluster.Enums.AudioCodecEnum.kOpus else 40000 + + self.step(6) + stream_usage_priorities = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.StreamUsagePriorities) + asserts.assert_greater(len(stream_usage_priorities), 0, "StreamUsagePriorities should not be empty") + + self.step(7) + stream_usage = stream_usage_priorities[0] + audio_codec = first_codec + channel_count = microphone_capabilities.maxNumberOfChannels + sample_rate = microphone_capabilities.supportedSampleRates[0] + bit_depth = microphone_capabilities.supportedBitDepths[0] + + cmd = commands.AudioStreamAllocate( + streamUsage=stream_usage, + audioCodec=audio_codec, + channelCount=channel_count, + sampleRate=sample_rate, + bitRate=bit_rate, + bitDepth=bit_depth, + ) + + resp = await self.send_single_cmd(endpoint=endpoint, cmd=cmd) + my_stream_id = resp.audioStreamID + asserts.assert_is_not_none(my_stream_id, "AudioStreamID should not be None") + + allocated_stream_info = cluster.Structs.AudioStreamStruct( + audioStreamID=my_stream_id, + streamUsage=stream_usage, + audioCodec=audio_codec, + channelCount=channel_count, + sampleRate=sample_rate, + bitRate=bit_rate, + bitDepth=bit_depth, + referenceCount=0 + ) + + self.step(8) + allocated_audio_streams = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedAudioStreams) + asserts.assert_equal(len(allocated_audio_streams), 1, "AllocatedAudioStreams should have 1 entry") + + self.step(9) + await self.request_device_reboot() + self.step(10) + + self.step(11) + allocated_audio_streams = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedAudioStreams) + asserts.assert_equal(len(allocated_audio_streams), 1, "AllocatedAudioStreams should have 1 entry after reboot") + retrieved_stream = allocated_audio_streams[0] + asserts.assert_equal(retrieved_stream.audioStreamID, allocated_stream_info.audioStreamID, "audioStreamID mismatch") + asserts.assert_equal(retrieved_stream.streamUsage, allocated_stream_info.streamUsage, "streamUsage mismatch") + asserts.assert_equal(retrieved_stream.audioCodec, allocated_stream_info.audioCodec, "audioCodec mismatch") + asserts.assert_equal(retrieved_stream.channelCount, allocated_stream_info.channelCount, "channelCount mismatch") + asserts.assert_equal(retrieved_stream.sampleRate, allocated_stream_info.sampleRate, "sampleRate mismatch") + asserts.assert_equal(retrieved_stream.bitDepth, allocated_stream_info.bitDepth, "bitDepth mismatch") + asserts.assert_equal(retrieved_stream.bitRate, allocated_stream_info.bitRate, "bitRate mismatch") + + self.step(12) + await self.send_single_cmd(cmd=commands.AudioStreamDeallocate(audioStreamID=my_stream_id), endpoint=endpoint) + + self.step(13) + allocated_audio_streams = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedAudioStreams) + asserts.assert_equal(len(allocated_audio_streams), 0, "AllocatedAudioStreams should be empty after deallocate") + + self.step(14) + await self.request_device_reboot() + self.step(15) + + self.step(16) + allocated_audio_streams = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedAudioStreams) + asserts.assert_equal(len(allocated_audio_streams), 0, "AllocatedAudioStreams should be empty after reboot") + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_AVSM_2_20.py b/src/python_testing/TC_AVSM_2_20.py new file mode 100644 index 00000000000..06909899d29 --- /dev/null +++ b/src/python_testing/TC_AVSM_2_20.py @@ -0,0 +1,183 @@ +# +# Copyright (c) 2025 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. + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${CAMERA_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# app-ready-pattern: "APP STATUS: Starting event loop" +# 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 +# --endpoint 1 +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import logging + +from mobly import asserts +from TC_AVSMTestBase import AVSMTestBase + +import matter.clusters as Clusters +from matter.testing.decorators import has_feature, run_if_endpoint_matches +from matter.testing.matter_testing import MatterBaseTest +from matter.testing.runner import TestStep, default_matter_test_main + +log = logging.getLogger(__name__) + + +class TC_AVSM_2_20(MatterBaseTest, AVSMTestBase): + + def desc_TC_AVSM_2_20(self) -> str: + return "[TC-AVSM-2.20] Validate persistence of allocated snapshot streams with DUT" + + def steps_TC_AVSM_2_20(self) -> list[TestStep]: + return [ + TestStep(1, "Commissioning, already done", is_commissioning=True), + TestStep(2, "TH reads FeatureMap attribute from CameraAVStreamManagement Cluster on DUT. Verify F_SNP is supported."), + TestStep(3, "TH reads AllocatedSnapshotStreams attribute from CameraAVStreamManagement Cluster on DUT. Verify the number of allocated snapshot streams in the list is 0."), + TestStep(4, "TH reads SnapshotCapabilities attribute from CameraAVStreamManagement Cluster on DUT. Store this value in aSnapshotCapabilities."), + TestStep(5, "If F_WMARK is supported, TH sets its local aWatermark to True, otherwise this is Null."), + TestStep(6, "If F_OSD is supported, TH sets its local aOSD to True, otherwise this is Null."), + TestStep(7, "TH sends the SnapshotStreamAllocate command with valid values of ImageCodec, MaxFrameRate, MinResolution=MaxResolution=Resolution from aSnapshotCapabilities, WatermarkEnabled to aWatermark, OSDEnabled to aOSD, and Quality set to 90."), + TestStep(8, "TH reads AllocatedSnapshotStreams attribute from CameraAVStreamManagement Cluster on DUT. Verify the number of allocated snapshot streams in the list is 1."), + TestStep(9, "TH reboots the DUT."), + TestStep(10, "TH waits for the DUT to come back online."), + TestStep(11, "TH reads AllocatedSnapshotStreams attribute from CameraAVStreamManagement Cluster on DUT. Verify the number of allocated snapshot streams in the list is 1 and the stream info is identical to what was provided in step 7."), + TestStep(12, "TH sends the SnapshotStreamDeallocate command with SnapshotStreamID set to myStreamID."), + TestStep(13, "TH reads AllocatedSnapshotStreams attribute from CameraAVStreamManagement Cluster on DUT. Verify the number of allocated snapshot streams in the list is 0."), + TestStep(14, "TH reboots the DUT."), + TestStep(15, "TH waits for the DUT to come back online."), + TestStep(16, "TH reads AllocatedSnapshotStreams attribute from CameraAVStreamManagement Cluster on DUT. Verify the number of allocated snapshot streams in the list is 0."), + ] + + def pics_TC_AVSM_2_20(self) -> list[str]: + return ["AVSM.S", "AVSM.S.F_SNP"] + + @run_if_endpoint_matches( + has_feature(Clusters.CameraAvStreamManagement, Clusters.CameraAvStreamManagement.Bitmaps.Feature.kSnapshot) + ) + async def test_TC_AVSM_2_20(self): + endpoint = self.get_endpoint() + cluster = Clusters.CameraAvStreamManagement + attr = Clusters.CameraAvStreamManagement.Attributes + commands = Clusters.CameraAvStreamManagement.Commands + + self.step(1) + + self.step(2) + feature_map = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.FeatureMap) + has_f_snp = (feature_map & cluster.Bitmaps.Feature.kSnapshot) != 0 + asserts.assert_true(has_f_snp, "FeatureMap F_SNP is not set") + + self.step(3) + allocated_snapshot_streams = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedSnapshotStreams) + asserts.assert_equal(len(allocated_snapshot_streams), 0, "AllocatedSnapshotStreams should be empty") + + self.step(4) + snapshot_capabilities = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.SnapshotCapabilities) + asserts.assert_greater(len(snapshot_capabilities), 0, "SnapshotCapabilities should not be empty") + + self.step(5) + has_f_wmark = (feature_map & cluster.Bitmaps.Feature.kWatermark) != 0 + watermark_enabled = True if has_f_wmark else None + + self.step(6) + has_f_osd = (feature_map & cluster.Bitmaps.Feature.kOnScreenDisplay) != 0 + osd_enabled = True if has_f_osd else None + + self.step(7) + capability = snapshot_capabilities[0] + image_codec = capability.imageCodec + frame_rate = capability.maxFrameRate + resolution = capability.resolution + quality = 90 + + cmd = commands.SnapshotStreamAllocate( + imageCodec=image_codec, + maxFrameRate=frame_rate, + minResolution=resolution, + maxResolution=resolution, + quality=quality, + watermarkEnabled=watermark_enabled, + OSDEnabled=osd_enabled, + ) + + resp = await self.send_single_cmd(endpoint=endpoint, cmd=cmd) + my_stream_id = resp.snapshotStreamID + asserts.assert_is_not_none(my_stream_id, "SnapshotStreamID should not be None") + + allocated_stream_info = cluster.Structs.SnapshotStreamStruct( + snapshotStreamID=my_stream_id, + imageCodec=image_codec, + frameRate=frame_rate, + minResolution=resolution, + maxResolution=resolution, + watermarkEnabled=watermark_enabled, + OSDEnabled=osd_enabled, + quality=quality, + referenceCount=0 + ) + + self.step(8) + allocated_snapshot_streams = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedSnapshotStreams) + asserts.assert_equal(len(allocated_snapshot_streams), 1, "AllocatedSnapshotStreams should have 1 entry") + + self.step(9) + await self.request_device_reboot() + self.step(10) + + self.step(11) + allocated_snapshot_streams = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedSnapshotStreams) + asserts.assert_equal(len(allocated_snapshot_streams), 1, "AllocatedSnapshotStreams should have 1 entry after reboot") + retrieved_stream = allocated_snapshot_streams[0] + asserts.assert_equal(retrieved_stream.snapshotStreamID, allocated_stream_info.snapshotStreamID, "snapshotStreamID mismatch") + asserts.assert_equal(retrieved_stream.imageCodec, allocated_stream_info.imageCodec, "imageCodec mismatch") + asserts.assert_equal(retrieved_stream.frameRate, allocated_stream_info.frameRate, "frameRate mismatch") + asserts.assert_equal(retrieved_stream.minResolution, allocated_stream_info.minResolution, "minResolution mismatch") + asserts.assert_equal(retrieved_stream.maxResolution, allocated_stream_info.maxResolution, "maxResolution mismatch") + asserts.assert_equal(retrieved_stream.watermarkEnabled, allocated_stream_info.watermarkEnabled, "watermarkEnabled mismatch") + asserts.assert_equal(retrieved_stream.OSDEnabled, allocated_stream_info.OSDEnabled, "OSDEnabled mismatch") + asserts.assert_equal(retrieved_stream.quality, allocated_stream_info.quality, "quality mismatch") + + self.step(12) + await self.send_single_cmd(cmd=commands.SnapshotStreamDeallocate(snapshotStreamID=my_stream_id), endpoint=endpoint) + + self.step(13) + allocated_snapshot_streams = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedSnapshotStreams) + asserts.assert_equal(len(allocated_snapshot_streams), 0, "AllocatedSnapshotStreams should be empty after deallocate") + + self.step(14) + await self.request_device_reboot() + self.step(15) + + self.step(16) + allocated_snapshot_streams = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedSnapshotStreams) + asserts.assert_equal(len(allocated_snapshot_streams), 0, "AllocatedSnapshotStreams should be empty after reboot") + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_AVSM_2_21.py b/src/python_testing/TC_AVSM_2_21.py new file mode 100644 index 00000000000..e79549c391f --- /dev/null +++ b/src/python_testing/TC_AVSM_2_21.py @@ -0,0 +1,118 @@ +# +# Copyright (c) 2025 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. + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${CAMERA_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# app-ready-pattern: "APP STATUS: Starting event loop" +# 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 +# --endpoint 1 +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import logging +import random + +from mobly import asserts +from TC_AVSMTestBase import AVSMTestBase + +import matter.clusters as Clusters +from matter.testing.decorators import has_feature, run_if_endpoint_matches +from matter.testing.matter_testing import MatterBaseTest +from matter.testing.runner import TestStep, default_matter_test_main + +log = logging.getLogger(__name__) + + +class TC_AVSM_2_21(MatterBaseTest, AVSMTestBase): + + def desc_TC_AVSM_2_21(self) -> str: + return "[TC-AVSM-2.21] Validate persistence of stream usage priorities with DUT" + + def steps_TC_AVSM_2_21(self) -> list[TestStep]: + return [ + TestStep(1, "Commissioning, already done", is_commissioning=True), + TestStep(2, "TH reads FeatureMap attribute from CameraAVStreamManagement Cluster on DUT. Verify F_VDO is supported."), + TestStep(3, "TH reads AllocatedVideoStreams attribute from CameraAVStreamManagement Cluster on DUT. Verify the number of allocated video streams in the list is 0."), + TestStep(4, "TH reads SupportedStreamUsages attribute from CameraAVStreamManagement Cluster on DUT. Store this value in aSupportedStreamUsages."), + TestStep(5, "TH sends the SetStreamPriorities command with StreamPriorities set as a subset of aSupportedStreamUsages."), + TestStep(6, "TH reads StreamUsagePriorities attribute from CameraAVStreamManagement Cluster on DUT. Store this value in aStreamUsagePriorities."), + TestStep(7, "TH reboots the DUT."), + TestStep(8, "TH waits for the DUT to come back online."), + TestStep(9, "TH reads StreamUsagePriorities attribute from CameraAVStreamManagement Cluster on DUT. Verify this value is same as aStreamUsagePriorities."), + ] + + def pics_TC_AVSM_2_21(self) -> list[str]: + return ["AVSM.S", "AVSM.S.F_VDO"] + + @run_if_endpoint_matches( + has_feature(Clusters.CameraAvStreamManagement, Clusters.CameraAvStreamManagement.Bitmaps.Feature.kVideo) + ) + async def test_TC_AVSM_2_21(self): + endpoint = self.get_endpoint() + cluster = Clusters.CameraAvStreamManagement + attr = Clusters.CameraAvStreamManagement.Attributes + commands = Clusters.CameraAvStreamManagement.Commands + + self.step(1) + + self.step(2) + feature_map = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.FeatureMap) + has_f_vdo = (feature_map & cluster.Bitmaps.Feature.kVideo) != 0 + asserts.assert_true(has_f_vdo, "FeatureMap F_VDO is not set") + + self.step(3) + allocated_video_streams = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedVideoStreams) + asserts.assert_equal(len(allocated_video_streams), 0, "AllocatedVideoStreams should be empty") + + self.step(4) + supported_stream_usages = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.SupportedStreamUsages) + asserts.assert_greater(len(supported_stream_usages), 0, "SupportedStreamUsages should not be empty") + + self.step(5) + # Send a shuffled subset of supported usages + new_priorities = random.sample(supported_stream_usages, k=random.randint(1, len(supported_stream_usages))) + await self.send_single_cmd(cmd=commands.SetStreamPriorities(streamPriorities=new_priorities), endpoint=endpoint) + + self.step(6) + stream_usage_priorities = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.StreamUsagePriorities) + asserts.assert_equal(stream_usage_priorities, new_priorities, "StreamUsagePriorities not set correctly") + + self.step(7) + await self.request_device_reboot() + self.step(8) + + self.step(9) + stream_usage_priorities_after_reboot = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attr.StreamUsagePriorities) + asserts.assert_equal(stream_usage_priorities_after_reboot, new_priorities, + "StreamUsagePriorities did not persist after reboot") + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_AVSUMTestBase.py b/src/python_testing/TC_AVSUMTestBase.py index 8edef17311f..c75b79a308d 100644 --- a/src/python_testing/TC_AVSUMTestBase.py +++ b/src/python_testing/TC_AVSUMTestBase.py @@ -26,6 +26,17 @@ class AVSUMTestBase: + SPEC_PANMIN_MIN_VALUE = -180 + SPEC_PANMIN_MAX_VALUE = 0 + SPEC_PANMAX_MIN_VALUE = 1 + SPEC_PANMAX_MAX_VALUE = 180 + SPEC_TILTMIN_MIN_VALUE = -180 + SPEC_TILTMIN_MAX_VALUE = 0 + SPEC_TILTMAX_MIN_VALUE = 1 + SPEC_TILTMAX_MAX_VALUE = 180 + SPEC_ZOOMMAX_MIN_VALUE = 2 + SPEC_ZOOMMAX_MAX_VALUE = 100 + has_feature_dptz = False has_feature_mpan = False has_feature_mtilt = False diff --git a/src/python_testing/TC_AVSUM_2_1.py b/src/python_testing/TC_AVSUM_2_1.py index 698aab77cff..981b1ed2b7e 100644 --- a/src/python_testing/TC_AVSUM_2_1.py +++ b/src/python_testing/TC_AVSUM_2_1.py @@ -105,8 +105,9 @@ async def test_TC_AVSUM_2_1(self): asserts.assert_in(attributes.ZoomMax.attribute_id, attribute_list, "ZoomMax attribute is a mandatory attribute if MZOOM.") zoom_max_dut = await self.read_avsum_attribute_expect_success(endpoint, attributes.ZoomMax) - asserts.assert_less_equal(zoom_max_dut, 100, "ZoomMax is not in valid range.") - asserts.assert_greater_equal(zoom_max_dut, 2, "ZoomMax must be at least 2.") + asserts.assert_less_equal(zoom_max_dut, self.SPEC_ZOOMMAX_MAX_VALUE, "ZoomMax is not in valid range.") + asserts.assert_greater_equal(zoom_max_dut, self.SPEC_ZOOMMAX_MIN_VALUE, + f"ZoomMax must be at least {self.SPEC_ZOOMMAX_MIN_VALUE}.") else: logging.info("MZOOM Feature not supported. Test step skipped") self.skip_step(3) @@ -116,15 +117,15 @@ async def test_TC_AVSUM_2_1(self): asserts.assert_in(attributes.TiltMin.attribute_id, attribute_list, "TiltMin attribute is a mandatory attribute if MTILT.") tilt_min_dut = await self.read_avsum_attribute_expect_success(endpoint, attributes.TiltMin) - asserts.assert_less_equal(tilt_min_dut, 179, "TiltMin is not in valid range.") - asserts.assert_greater_equal(tilt_min_dut, -180, "TiltMin is not in valid range.") + asserts.assert_less_equal(tilt_min_dut, self.SPEC_TILTMIN_MAX_VALUE, "TiltMin is not in valid range.") + asserts.assert_greater_equal(tilt_min_dut, self.SPEC_TILTMIN_MIN_VALUE, "TiltMin is not in valid range.") self.step(5) asserts.assert_in(attributes.TiltMax.attribute_id, attribute_list, "TiltMax attribute is a mandatory attribute if MTILT.") tilt_max_dut = await self.read_avsum_attribute_expect_success(endpoint, attributes.TiltMax) - asserts.assert_less_equal(tilt_max_dut, 180, "TiltMin is not in valid range.") - asserts.assert_greater_equal(tilt_max_dut, -179, "TiltMin is not in valid range.") + asserts.assert_less_equal(tilt_max_dut, self.SPEC_TILTMAX_MAX_VALUE, "TiltMax is not in valid range.") + asserts.assert_greater_equal(tilt_max_dut, self.SPEC_TILTMAX_MIN_VALUE, "TiltMax is not in valid range.") else: logging.info("MTILT Feature not supported. Test steps skipped") self.skip_step(4) @@ -135,15 +136,15 @@ async def test_TC_AVSUM_2_1(self): asserts.assert_in(attributes.PanMin.attribute_id, attribute_list, "PanMin attribute is a mandatory attribute if MPAN.") pan_min_dut = await self.read_avsum_attribute_expect_success(endpoint, attributes.PanMin) - asserts.assert_less_equal(pan_min_dut, 179, "PanMin is not in valid range.") - asserts.assert_greater_equal(pan_min_dut, -180, "PanMin is not in valid range.") + asserts.assert_less_equal(pan_min_dut, self.SPEC_PANMIN_MAX_VALUE, "PanMin is not in valid range.") + asserts.assert_greater_equal(pan_min_dut, self.SPEC_PANMIN_MIN_VALUE, "PanMin is not in valid range.") self.step(7) asserts.assert_in(attributes.PanMax.attribute_id, attribute_list, "PanMax attribute is a mandatory attribute if MPAN.") pan_max_dut = await self.read_avsum_attribute_expect_success(endpoint, attributes.PanMax) - asserts.assert_less_equal(pan_max_dut, 180, "PanMax is not in valid range.") - asserts.assert_greater_equal(pan_max_dut, -179, "PanMax is not in valid range.") + asserts.assert_less_equal(pan_max_dut, self.SPEC_PANMAX_MAX_VALUE, "PanMax is not in valid range.") + asserts.assert_greater_equal(pan_max_dut, self.SPEC_PANMAX_MIN_VALUE, "PanMax is not in valid range.") else: logging.info("MPAN Feature not supported. Test steps skipped") self.skip_step(6) diff --git a/src/python_testing/TC_AVSUM_2_2.py b/src/python_testing/TC_AVSUM_2_2.py index d3a55d8f22c..70ede360a24 100644 --- a/src/python_testing/TC_AVSUM_2_2.py +++ b/src/python_testing/TC_AVSUM_2_2.py @@ -142,15 +142,15 @@ async def test_TC_AVSUM_2_2(self): asserts.assert_in(attributes.PanMin.attribute_id, attribute_list, "PanMin attribute is a mandatory attribute if MPAN.") pan_min_dut = await self.read_avsum_attribute_expect_success(endpoint, attributes.PanMin) - asserts.assert_less_equal(pan_min_dut, 179, "PanMin is not in valid range.") - asserts.assert_greater_equal(pan_min_dut, -180, "PanMin is not in valid range.") + asserts.assert_less_equal(pan_min_dut, self.SPEC_PANMIN_MAX_VALUE, "PanMin is not in valid range.") + asserts.assert_greater_equal(pan_min_dut, self.SPEC_PANMIN_MIN_VALUE, "PanMin is not in valid range.") self.step(6) asserts.assert_in(attributes.PanMax.attribute_id, attribute_list, "PanMax attribute is a mandatory attribute if MPAN.") pan_max_dut = await self.read_avsum_attribute_expect_success(endpoint, attributes.PanMax) - asserts.assert_less_equal(pan_max_dut, 180, "PanMax is not in valid range.") - asserts.assert_greater_equal(pan_max_dut, -179, "PanMax is not in valid range.") + asserts.assert_less_equal(pan_max_dut, self.SPEC_PANMAX_MAX_VALUE, "PanMax is not in valid range.") + asserts.assert_greater_equal(pan_max_dut, self.SPEC_PANMAX_MIN_VALUE, "PanMax is not in valid range.") self.step(7) # Create new Value for Pan @@ -214,15 +214,15 @@ async def test_TC_AVSUM_2_2(self): asserts.assert_in(attributes.TiltMin.attribute_id, attribute_list, "TiltMin attribute is a mandatory attribute if MTILT.") tilt_min_dut = await self.read_avsum_attribute_expect_success(endpoint, attributes.TiltMin) - asserts.assert_less_equal(tilt_min_dut, 179, "TiltMin is not in valid range.") - asserts.assert_greater_equal(tilt_min_dut, -180, "TiltMin is not in valid range.") + asserts.assert_less_equal(tilt_min_dut, self.SPEC_TILTMIN_MAX_VALUE, "TiltMin is not in valid range.") + asserts.assert_greater_equal(tilt_min_dut, self.SPEC_TILTMIN_MIN_VALUE, "TiltMin is not in valid range.") self.step(16) asserts.assert_in(attributes.TiltMax.attribute_id, attribute_list, "TiltMax attribute is a mandatory attribute if MTILT.") tilt_max_dut = await self.read_avsum_attribute_expect_success(endpoint, attributes.TiltMax) - asserts.assert_less_equal(tilt_max_dut, 180, "TiltMax is not in valid range.") - asserts.assert_greater_equal(tilt_max_dut, -179, "TiltMax is not in valid range.") + asserts.assert_less_equal(tilt_max_dut, self.SPEC_TILTMAX_MAX_VALUE, "TiltMax is not in valid range.") + asserts.assert_greater_equal(tilt_max_dut, self.SPEC_TILTMAX_MIN_VALUE, "TiltMax is not in valid range.") self.step(17) # Create new Value for Tilt @@ -271,8 +271,8 @@ async def test_TC_AVSUM_2_2(self): asserts.assert_in(attributes.ZoomMax.attribute_id, attribute_list, "ZoomMax attribute is a mandatory attribute if MZOOM.") zoom_max_dut = await self.read_avsum_attribute_expect_success(endpoint, attributes.ZoomMax) - asserts.assert_less_equal(zoom_max_dut, 100, "ZoomMax is not in valid range.") - asserts.assert_greater_equal(zoom_max_dut, 2, "ZoomMax is not in valid range.") + asserts.assert_less_equal(zoom_max_dut, self.SPEC_ZOOMMAX_MAX_VALUE, "ZoomMax is not in valid range.") + asserts.assert_greater_equal(zoom_max_dut, self.SPEC_ZOOMMAX_MIN_VALUE, "ZoomMax is not in valid range.") self.step(24) # Create new Value for Zoom diff --git a/src/python_testing/TC_AVSUM_2_3.py b/src/python_testing/TC_AVSUM_2_3.py index 321a667a0eb..44dca9dc3e4 100644 --- a/src/python_testing/TC_AVSUM_2_3.py +++ b/src/python_testing/TC_AVSUM_2_3.py @@ -139,15 +139,15 @@ async def test_TC_AVSUM_2_3(self): asserts.assert_in(attributes.PanMin.attribute_id, attribute_list, "PanMin attribute is a mandatory attribute if MPAN.") pan_min_dut = await self.read_avsum_attribute_expect_success(endpoint, attributes.PanMin) - asserts.assert_less_equal(pan_min_dut, 179, "PanMin is not in valid range.") - asserts.assert_greater_equal(pan_min_dut, -180, "PanMin is not in valid range.") + asserts.assert_less_equal(pan_min_dut, self.SPEC_PANMIN_MAX_VALUE, "PanMin is not in valid range.") + asserts.assert_greater_equal(pan_min_dut, self.SPEC_PANMIN_MIN_VALUE, "PanMin is not in valid range.") self.step(6) asserts.assert_in(attributes.PanMax.attribute_id, attribute_list, "PanMax attribute is a mandatory attribute if MPAN.") pan_max_dut = await self.read_avsum_attribute_expect_success(endpoint, attributes.PanMax) - asserts.assert_less_equal(pan_max_dut, 180, "PanMax is not in valid range.") - asserts.assert_greater_equal(pan_max_dut, -179, "PanMax is not in valid range.") + asserts.assert_less_equal(pan_max_dut, self.SPEC_PANMAX_MAX_VALUE, "PanMax is not in valid range.") + asserts.assert_greater_equal(pan_max_dut, self.SPEC_PANMAX_MIN_VALUE, "PanMax is not in valid range.") self.step(7) # Create new Value for Pan @@ -204,15 +204,15 @@ async def test_TC_AVSUM_2_3(self): asserts.assert_in(attributes.TiltMin.attribute_id, attribute_list, "TiltMin attribute is a mandatory attribute if MTILT.") tilt_min_dut = await self.read_avsum_attribute_expect_success(endpoint, attributes.TiltMin) - asserts.assert_less_equal(tilt_min_dut, 179, "TiltMin is not in valid range.") - asserts.assert_greater_equal(tilt_min_dut, -180, "TiltMin is not in valid range.") + asserts.assert_less_equal(tilt_min_dut, self.SPEC_TILTMIN_MAX_VALUE, "TiltMin is not in valid range.") + asserts.assert_greater_equal(tilt_min_dut, self.SPEC_TILTMIN_MIN_VALUE, "TiltMin is not in valid range.") self.step(14) asserts.assert_in(attributes.TiltMax.attribute_id, attribute_list, "TiltMax attribute is a mandatory attribute if MTILT.") tilt_max_dut = await self.read_avsum_attribute_expect_success(endpoint, attributes.TiltMax) - asserts.assert_less_equal(tilt_max_dut, 180, "TiltMax is not in valid range.") - asserts.assert_greater_equal(tilt_max_dut, -179, "TiltMax is not in valid range.") + asserts.assert_less_equal(tilt_max_dut, self.SPEC_TILTMAX_MAX_VALUE, "TiltMax is not in valid range.") + asserts.assert_greater_equal(tilt_max_dut, self.SPEC_TILTMAX_MIN_VALUE, "TiltMax is not in valid range.") self.step(15) # Create new Value for Tilt @@ -268,8 +268,8 @@ async def test_TC_AVSUM_2_3(self): asserts.assert_in(attributes.ZoomMax.attribute_id, attribute_list, "ZoomMax attribute is a mandatory attribute if MZOOM.") zoom_max_dut = await self.read_avsum_attribute_expect_success(endpoint, attributes.ZoomMax) - asserts.assert_less_equal(zoom_max_dut, 100, "ZoomMax is not in valid range.") - asserts.assert_greater_equal(zoom_max_dut, 2, "ZoomMax is not in valid range.") + asserts.assert_less_equal(zoom_max_dut, self.SPEC_ZOOMMAX_MAX_VALUE, "ZoomMax is not in valid range.") + asserts.assert_greater_equal(zoom_max_dut, self.SPEC_ZOOMMAX_MIN_VALUE, "ZoomMax is not in valid range.") self.step(22) # Create new Value for Zoom diff --git a/src/python_testing/TC_AccessChecker.py b/src/python_testing/TC_AccessChecker.py index 01d53d0cb40..a2a588a0f14 100644 --- a/src/python_testing/TC_AccessChecker.py +++ b/src/python_testing/TC_AccessChecker.py @@ -48,6 +48,19 @@ # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # --bool-arg ci_only_linux_skip_ota_cluster_disallowed_for_certification:True # --tests test_TC_ACE_2_3 +# run4: +# app: ${ALL_CLUSTERS_APP} +# factory-reset: true +# quiet: true +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# 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 +# --tests test_TC_ACE_2_4 # === END CI TEST ARGUMENTS === import logging @@ -57,6 +70,7 @@ import matter.clusters as Clusters from matter.clusters.Attribute import ValueDecodeFailure +from matter.exceptions import ChipStackError from matter.interaction_model import InteractionModelError, Status from matter.testing.basic_composition import BasicCompositionTests from matter.testing.global_attribute_ids import (GlobalAttributeIds, is_standard_attribute_id, is_standard_cluster_id, @@ -66,11 +80,14 @@ from matter.testing.spec_parsing import XmlCluster from matter.tlv import uint +log = logging.getLogger(__name__) + class AccessTestType(Enum): READ = auto() WRITE = auto() INVOKE = auto() + SUBSCRIBE = auto() def step_number_with_privilege(step: int, substep: str, privilege: Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum) -> str: @@ -128,10 +145,11 @@ async def setup_class(self): self.TH2 = fabric_admin.NewController(nodeId=self.TH2_nodeid) # Both the tests in this suite are potentially long-running if there are a large number of attributes on the DUT - # and the network is slow. Set the default to 3 minutes to account for this. + # and the network is slow. TC_ACE_2_4 (subscription test) is especially long as it tests ALL attributes. + # Set the default to 25 minutes to account for comprehensive subscription testing. @property def default_timeout(self) -> int: - return 180 + return 1500 # 25 minutes for comprehensive subscription testing @async_test_body async def setup_test(self): @@ -273,6 +291,103 @@ async def _run_read_access_test_for_cluster_privilege(self, endpoint_id, cluster if ret is None: self.success = False + async def _subscribe_single_attribute_check_success(self, endpoint_id, cluster_id, attribute_id, attribute, cluster_class, privilege, test_name): + """Helper to subscribe to an attribute expecting success.""" + try: + subscription = await self.TH2.ReadAttribute( + nodeId=self.dut_node_id, + attributes=[(endpoint_id, attribute)], + reportInterval=(0, 30), + keepSubscriptions=False, + fabricFiltered=False + ) + + if subscription.subscriptionId is None: + self.record_error(test_name=test_name, + location=AttributePathLocation(endpoint_id=endpoint_id, + cluster_id=cluster_id, attribute_id=attribute_id), + problem=f"Subscription activation failed - expected success with privilege {privilege}") + self.success = False + return False + + log.info(f"Successfully established subscription (ID: {subscription.subscriptionId}) with privilege {privilege}") + subscription.Shutdown() + return True + + except ChipStackError as e: # chipstack-ok + # Unexpected ChipStackError + log.error(f"Unexpected ChipStackError subscribing to attribute {attribute}: {e}") + self.record_error(test_name=test_name, + location=AttributePathLocation(endpoint_id=endpoint_id, + cluster_id=cluster_id, attribute_id=attribute_id), + problem=f"Unexpected ChipStackError during subscription: {e} (error code: 0x{e.err:08X})") + self.success = False + return False + + async def _subscribe_single_attribute_expect_error(self, endpoint_id, cluster_id, attribute_id, attribute, cluster_class, privilege, test_name): + """Helper to subscribe to an attribute expecting UnsupportedAccess error.""" + try: + subscription = await self.TH2.ReadAttribute( + nodeId=self.dut_node_id, + attributes=[(endpoint_id, attribute)], + reportInterval=(0, 30), + keepSubscriptions=False, + fabricFiltered=False + ) + + # Subscription succeeded but should have failed + subscription.Shutdown() + self.record_error(test_name=test_name, + location=AttributePathLocation(endpoint_id=endpoint_id, + cluster_id=cluster_id, attribute_id=attribute_id), + problem=f"Subscription succeeded but should have failed with privilege {privilege}") + self.success = False + return False + + except ChipStackError as e: # chipstack-ok + if e.err == 0x00000580: # INVALID_ACTION - some attributes don't support subscription + # This occurs for attributes that cannot be subscribed to when testing with insufficient privileges. + # The attributes are write-only or have special subscription restrictions. + # These are the current clusters where this is noticed: + # - AccessControl + # - NetworkCommissioning + # - CameraAvStreamManagement + # - OperationalCredentials + log.warning( + f"INVALID_ACTION: {cluster_class.__name__}.{attribute.__name__} (Cluster=0x{cluster_id:04X}, Attribute=0x{attribute_id:04X}, Endpoint={endpoint_id}, Privilege={privilege.name})") + return None # Indicates skip + # Unexpected ChipStackError + log.error(f"Unexpected ChipStackError subscribing to attribute {attribute}: {e}") + self.record_error(test_name=test_name, + location=AttributePathLocation(endpoint_id=endpoint_id, + cluster_id=cluster_id, attribute_id=attribute_id), + problem=f"Unexpected ChipStackError during subscription: {e} (error code: 0x{e.err:08X})") + self.success = False + return False + + async def _run_subscribe_access_test_for_cluster_privilege(self, endpoint_id, cluster_id, device_cluster_data, xml_cluster: XmlCluster, privilege: Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum): + """Tests subscription access control by verifying subscriptions can be established. + + This follows the same pattern as _run_read_access_test_for_cluster_privilege, + but uses subscription parameters in the ReadAttribute call. + """ + for attribute_id in checkable_attributes(cluster_id, device_cluster_data, xml_cluster): + spec_requires = xml_cluster.attributes[attribute_id].read_access + attribute = Clusters.ClusterObjects.ALL_ATTRIBUTES[cluster_id][attribute_id] + cluster_class = Clusters.ClusterObjects.ALL_CLUSTERS[cluster_id] + test_name = f'Subscribe access checker - {privilege}' + + log.info(f"Subscribing to attribute {attribute} cluster {xml_cluster.name} privilege {privilege}") + + if operation_allowed(spec_requires, privilege): + result = await self._subscribe_single_attribute_check_success( + endpoint_id, cluster_id, attribute_id, attribute, cluster_class, privilege, test_name) + else: + result = await self._subscribe_single_attribute_expect_error( + endpoint_id, cluster_id, attribute_id, attribute, cluster_class, privilege, test_name) + if result is None: # Skip this attribute (INVALID_ACTION) + continue + async def _run_write_access_test_for_cluster_privilege(self, endpoint_id, cluster_id, cluster, xml_cluster: XmlCluster, privilege: Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum, wildcard_read): for attribute_id in checkable_attributes(cluster_id, cluster, xml_cluster): spec_requires = xml_cluster.attributes[attribute_id].write_access @@ -348,7 +463,7 @@ async def run_access_test(self, test_type: AccessTestType): self.step(check_step) enum = Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum in_progress_clusters = [Clusters.ColorControl.id] - privilege_enum = [p for p in enum if p != enum.kUnknownEnumValue] + privilege_enum = [p for p in enum if p != enum.kUnknownEnumValue and p != enum.kProxyView] for privilege in privilege_enum: logging.info(f"Testing for {privilege}") self.step(step_number_with_privilege(check_step, 'a', privilege)) @@ -368,6 +483,8 @@ async def run_access_test(self, test_type: AccessTestType): await self._run_write_access_test_for_cluster_privilege(endpoint_id, cluster_id, device_cluster_data, xml_cluster, privilege, wildcard_read) elif test_type == AccessTestType.INVOKE: await self._maybe_run_command_access_test_for_cluster_privilege(endpoint_id, cluster_id, device_cluster_data, xml_cluster, privilege) + elif test_type == AccessTestType.SUBSCRIBE: + await self._run_subscribe_access_test_for_cluster_privilege(endpoint_id, cluster_id, device_cluster_data, xml_cluster, privilege) else: self.fail_current_test("Unsupported test type") if not self.success: @@ -379,7 +496,7 @@ def steps_TC_ACE_2_1(self): TestStep(2, "TH_commissioner reads the ACL attribute (done during test setup)"), TestStep(3, "Repeat steps 3a and 3b for each permission level")] enum = Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum - privilege_enum = [p for p in enum if p != enum.kUnknownEnumValue] + privilege_enum = [p for p in enum if p != enum.kUnknownEnumValue and p != enum.kProxyView] for p in privilege_enum: steps.append(TestStep(step_number_with_privilege(3, 'a', p), "TH_commissioner gives TH_second_commissioner the specified privilege")) @@ -402,7 +519,7 @@ def steps_TC_ACE_2_2(self): TestStep(4, "TH_second_controller performs a wildcard read"), TestStep(5, "Repeat steps 5a and 5b for each permission level")] enum = Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum - privilege_enum = [p for p in enum if p != enum.kUnknownEnumValue] + privilege_enum = [p for p in enum if p != enum.kUnknownEnumValue and p != enum.kProxyView] for p in privilege_enum: steps.append(TestStep(step_number_with_privilege(5, 'a', p), "TH_commissioner gives TH_second_commissioner the specified privilege")) @@ -423,7 +540,7 @@ def steps_TC_ACE_2_3(self): TestStep(2, "TH_commissioner reads the ACL attribute (done during test setup)"), TestStep(3, "Repeat steps 3a and 3b for each permission level")] enum = Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum - privilege_enum = [p for p in enum if p != enum.kUnknownEnumValue] + privilege_enum = [p for p in enum if p != enum.kUnknownEnumValue and p != enum.kProxyView] for p in privilege_enum: steps.append(TestStep(step_number_with_privilege(3, 'a', p), "TH_commissioner gives TH_second_controller the specified privilege")) @@ -444,6 +561,27 @@ def desc_TC_ACE_2_3(self): async def test_TC_ACE_2_3(self): await self.run_access_test(AccessTestType.INVOKE) + def steps_TC_ACE_2_4(self): + steps = [TestStep("precondition", "DUT is commissioned", is_commissioning=True), + TestStep(1, "TH_commissioner performs a wildcard read (done during test setup)"), + TestStep(2, "TH_commissioner reads the ACL attribute (done during test setup)"), + TestStep(3, "Repeat steps 3a and 3b for each permission level")] + enum = Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum + privilege_enum = [p for p in enum if p != enum.kUnknownEnumValue and p != enum.kProxyView] + for p in privilege_enum: + steps.append(TestStep(step_number_with_privilege(3, 'a', p), + "TH_commissioner gives TH_second_commissioner the specified privilege")) + steps.append(TestStep(step_number_with_privilege(3, 'b', p), + "TH_second_controller subscribes to all the attributes and verifies the subscription is established and priming report is received with appropriate permission errors")) + return steps + + def desc_TC_ACE_2_4(self): + return "[TC-ACE-2.4] Attribute read subscription report - [DUT as Server]" + + @async_test_body + async def test_TC_ACE_2_4(self): + await self.run_access_test(AccessTestType.SUBSCRIBE) + if __name__ == "__main__": default_matter_test_main() diff --git a/src/python_testing/TC_CHIMETestBase.py b/src/python_testing/TC_CHIMETestBase.py index 6446b6f7e00..92e02096c33 100644 --- a/src/python_testing/TC_CHIMETestBase.py +++ b/src/python_testing/TC_CHIMETestBase.py @@ -39,10 +39,11 @@ async def write_chime_attribute_expect_failure(self, endpoint, attribute, value, asserts.assert_equal(response, status, "Unexpected error returned") - async def send_play_chime_sound_command(self, endpoint, expected_status: Status = Status.Success): + async def send_play_chime_sound_command(self, endpoint, chimeID: int = None, expected_status: Status = Status.Success): try: - await self.send_single_cmd(cmd=Clusters.Chime.Commands.PlayChimeSound(), - endpoint=endpoint) + await self.send_single_cmd(cmd=Clusters.Chime.Commands.PlayChimeSound( + chimeID=chimeID), + endpoint=endpoint) asserts.assert_equal(expected_status, Status.Success) diff --git a/src/python_testing/TC_CHIME_2_5.py b/src/python_testing/TC_CHIME_2_5.py new file mode 100644 index 00000000000..f6900b28d18 --- /dev/null +++ b/src/python_testing/TC_CHIME_2_5.py @@ -0,0 +1,136 @@ +# +# Copyright (c) 2025 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. + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${CAMERA_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# 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 +# --endpoint 1 +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import logging + +from mobly import asserts +from TC_CHIMETestBase import CHIMETestBase + +import matter.clusters as Clusters +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.matter_testing import MatterBaseTest +from matter.testing.runner import TestStep, default_matter_test_main + +log = logging.getLogger(__name__) + + +class TC_CHIME_2_5(MatterBaseTest, CHIMETestBase): + + def desc_TC_CHIME_2_5(self) -> str: + return "[TC-CHIME-2.5] Verify functionality of the PlayChimeSound command-Release 1.5.1 or later" + + def steps_TC_CHIME_2_5(self) -> list[TestStep]: + return [ + TestStep(1, "Commissioning, already done", is_commissioning=True), + TestStep(2, "Set the enabled attribute to False"), + TestStep(3, "Send the PlayChimeSound command and verify that no chime sound is heard"), + TestStep(4, "Set the enabled attribute to True"), + TestStep(5, "Send the PlayChimeSound with a ChimeID field different to the currently SelectedChime"), + TestStep(6, "Verify that a chime appropriate to the provided ID is heard."), + ] + + def pics_TC_CHIME_2_5(self) -> list[str]: + return [ + "CHIME.S", + ] + + @run_if_endpoint_matches(has_cluster(Clusters.Chime)) + async def test_TC_CHIME_2_5(self): + cluster = Clusters.Objects.Chime + attributes = cluster.Attributes + endpoint = self.get_endpoint() + self.is_ci = self.check_pics("PICS_SDK_CI_ONLY") + + # Pre-condition, make sure the ClusterRevision is at least 2 + clusterRevision = await self.read_chime_attribute_expect_success(endpoint=endpoint, attribute=attributes.ClusterRevision) + if clusterRevision < 2: + log.info("Chime 2.5: skipping as cluster revision is less than 2") + self.mark_all_remaining_steps_skipped(6) + return + + self.step(1) # Already done, immediately go to step 2 + + self.step(2) + await self.write_chime_attribute_expect_success(endpoint, attributes.Enabled, False) + + self.step(3) + await self.send_play_chime_sound_command(endpoint) + if not self.is_ci: + user_response = self.wait_for_user_input(prompt_msg="A chime sound should not have been played, is this correct? Enter 'y' or 'n'", + prompt_msg_placeholder="y", + default_value="y") + if user_response is not None: + log.info(f"CHIME 2_5: response '{user_response}' received on confirmation of no chime sound") + asserts.assert_equal(user_response.lower(), "y") + else: + log.info("CHIME 2_5: No response received for no chime sound played user prompt") + + self.step(4) + await self.write_chime_attribute_expect_success(endpoint, attributes.Enabled, True) + + myChimeSounds = await self.read_chime_attribute_expect_success(endpoint, attributes.InstalledChimeSounds) + mySelectedChime = await self.read_chime_attribute_expect_success(endpoint, attributes.SelectedChime) + if len(myChimeSounds) > 1: + self.step(5) + + newSelectedChime = mySelectedChime + for chime in myChimeSounds: + if chime.chimeID != mySelectedChime: + newSelectedChime = chime.chimeID + break + + await self.send_play_chime_sound_command(endpoint, newSelectedChime) + if not self.is_ci: + self.step(6) + user_response = self.wait_for_user_input(prompt_msg="A chime sound should have just been played, is this correct? Enter 'y' or 'n'", + prompt_msg_placeholder="y", + default_value="y") + if user_response is not None: + log.info(f"CHIME 2_5: response '{user_response}' received on confirmation of different chime sound") + asserts.assert_equal(user_response.lower(), "y") + else: + log.info("CHIME 2_5: No response received for different chime sound played user prompt") + else: + self.skip_step(6) + + else: + self.skip_step(5) + self.skip_step(6) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_CHIME_2_6.py b/src/python_testing/TC_CHIME_2_6.py new file mode 100644 index 00000000000..9b3f3d705bb --- /dev/null +++ b/src/python_testing/TC_CHIME_2_6.py @@ -0,0 +1,123 @@ +# +# Copyright (c) 2025 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. + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${CAMERA_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# 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 +# --endpoint 1 +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import logging + +from mobly import asserts +from TC_CHIMETestBase import CHIMETestBase + +import matter.clusters as Clusters +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.event_attribute_reporting import EventSubscriptionHandler +from matter.testing.matter_testing import MatterBaseTest +from matter.testing.runner import TestStep, default_matter_test_main + +log = logging.getLogger(__name__) + + +class TC_CHIME_2_6(MatterBaseTest, CHIMETestBase): + + def desc_TC_CHIME_2_6(self) -> str: + return "[TC-CHIME-2.6] Verify the generation of the ChimeStartedPlaying Event" + + def steps_TC_CHIME_2_6(self) -> list[TestStep]: + return [ + TestStep(1, "Commissioning, already done", is_commissioning=True), + TestStep(2, "Establish a subscription to the ChimeStartedPlaying event"), + TestStep(3, "Set the enabled attribute to True"), + TestStep(4, "Read and save the value of the SelectedChime attribute in mySelectedChime"), + TestStep(5, "Send the PlayChimeSound command"), + TestStep(6, "Verify reception of the ChimeStartedPlaying event"), + TestStep(7, "Verify that the value of the ChimeID in the event is the same as the value of mySelectedChime"), + ] + + def pics_TC_CHIME_2_6(self) -> list[str]: + return [ + "CHIME.S", + ] + + @run_if_endpoint_matches(has_cluster(Clusters.Chime)) + async def test_TC_CHIME_2_6(self): + cluster = Clusters.Objects.Chime + attributes = cluster.Attributes + endpoint = self.get_endpoint() + self.is_ci = self.check_pics("PICS_SDK_CI_ONLY") + + # Pre-condition, make sure the ClusterRevision is at least 2 + clusterRevision = await self.read_chime_attribute_expect_success(endpoint=endpoint, attribute=attributes.ClusterRevision) + if clusterRevision < 2: + log.info("Chime 2.5: skipping as cluster revision is less than 2") + self.mark_all_remaining_steps_skipped(7) + return + + self.step(1) # Already done, immediately go to step 2 + + # TH establishes a subscription to all of the Events from the Cluster + self.step(2) + event_callback = EventSubscriptionHandler(expected_cluster=Clusters.Chime) + await event_callback.start(self.default_controller, + self.dut_node_id, + self.get_endpoint()) + + self.step(3) + await self.write_chime_attribute_expect_success(endpoint, attributes.Enabled, True) + + self.step(4) + mySelectedChime = await self.read_chime_attribute_expect_success(endpoint, attributes.SelectedChime) + + self.step(5) + await self.send_play_chime_sound_command(endpoint) + if not self.is_ci: + user_response = self.wait_for_user_input(prompt_msg="A chime sound should have been played, is this correct? Enter 'y' or 'n'", + prompt_msg_placeholder="y", + default_value="y") + if user_response is not None: + log.info(f"CHIME 2_6: response '{user_response}' received confirmation of chime sound") + asserts.assert_equal(user_response.lower(), "y") + else: + log.info("CHIME 2_6: No response received for chime sound played user prompt") + + self.step(6) + event_data = event_callback.wait_for_event_report(Clusters.Chime.Events.ChimeStartedPlaying, timeout_sec=5) + log.info(f"Event data {event_data}") + + self.step(7) + asserts.assert_equal(event_data.chimeID, mySelectedChime, "Unexpected value for ChimeID returned") + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_DA_1_2.py b/src/python_testing/TC_DA_1_2.py index 43386e3b0d3..c484955b8d6 100644 --- a/src/python_testing/TC_DA_1_2.py +++ b/src/python_testing/TC_DA_1_2.py @@ -33,12 +33,27 @@ # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # factory-reset: true # quiet: true +# run2: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --string-arg cd_cert_dir:credentials/development/cd-certs +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true # === END CI TEST ARGUMENTS === import logging -import os import random import re +from enum import IntEnum +from pathlib import Path from typing import Tuple from cryptography import x509 @@ -57,7 +72,9 @@ from matter.interaction_model import InteractionModelError, Status from matter.testing.basic_composition import BasicCompositionTests from matter.testing.conversions import hex_from_bytes +from matter.testing.credentials import CredentialSource, get_cd_certs from matter.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main, matchers +from matter.testing.problem_notices import CommandPathLocation from matter.tlv import TLVReader @@ -123,10 +140,12 @@ def parse_ids_from_certs(dac: x509.Certificate, pai: x509.Certificate) -> Tuple[ return dac_vid, dac_pid, pai_vid, pai_pid -# To set the directory for the CD certificates use +# To set the directory for the CD signer certificates use # --string-arg cd_cert_dir:'your_directory_name' # ex. --string-arg cd_cert_dir:'credentials/development/cd-certs' -# default is 'credentials/development/cd-certs'. +# default is the internal development CD signer certificates +# This directory is only used for test CDs or provisional CDs when the override_provisional_cd_check_warning flag is used. +# For production and provisional CDs with no flag, the internal production CD signer certificates are used class TC_DA_1_2(MatterBaseTest, BasicCompositionTests): @@ -158,7 +177,7 @@ def steps_TC_DA_1_2(self): TestStep("6.6", "Verify CD security level", "security level = 0"), TestStep("6.7", "Verify CD security_information", "security_information = 0"), TestStep("6.8", "Verify CD version_number", "version_number is an integer in range 0..65535"), - TestStep("6.9", "Verify CD certification_type", "certification_type has a value between 1..2"), + TestStep("6.9", "Verify CD certification_type", "certification_type has a value between 0..2"), TestStep("7.0", "Extract the Vendor ID (VID) and Product ID (PID) from the DAC. Extract the VID from the PAI. Extract the PID from the PAI, if present", "VID and PID are present and properly encoded in the DAC. VID is present and properly encoded in the PAI. If the PID is present in the PAI, it is properly encoded"), TestStep("7.1", "", "If the dac_origin_vendor_id is present in the CD, confirm the dac_origin_product_id is also present. If the dac_origin_vendor_id is not present in the CD, confirm the dac_origin_product_id is also not present."), @@ -172,7 +191,12 @@ def steps_TC_DA_1_2(self): "* If it is present in the PAI certificate, the Product ID (PID) in the subject is contained in the product_id_array field in the Certification Declaration.\n")), TestStep(8, "If the Certification Declaration has authorized_paa_list, check that the authority_key_id extension of the PAI matches one found in the authorized_paa_list", "PAA from PAI authority_key_id extension matches one found in authorized_paa_list"), - TestStep(9, "Verify that the certification_declaration CMS enveloped can be verified with the well-known Certification Declaration public key used to originally sign the Certification Declaration", "Signature verification passes"), + TestStep(9, ("Verify that the certification_declaration CMS enveloped can be verified with Certification Declaration public key.\n" + "For official CDs the signer must be one of the well-known CSA CD signing keys.\n" + "For provisional CDs, the signer must be one of the well-known CSA CD signing keys unless the `override_provisional_cd_check_warning` flag is set to acknowledge the use of a provisional CD that cannot be used in production devices." + "For test and development CDs, the signer certificates may be one of the development certificates or can be provided by the tester." + ), + "Signature verification passes"), TestStep(10, "Verify attestation_nonce", ("* attestation_nonce is present in the attestation_elements_message structure\n" "* attestation_nonce value matches the AttestationNonce field value sent in the AttestationRequest Command sent by the commissioner\n" "* attestation_nonce is a 32 byte-long octet string\n")), @@ -187,7 +211,17 @@ def steps_TC_DA_1_2(self): @async_test_body async def test_TC_DA_1_2(self): - cd_cert_dir = self.user_params.get("cd_cert_dir", 'credentials/development/cd-certs') + class CertificationType(IntEnum): + kTest = 0 + kProvisional = 1 + kOfficial = 2 + + # NOTE: this parameter is not used for production CDs or provisional CDs without the override flag. + cd_cert_dir = self.user_params.get("cd_cert_dir") + if cd_cert_dir is None: + cd_cert_dir = CredentialSource.kDevelopment + else: + cd_cert_dir = Path(cd_cert_dir) post_cert_test = self.user_params.get("post_cert_test", False) do_test_over_pase = self.user_params.get("use_pase_only", False) @@ -195,6 +229,11 @@ async def test_TC_DA_1_2(self): setupCode = self.matter_test_config.qr_code_content or self.matter_test_config.manual_code await self.default_controller.FindOrEstablishPASESession(setupCode[0], self.dut_node_id) + override_provisional_cd_check_warning = self.user_params.get("override_provisional_cd_check_warning", False) + + problem_location = CommandPathLocation(endpoint_id=0, cluster_id=Clusters.OperationalCredentials.id, + command_id=Clusters.OperationalCredentials.Commands.AttestationRequest.command_id) + # Commissioning - done self.step(0) @@ -339,11 +378,24 @@ async def test_TC_DA_1_2(self): asserts.assert_in(version_number, range(0, 65535), "Version number out of range") self.step("6.9") if post_cert_test: - asserts.assert_equal(certification_type, 2, "Certification declaration is not marked as production.") - elif self.is_pics_sdk_ci_only: - asserts.assert_in(certification_type, [0, 1, 2], "Certification type is out of range") - else: - asserts.assert_in(certification_type, [1, 2], "Certification type is out of range") + asserts.assert_in(certification_type, [CertificationType.kProvisional, CertificationType.kOfficial], + "Certification declaration is not marked as production or provisional.") + if certification_type == CertificationType.kProvisional: + # This is a provisional CD, which is technically allowed, but unexpected in the interop lab. Create a warning, + # but delay reporting until the end of the test. + msg = """ + WARNING ONLY: This product contains a provisional certification declaration. + While this is technically allowed, it is unexpected since devices are expected to replace provisional + CDs on update. This is not a full failure, but the manufacturer should be informed. + """ + self.record_warning(test_name=self.current_test_info.name, problem=msg, location=problem_location) + + # At certification testing, we now allow test CDs. + # Provisional CDs must be signed by a CSA CD signing key (unless there is an override). + # Production CDs must always be signed by a CSA CD signing key. + # The signature check is handled in step 9. + asserts.assert_in(certification_type, [CertificationType.kTest, CertificationType.kProvisional, + CertificationType.kOfficial], "Certification type is out of range") self.step("7.0") dac_vid, dac_pid, pai_vid, pai_pid = parse_ids_from_certs(parsed_dac, parsed_pai) @@ -390,20 +442,54 @@ async def test_TC_DA_1_2(self): self.step(9) signature_cd = bytes(signer_info['signature']) - certs = {} - for filename in os.listdir(cd_cert_dir): - if '.der' not in filename: - continue - with open(os.path.join(cd_cert_dir, filename), 'rb') as f: - logging.info(f'Parsing CD signing certificate file: {filename}') - try: - cert = x509.load_der_x509_certificate(f.read()) - except ValueError: - logging.info(f'File {filename} is not a valid certificate, skipping') - pass - pub = cert.public_key() - ski = x509.SubjectKeyIdentifier.from_public_key(pub).digest - certs[ski] = pub + + def load_certs(cd_signers): + certs = {} + for filename in get_cd_certs(cd_signers).iterdir(): + if not filename.name.endswith('.der'): + continue + with filename.open("rb") as f: + logging.info(f'Parsing CD signing certificate file: {filename}') + try: + cert = x509.load_der_x509_certificate(f.read()) + except ValueError: + logging.info(f'File {filename} is not a valid certificate, skipping') + continue + pub = cert.public_key() + ski = x509.SubjectKeyIdentifier.from_public_key(pub).digest + certs[ski] = pub + return certs + # If the CD is a test CD, or a provisional key with the specified override, it can be signed by the supplied CD signers. + # if the CD is a provisional CD with no override, or a full production CD, it MUST be signed by the official CD signers. + prod_certs = load_certs(CredentialSource.kProduction) + if certification_type == CertificationType.kTest or (override_provisional_cd_check_warning and certification_type == CertificationType.kProvisional): + certs = load_certs(cd_cert_dir) + else: + certs = prod_certs + + if certification_type == CertificationType.kProvisional and subject_key_identifier not in prod_certs: + msg = """WARNING: This device is using a CD that is marked as provisional, but which is not signed by the official CSA + CD signing key. + + Devices were previously required to bring such a certificate to certification, but recent changes to the + specification to support CSA-signed provisional CDs have resulted in changes to these requirements. + + The restrictions on CD certification type for certification testing have been loosened such that is it now + acceptable to bring a test CD to certification. + During this transition period, non-CSA signed provisional CDs are still being accepted for certification + testing. Note that such CDs are NOT suitable for use on production devices. + + """ + if override_provisional_cd_check_warning: + msg += "Press enter to acknowledge that this provisional CD cannot be used in a production device." + self.wait_for_user_input(msg) + else: + msg += """ + To continue using a non-CSA signed provisional CD for certification testing, please set the + override_provisional_cd_check_warning flag (`--bool-arg override_provisional_cd_check_warning:true') + and re-run this test. + """ + self.record_error(test_name=self.current_test_info.name, location=problem_location, problem=msg) asserts.assert_true(subject_key_identifier in certs.keys(), "Subject key identifier not found in CD certs") try: @@ -460,6 +546,9 @@ async def test_TC_DA_1_2(self): except InteractionModelError as e: asserts.assert_equal(e.status, Status.InvalidCommand, "Received incorrect error from AttestationRequest command") + if self.problems: + self.fail("Problems found during test") + if __name__ == "__main__": default_matter_test_main() diff --git a/src/python_testing/TC_PAVSTI_1_1.py b/src/python_testing/TC_PAVSTI_1_1.py index 9a5b1eea2ca..22d903036da 100644 --- a/src/python_testing/TC_PAVSTI_1_1.py +++ b/src/python_testing/TC_PAVSTI_1_1.py @@ -287,7 +287,7 @@ async def test_TC_PAVSTI_1_1(self): "audioStreamID": audioStreamId, "TLSEndpointID": tlsEndpointId, "url": f"https://{self.host_ip}:1234/streams/{uploadStreamId}/", - "triggerOptions": {"triggerType": pushavCluster.Enums.TransportTriggerTypeEnum.kCommand, "maxPreRollLen": 10}, + "triggerOptions": {"triggerType": pushavCluster.Enums.TransportTriggerTypeEnum.kCommand, "maxPreRollLen": 10000}, "ingestMethod": pushavCluster.Enums.IngestMethodsEnum.kCMAFIngest, "containerFormat": pushavCluster.Enums.ContainerFormatEnum.kCmaf, "containerOptions": { diff --git a/src/python_testing/TC_PAVSTTestBase.py b/src/python_testing/TC_PAVSTTestBase.py index 3b8c79f7991..13af23f74d2 100644 --- a/src/python_testing/TC_PAVSTTestBase.py +++ b/src/python_testing/TC_PAVSTTestBase.py @@ -29,7 +29,7 @@ class PAVSTTestBase: - DEFAULT_AV_TRANSPORT_EXPIRY_TIME_SEC = 30 # 30 seconds + DEFAULT_AV_TRANSPORT_EXPIRY_TIME_SEC = 150 # 150 seconds async def read_pavst_attribute_expect_success(self, endpoint, attribute): cluster = Clusters.Objects.PushAvStreamTransport diff --git a/src/python_testing/TC_PAVST_2_11.py b/src/python_testing/TC_PAVST_2_11.py new file mode 100644 index 00000000000..2006b6b36e2 --- /dev/null +++ b/src/python_testing/TC_PAVST_2_11.py @@ -0,0 +1,804 @@ +# +# Copyright (c) 2025 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. + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${CAMERA_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --app-pipe /tmp/pavst_2_11_fifo +# script-args: > +# --storage-path admin_storage.json +# --string-arg th_server_app_path:${PUSH_AV_SERVER} +# --string-arg host_ip:localhost +# --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 +# --endpoint 1 +# --app-pipe /tmp/pavst_2_11_fifo +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import logging + +from mobly import asserts +from TC_PAVSTI_Utils import PAVSTIUtils, PushAvServerProcess +from TC_PAVSTTestBase import PAVSTTestBase + +import matter.clusters as Clusters +from matter.clusters import Globals +from matter.clusters.Types import Nullable, NullValue +from matter.interaction_model import InteractionModelError, Status +from matter.testing.decorators import async_test_body, has_cluster, run_if_endpoint_matches +from matter.testing.matter_testing import MatterBaseTest, TestStep +from matter.testing.runner import default_matter_test_main + +log = logging.getLogger(__name__) + + +class TC_PAVST_2_11(MatterBaseTest, PAVSTTestBase, PAVSTIUtils): + def desc_TC_PAVST_2_11(self) -> str: + return "[TC-PAVST-2.11] Allocate PushAV Transport with Server as DUT-Release 1.5.1 and later" + + def pics_TC_PAVST_2_11(self): + return ["PAVST.S", "AVSM.S", "TLSCLIENT.S"] + + @async_test_body + async def setup_class(self): + th_server_app = self.user_params.get("th_server_app_path", None) + self.server = PushAvServerProcess(server_path=th_server_app) + self.server.start( + expected_output="Running on https://0.0.0.0:1234", + timeout=30, + ) + super().setup_class() + + def teardown_class(self): + if self.server is not None: + self.server.terminate() + super().teardown_class() + + def steps_TC_PAVST_2_11(self) -> list[TestStep]: + return [ + TestStep("precondition", "Commissioning, already done", is_commissioning=True), + TestStep(1, "TH Reads CurrentConnections attribute from PushAV Stream Transport Cluster on DUT", + "Verify the number of PushAV Connections in the list is 0. If not 0, issue DeAllocatePushAVTransport with ConnectionID to remove any connections."), + TestStep(2, "TH Reads SupportedFormats attribute from PushAV Stream Transport Cluster on DUT", + "Store value as aSupportedFormats."), + TestStep(3, "After ensuring that no streams have been allocated, TH sends an AllocatePushTransport command with Null for the video and audio stream IDs", + "DUT responds with InvalidInState as no streams have been allocated."), + TestStep(4, "If no video streams are allocated, TH sends a VideoStreamAllocate command. Otherwise the first allocated video stream is used.", + "If the command is sent, the DUT responds with VideoStreamAllocateResponse, store this as aAllocatedVideoStreams."), + TestStep(5, "If no audio streams are allocated, TH sends a AudioStreamAllocate command. Otherwise the first allocated audio stream is used.", + "If the command is sent, the DUT responds with AudioStreamAllocateResponse, store this as aAllocatedAudioStreams."), + TestStep(6, "TH sends the AllocatePushTransport command with valid parameters", + "DUT responds with `AllocatePushTransportResponse` containing the allocated `ConnectionID`, `TransportOptions`, and `TransportStatus` in the `TransportConfigurationStruct`. Store ConnectionID as `aConnectionID_1`."), + TestStep(7, "TH Reads CurrentConnections attribute from PushAV Stream Transport Cluster on DUT over a large-payload session", + "Verify the number of PushAV Connections is 1. Verify that the TransportStatus field is Inactive."), + TestStep(8, "TH Reads Zones attribute from Zones Management Cluster on DUT, if the zone management cluster is present on this endpoint", + "Store value as aZones."), + TestStep(9, "TH Reads MaxZones attribute from Zones Management Cluster on DUT, if the zone management cluster is present on this endpoint", + "Store value as aMaxZones."), + TestStep(10, "TH Reads ProvisionedEndpoints attribute from TLS Client Management Cluster on DUT", + "Store value as aProvisionedEndpoints."), + TestStep(11, "TH sends the AllocatePushTransport command with a TLSEndpointID not in aProvisionedEndpoints in the TransportOptions struct.", + "DUT responds with Status Code InvalidTLSEndpoint."), + TestStep(12, "TH sends the AllocatePushTransport command with an invalid IngestMethod.", + "DUT responds with Status Code ConstraintError."), + TestStep(13, "TH sends the AllocatePushTransport command with Invalid URL.", + "DUT responds with Status Code InvalidURL."), + TestStep(14, "TH sends the AllocatePushTransport command with an invalid TriggerType in the TransportTriggerOptions struct field.", + "DUT responds with Status Code InvalidTriggerType."), + TestStep(15, "If the zone management cluster is present on this endpoint, TH sends the AllocatePushTransport command with a Null Zone in MotionZones.", + "DUT responds with Success."), + TestStep(16, "If the zone management cluster is present on this endpoint, TH sends the AllocatePushTransport command with duplicate numeric Zone IDs within MotionZones.", + "DUT responds with Status Code AlreadyExists."), + TestStep(17, "If the zone management cluster is present on this endpoint, TH sends the AllocatePushTransport command with duplicate Null Zone IDs within MotionZones.", + "DUT responds with Status Code AlreadyExists."), + TestStep(18, "If the zone management cluster is present on this endpoint, TH sends the AllocatePushTransport command with an invalid ZoneID that is not present in aZones.", + "DUT responds with Status Code InvalidZone."), + TestStep(19, "TH sends the AllocatePushTransport command with VideoStreams containing a VideoStreamID not present in aAllocatedVideoStreams.", + "DUT responds with Status Code InvalidStream."), + TestStep(20, "TH sends the AllocatePushTransport command with AudioStreams containing an AudioStreamID not present in aAllocatedAudioStreams.", + "DUT responds with Status Code InvalidStream."), + TestStep(21, "TH sends the AllocatePushTransport command with both `VideoStreams` and `AudioStreams` absent.", + "DUT responds with Status Code `InvalidCommand`."), + TestStep("21a", "TH sends the AllocatePushTransport command with a VideoStreamID set to an allocated stream ID, and a VideoStreams containing the same allocated stream ID", + "DUT responds with INVALID_COMMAND status code."), + TestStep(22, "TH sends the AllocatePushTransport command with both `VideoStreamID` and `AudioStreamID` set to NULL and no `VideoStreams` or `AudioStreams` fields present.", + "DUT responds with `AllocatePushTransportResponse` containing the allocated `ConnectionID`, store this as 'aConnectionID-2'. If the `AllocatePushTransportResponse` contains a TransportOptions, verify the following: * AudioStreamId field is present containing the allocated audio stream ID * VideoStreamId field is present containing the allocated video stream ID * VideoStreams field is present with an entry that has the allocated video stream ID, and a VideoStreamName of \"video\" * AudioStreams field is present with an entry that has the allocated audio stream ID, and an AudioStreamName of \"audio\""), + TestStep(23, "If the zone management cluster is present on this endpoint, TH sends the AllocatePushTransport command with the TriggerType = Motion and size of the MotionZones list to be greater than aMaxZones.", + "DUT responds with DynamicConstraintError."), + TestStep(24, "TH sends the AllocatePushTransport command with the TriggerType = Motion and valid value for MotionSensitivity if DUT supports PerZoneSensitivity.", + "DUT responds with InvalidCommand."), + TestStep(25, "TH sends the AllocatePushTransport command with the TriggerType = Motion and MotionSensitivity > 10 if DUT does not support PerZoneSensitivity.", + "DUT responds with ConstraintError."), + TestStep(26, "TH sends the AllocatePushTransport command with the TriggerType = Motion and MotionTimeControl omitted.", + "DUT responds with InvalidCommand."), + TestStep(27, "TH sends the AllocatePushTransport command with the TriggerType = Motion and MotionTimeControl struct with InitialDuration = 0.", + "DUT responds with ConstraintError."), + TestStep(28, "TH sends the AllocatePushTransport command with the TriggerType = Motion and MotionTimeControl struct with MaxDuration = 0.", + "DUT responds with ConstraintError."), + TestStep(29, "TH sends a `DeallocatePushTransport`command with `aConnectionID_1`. TH sends the AllocatePushTransport command with all valid parameters. The `TriggerType = Motion` and `MotionZones` and `MotionSensitivity` fields are present and NULL.", + "DUT responds with AllocatePushTransportResponse containing the allocated ConnectionID."), + TestStep(30, "TH sends a `DeallocatePushTransport` command with `aConnectionID-2`. TH sends the AllocatePushTransport command with all valid parameters. The `TriggerType = Motion` and `MotionZones` field is empty.", + "DUT responds with `AllocatePushTransportResponse` containing the allocated `ConnectionID`."), + TestStep(31, "TH sends the AllocatePushTransport command with an invalid value for StreamUsage in the TransportOptions struct.", + "DUT responds with InvalidCommand."), + TestStep(32, "TH sends the AllocatePushTransport command with ContainerType = CMAF and CMAFContainerOptions omitted.", + "DUT responds with InvalidCommand."), + TestStep(33, "TH sends the AllocatePushTransport command with ContainerType = CMAF and CMAFContainerOptions having a segment that is not an exact multiplier of the KeyFrameInterval of the allocated video stream ID.", + "DUT responds with InvalidOptions."), + TestStep(34, "TH sends the AllocatePushTransport command with a value for StreamUsage not in SupportedStreamUsages.", + "DUT responds with InvalidStreamUsage."), + TestStep(35, "TH sends the AllocatePushTransport command with a non-zero MaxPreRollLen that is less than the KeyFrameInterval value of the selected allocated video stream ID", + "DUT responds with InvalidPreRollLength."), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.PushAvStreamTransport)) + async def test_TC_PAVST_2_11(self): + endpoint = self.get_endpoint() + self.endpoint = endpoint + self.node_id = self.dut_node_id + pvcluster = Clusters.PushAvStreamTransport + avcluster = Clusters.CameraAvStreamManagement + pvattr = Clusters.PushAvStreamTransport.Attributes + avattr = Clusters.CameraAvStreamManagement.Attributes + tlscluster = Clusters.TlsClientManagement + tlsattr = Clusters.TlsClientManagement.Attributes + zmcluster = Clusters.ZoneManagement + + # Precondition + self.step("precondition") + host_ip = self.user_params.get("host_ip", None) + tlsEndpointId, host_ip = await self.precondition_provision_tls_endpoint( + endpoint=endpoint, server=self.server, host_ip=host_ip) + uploadStreamId = self.server.create_stream() + + # Step 1: Reads CurrentConnections attribute + self.step(1) + transport_configs = await self.read_single_attribute_check_success( + endpoint=endpoint, cluster=pvcluster, attribute=pvattr.CurrentConnections) + for cfg in transport_configs: + if cfg.ConnectionID != 0: + try: + await self.send_single_cmd( + cmd=pvcluster.Commands.DeallocatePushTransport(connectionID=cfg.ConnectionID), + endpoint=endpoint) + except InteractionModelError as e: + log.warning(f"Failed to deallocate connection {cfg.ConnectionID} during cleanup: {e}") + + # Step 2: Read supported formats + self.step(2) + aSupportedFormats = await self.read_single_attribute_check_success( + endpoint=endpoint, cluster=pvcluster, attribute=pvattr.SupportedFormats) + log.info(f"aSupportedFormats={aSupportedFormats}") + + # Step 3: Try to allocate transport with null stream IDs when no streams are allocated + self.step(3) + try: + status = await self.send_single_cmd(cmd=pvcluster.Commands.AllocatePushTransport( + { + "streamUsage": Globals.Enums.StreamUsageEnum.kRecording, + "videoStreamID": NullValue, + "audioStreamID": NullValue, + "TLSEndpointID": tlsEndpointId, + "url": f"https://{host_ip}:1234/streams/1/", + "triggerOptions": {"triggerType": 2}, + "ingestMethod": 0, + "containerOptions": { + "containerType": 0, + "CMAFContainerOptions": {"CMAFInterface": 0, "segmentDuration": 4000, "chunkDuration": 2000, "sessionGroup": 1, "trackName": "media"} + }, + "expiryTime": 5 + }), endpoint=endpoint) + asserts.assert_equal(status, Status.InvalidInState, + "Unexpected success when the DUT must respond with Status Code InvalidInState.") + except InteractionModelError as e: + asserts.assert_equal(e.status, Status.InvalidInState, + f"DUT must respond with Status Code InvalidInState, received {e.status}.") + + # Step 4: Allocate video stream + self.step(4) + aAllocatedVideoStreams = await self.allocate_one_video_stream() + asserts.assert_greater_equal( + len(aAllocatedVideoStreams), + 1, + "AllocatedVideoStreams must not be empty", + ) + + # Step 5: Allocate audio stream + self.step(5) + aAllocatedAudioStreams = await self.allocate_one_audio_stream() + asserts.assert_greater_equal( + len(aAllocatedAudioStreams), + 1, + "AllocatedAudioStreams must not be empty", + ) + + # Step 6: Allocate push transport with valid parameters + self.step(6) + status = await self.allocate_one_pushav_transport( + endpoint, + tlsEndPoint=tlsEndpointId, + url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal( + status, Status.Success, "Push AV Transport should be allocated successfully") + + # Get the connection ID from CurrentConnections + transport_configs = await self.read_single_attribute_check_success( + endpoint=endpoint, cluster=pvcluster, attribute=pvattr.CurrentConnections) + aConnectionID_1 = None + if len(transport_configs) > 0: + aConnectionID_1 = transport_configs[0].connectionID + asserts.assert_is_not_none(aConnectionID_1, "ConnectionID should be present") + + # Step 7: Read CurrentConnections over large-payload session + self.step(7) + transport_configs = await self.read_single_attribute_check_success( + endpoint=endpoint, cluster=pvcluster, attribute=pvattr.CurrentConnections) + asserts.assert_equal(len(transport_configs), 1, "TransportConfigurations must be 1") + asserts.assert_true(transport_configs[0].transportStatus == + pvcluster.Enums.TransportStatusEnum.kInactive, "Transport status should be Inactive") + + # Step 8: Read Zones attribute if zone management cluster is present + self.step(8) + aZones = await self.read_single_attribute_check_success( + endpoint=endpoint, cluster=zmcluster, attribute=zmcluster.Attributes.Zones + ) + log.info(f"aZones: {aZones}") + + # Step 9: Read MaxZones attribute if zone management cluster is present + self.step(9) + aMaxZones = await self.read_single_attribute_check_success( + endpoint=endpoint, cluster=zmcluster, attribute=zmcluster.Attributes.MaxZones + ) + log.info(f"aMaxZones: {aMaxZones}") + + # Read FeatureMap to check for PerZoneSensitivity support + aFeatureMap = await self.read_single_attribute_check_success( + endpoint=endpoint, cluster=zmcluster, attribute=zmcluster.Attributes.FeatureMap + ) + log.info(f"ZoneManagement FeatureMap: {aFeatureMap}") + self.perZoneSenseSupported = aFeatureMap & zmcluster.Bitmaps.Feature.kPerZoneSensitivity + + # Step 10: Read ProvisionedEndpoints attribute from TLS Client Management Cluster + self.step(10) + if self.pics_guard(self.check_pics("PAVST.S")): + aProvisionedEndpoints = await self.read_single_attribute_check_success( + endpoint=endpoint, cluster=tlscluster, attribute=tlsattr.ProvisionedEndpoints + ) + log.info(f"aProvisionedEndpoints: {aProvisionedEndpoints}") + + self.step(11) + if self.pics_guard(self.check_pics("PAVST.S")): + try: + status = await self.send_single_cmd(cmd=pvcluster.Commands.AllocatePushTransport( + { + "streamUsage": 0, + "videoStreamID": 1, + "audioStreamID": 1, + "TLSEndpointID": 5, + "url": f"https://{host_ip}:1234/streams/1/", + "triggerOptions": {"triggerType": 2}, + "ingestMethod": 0, + "containerOptions": { + "containerType": 0, + "CMAFContainerOptions": {"CMAFInterface": 0, "segmentDuration": 4000, "chunkDuration": 2000, "sessionGroup": 1, "trackName": "media"} + }, + "expiryTime": 5 + }), endpoint=endpoint) + asserts.assert_equal(status, pvcluster.Enums.StatusCodeEnum.kInvalidTLSEndpoint, + "DUT must responds with Status Code InvalidTLSEndpoint.") + except InteractionModelError as e: + asserts.assert_equal(e.clusterStatus, pvcluster.Enums.StatusCodeEnum.kInvalidTLSEndpoint, + "DUT must responds with Status Code InvalidTLSEndpoint.") + + # Step 12: Try to allocate transport with invalid IngestMethod + self.step(12) + status = await self.allocate_one_pushav_transport(endpoint, ingestMethod=pvcluster.Enums.IngestMethodsEnum.kUnknownEnumValue, + tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.ConstraintError, + "DUT must respond with Status Code ConstraintError.") + + # Step 13: Try to allocate transport with invalid URL + self.step(13) + stream_id = self.server.create_stream() + status = await self.allocate_one_pushav_transport( + endpoint, + url=f"http://{host_ip}:1234/streams/{stream_id}/", + tlsEndPoint=tlsEndpointId, + expected_cluster_status=pvcluster.Enums.StatusCodeEnum.kInvalidURL) + asserts.assert_equal(status, pvcluster.Enums.StatusCodeEnum.kInvalidURL, + "Push AV Transport should return InvalidURL for invalid URL") + + # Step 14: Try to allocate transport with invalid TriggerType + self.step(14) + # Create transport options with invalid trigger type + invalid_trigger_options = { + "triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kUnknownEnumValue + } + status = await self.allocate_one_pushav_transport( + endpoint, + trigger_Options=invalid_trigger_options, + tlsEndPoint=tlsEndpointId, + url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.ConstraintError, + "DUT must respond with Status Code ConstraintError.") + + self.step(15) + # Verify a null Zone is handled + try: + zoneList = [{"zone": NullValue, "sensitivity": 4}] + triggerOptions = {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kMotion, + "maxPreRollLen": 4000, + "motionZones": zoneList, + "motionTimeControl": {"initialDuration": 1, "augmentationDuration": 1, "maxDuration": 1, "blindDuration": 1}} + status = await self.allocate_one_pushav_transport(endpoint, trigger_Options=triggerOptions, tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.Success, "DUT should respond with Status Code Success with a Null Zone.") + except InteractionModelError as e: + asserts.assert_fail(f"Unexpected error when setting a Zone that is Null (meaning all Zones). Error received {e.status}") + + # Step 16: Try to allocate transport with duplicate numeric Zone IDs within MotionZones (if zone management cluster is present) + self.step(16) + zoneList = [{"zone": 1, "sensitivity": 4}, {"zone": 2, "sensitivity": 4}, + {"zone": 3, "sensitivity": 4}, {"zone": 1, "sensitivity": 4}] + triggerOptions = {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kMotion, + "maxPreRollLen": 4000, + "motionZones": zoneList, + "motionTimeControl": {"initialDuration": 1, "augmentationDuration": 1, "maxDuration": 1, "blindDuration": 1}} + status = await self.allocate_one_pushav_transport(endpoint, trigger_Options=triggerOptions, tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.AlreadyExists, + "DUT should respond with Status Code AlreadyExists with a Duplicate Zone.") + + # Step 17: Try to allocate transport with duplicate Null Zone IDs within MotionZones (if zone management cluster is present) + self.step(17) + # Duplicate Zone ID rejection with Nulls + zoneList = [{"zone": 1, "sensitivity": 4}, {"zone": NullValue, "sensitivity": 4}, + {"zone": 3, "sensitivity": 4}, {"zone": NullValue, "sensitivity": 4}] + triggerOptions = {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kMotion, + "maxPreRollLen": 4000, + "motionZones": zoneList, + "motionTimeControl": {"initialDuration": 1, "augmentationDuration": 1, "maxDuration": 1, "blindDuration": 1}} + status = await self.allocate_one_pushav_transport(endpoint, trigger_Options=triggerOptions, tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.AlreadyExists, + "DUT should respond with Status Code AlreadyExists with Duplicate Null Zones.") + + # Step 18: Try to allocate transport with invalid ZoneID (if zone management cluster is present) + self.step(18) + try: + zoneList = [{"zone": 14, "sensitivity": 4}] + triggerOptions = {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kMotion, + "maxPreRollLen": 4000, + "motionZones": zoneList, + "motionTimeControl": {"initialDuration": 1, "augmentationDuration": 1, "maxDuration": 1, "blindDuration": 1}} + status = await self.allocate_one_pushav_transport(endpoint, trigger_Options=triggerOptions, expected_cluster_status=pvcluster.Enums.StatusCodeEnum.kInvalidZone, + tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, pvcluster.Enums.StatusCodeEnum.kInvalidZone, + "DUT must responds with Status Code InvalidZone.") + except InteractionModelError as e: + asserts.assert_equal(e.clusterStatus, pvcluster.Enums.StatusCodeEnum.kInvalidZone, + "DUT must responds with Status Code InvalidZone.") + + # Step 19: Try to allocate transport with invalid VideoStreamID + self.step(19) + invalid_video_stream_id = max(aAllocatedVideoStreams) + 100 + status = await self.allocate_one_pushav_transport( + endpoint, + videoStream_ID=invalid_video_stream_id, + tlsEndPoint=tlsEndpointId, + url=f"https://{host_ip}:1234/streams/{uploadStreamId}/", + expected_cluster_status=pvcluster.Enums.StatusCodeEnum.kInvalidStream) + asserts.assert_equal(status, pvcluster.Enums.StatusCodeEnum.kInvalidStream, + "Push AV Transport should return InvalidStream for invalid VideoStreamID") + + # Step 20: Try to allocate transport with invalid AudioStreamID + self.step(20) + invalid_audio_stream_id = max(aAllocatedAudioStreams) + 100 + status = await self.allocate_one_pushav_transport( + endpoint, + audioStream_ID=invalid_audio_stream_id, + tlsEndPoint=tlsEndpointId, + url=f"https://{host_ip}:1234/streams/{uploadStreamId}/", + expected_cluster_status=pvcluster.Enums.StatusCodeEnum.kInvalidStream) + asserts.assert_equal(status, pvcluster.Enums.StatusCodeEnum.kInvalidStream, + "Push AV Transport should return InvalidStream for invalid AudioStreamID") + + # Step 21: Try to allocate transport with both VideoStreams and AudioStreams absent + self.step(21) + try: + aStreamUsagePriorities = await self.read_single_attribute_check_success( + endpoint=endpoint, cluster=avcluster, attribute=avattr.StreamUsagePriorities + ) + asserts.assert_greater(len(aStreamUsagePriorities), 0, "StreamUsagePriorities is empty") + + streamUsage = aStreamUsagePriorities[0] + containerOptions = { + "containerType": pvcluster.Enums.ContainerFormatEnum.kCmaf, + "CMAFContainerOptions": {"CMAFInterface": pvcluster.Enums.CMAFInterfaceEnum.kInterface1, "chunkDuration": 4, "segmentDuration": 4000, + "sessionGroup": 3, "trackName": "media"}, + } + status = await self.send_single_cmd(cmd=pvcluster.Commands.AllocatePushTransport( + {"streamUsage": streamUsage, + "TLSEndpointID": tlsEndpointId, + "url": f"https://{host_ip}:1234/streams/1/", + "triggerOptions": {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kContinuous}, + "ingestMethod": pvcluster.Enums.IngestMethodsEnum.kCMAFIngest, + "containerOptions": containerOptions, + "expiryTime": 5 + }), endpoint=endpoint) + asserts.assert_equal(status, Status.InvalidCommand, + "DUT must respond with Status Code InvalidCommand.") + except InteractionModelError as e: + asserts.assert_equal(e.status, Status.InvalidCommand, + "DUT must respond with Status Code InvalidCommand.") + + # Step 21a: Try to allocate transport with VideoStreamID and VideoStreams containing same ID + self.step("21a") + # Get stream usage priorities for the command + aStreamUsagePriorities = await self.read_single_attribute_check_success( + endpoint=endpoint, cluster=avcluster, attribute=avattr.StreamUsagePriorities + ) + asserts.assert_greater(len(aStreamUsagePriorities), 0, "StreamUsagePriorities is empty") + + # Create transport options with both VideoStreamID and VideoStreams containing the same ID + # This should cause a conflict and return INVALID_COMMAND + transport_options_21a = { + "streamUsage": aStreamUsagePriorities[0], + "videoStreamID": aAllocatedVideoStreams[0], # Use first allocated video stream ID + "audioStreamID": NullValue, + "videoStreams": [{ + "videoStreamID": aAllocatedVideoStreams[0], # Same ID as videoStreamID - this creates the conflict + "videoStreamName": "video" + }], + "audioStreams": [], + "TLSEndpointID": tlsEndpointId, + "url": f"https://{host_ip}:1234/streams/{uploadStreamId}/", + "triggerOptions": { + "triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kContinuous + }, + "ingestMethod": pvcluster.Enums.IngestMethodsEnum.kCMAFIngest, + "containerOptions": { + "containerType": pvcluster.Enums.ContainerFormatEnum.kCmaf, + "CMAFContainerOptions": { + "CMAFInterface": pvcluster.Enums.CMAFInterfaceEnum.kInterface1, + "chunkDuration": 4, + "segmentDuration": 4000, + "sessionGroup": 3, + "trackName": "media" + } + }, + "expiryTime": 30 + } + + try: + await self.send_single_cmd( + cmd=pvcluster.Commands.AllocatePushTransport(transport_options_21a), + endpoint=endpoint) + asserts.fail("Step 21a failed: Expected INVALID_COMMAND status code") + except InteractionModelError as e: + asserts.assert_equal(e.status, Status.InvalidCommand, + "Push AV Transport should return INVALID_COMMAND for step 21a") + + # Step 22: Try to allocate transport with both VideoStreamID and AudioStreamID set to NULL + self.step(22) + # TH sends the AllocatePushTransport command with both VideoStreamID and AudioStreamID set to NULL + # and no VideoStreams or AudioStreams fields present + try: + allocatePushTransportResponse = await self.send_single_cmd( + cmd=pvcluster.Commands.AllocatePushTransport({ + "streamUsage": streamUsage, + "videoStreamID": Nullable(), + "audioStreamID": Nullable(), + "TLSEndpointID": tlsEndpointId, + "url": f"https://{host_ip}:1234/streams/{uploadStreamId}/", + "triggerOptions": {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kContinuous}, + "ingestMethod": pvcluster.Enums.IngestMethodsEnum.kCMAFIngest, + "containerOptions": { + "containerType": pvcluster.Enums.ContainerFormatEnum.kCmaf, + "CMAFContainerOptions": { + "CMAFInterface": pvcluster.Enums.CMAFInterfaceEnum.kInterface1, + "segmentDuration": 4000, + "chunkDuration": 2000, + "sessionGroup": 1, + "trackName": "media" + } + }, + "expiryTime": 5 + }), + endpoint=endpoint + ) + + # DUT responds with AllocatePushTransportResponse containing the allocated ConnectionID, store this as aConnectionID-2 + asserts.assert_is_not_none(allocatePushTransportResponse, "AllocatePushTransportResponse must not be None") + asserts.assert_is_not_none(allocatePushTransportResponse.transportConfiguration.connectionID, + "ConnectionID must be present in response") + aConnectionID_2 = allocatePushTransportResponse.transportConfiguration.connectionID + + # If TransportOptions is present, verify the required fields + transportOptions = allocatePushTransportResponse.transportConfiguration.transportOptions + if transportOptions is not None: + # Verify AudioStreamId field is present containing the allocated audio stream ID + asserts.assert_true(hasattr(transportOptions, 'audioStreamID'), + "AudioStreamId field must be present in TransportOptions") + + # Handle both nullable and plain uint cases + if hasattr(transportOptions.audioStreamID, 'IsNull'): + asserts.assert_false(transportOptions.audioStreamID.IsNull(), + "AudioStreamId must not be null") + allocatedAudioStreamID = transportOptions.audioStreamID.Value() + else: + allocatedAudioStreamID = transportOptions.audioStreamID + + # Verify VideoStreamId field is present containing the allocated video stream ID + asserts.assert_true(hasattr(transportOptions, 'videoStreamID'), + "VideoStreamId field must be present in TransportOptions") + + # Handle both nullable and plain uint cases + if hasattr(transportOptions.videoStreamID, 'IsNull'): + asserts.assert_false(transportOptions.videoStreamID.IsNull(), + "VideoStreamId must not be null") + allocatedVideoStreamID = transportOptions.videoStreamID.Value() + else: + allocatedVideoStreamID = transportOptions.videoStreamID + + # Verify VideoStreams field is present with correct entry + asserts.assert_true(hasattr(transportOptions, 'videoStreams'), + "VideoStreams field must be present in TransportOptions") + videoStreams = transportOptions.videoStreams + asserts.assert_is_not_none(videoStreams, "VideoStreams must not be None") + asserts.assert_equal(len(videoStreams), 1, "VideoStreams must contain exactly one entry") + asserts.assert_equal(videoStreams[0].videoStreamID, allocatedVideoStreamID, + "VideoStreamID in VideoStreams must match allocated VideoStreamId") + asserts.assert_equal(videoStreams[0].videoStreamName, "video", + "VideoStreamName must be 'video'") + + # Verify AudioStreams field is present with correct entry + asserts.assert_true(hasattr(transportOptions, 'audioStreams'), + "AudioStreams field must be present in TransportOptions") + audioStreams = transportOptions.audioStreams + asserts.assert_is_not_none(audioStreams, "AudioStreams must not be None") + asserts.assert_equal(len(audioStreams), 1, "AudioStreams must contain exactly one entry") + asserts.assert_equal(audioStreams[0].audioStreamID, allocatedAudioStreamID, + "AudioStreamID in AudioStreams must match allocated AudioStreamId") + asserts.assert_equal(audioStreams[0].audioStreamName, "audio", + "AudioStreamName must be 'audio'") + + except InteractionModelError as e: + asserts.fail(f"AllocatePushTransport command failed: {e.status}") + + # Step 23: Try to allocate transport with MotionZones list size > aMaxZones (if zone management cluster is present) + self.step(23) + # Create a zoneList that is one larger than max zones that we have already read + zoneList = [] + for i in range(aMaxZones+1): + itemToAppend = {"zone": i, "sensitivity": 4} + zoneList.append(itemToAppend) + triggerOptions = {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kMotion, + "maxPreRollLen": 4000, + "motionZones": zoneList, + "motionTimeControl": {"initialDuration": 1, "augmentationDuration": 1, "maxDuration": 1, "blindDuration": 1}} + status = await self.allocate_one_pushav_transport(endpoint, trigger_Options=triggerOptions, + tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.DynamicConstraintError, + "DUT must respond with Status code DynamicConstraintError") + + # Step 24: Only run if DUT supports PerZoneSensitivity + if self.perZoneSenseSupported: + self.step(24) + zoneList = [] + triggerOptions = {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kMotion, + "motionTimeControl": {"initialDuration": 1, "augmentationDuration": 1, "maxDuration": 1, "blindDuration": 1}, + "motionSensitivity": 3, + "motionZones": zoneList} + status = await self.allocate_one_pushav_transport(endpoint, trigger_Options=triggerOptions, tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.InvalidCommand, + "DUT must responds with Status Code InvalidCommand.") + else: + self.skip_step(24) + + # Step 25: Only run if DUT does NOT support PerZoneSensitivity + if not self.perZoneSenseSupported: + self.step(25) + zoneList = [] + triggerOptions = {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kMotion, + "motionTimeControl": {"initialDuration": 1, "augmentationDuration": 1, "maxDuration": 1, "blindDuration": 1}, + "motionSensitivity": 11, + "motionZones": zoneList} + status = await self.allocate_one_pushav_transport(endpoint, trigger_Options=triggerOptions, tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.ConstraintError, + "DUT must responds with Status Code ConstraintError.") + else: + self.skip_step(25) + + # Step 26: Try to allocate transport with MotionTimeControl omitted + self.step(26) + zoneList = [] + triggerOptions = {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kMotion, + "motionZones": zoneList, + "motionSensitivity": 3} + status = await self.allocate_one_pushav_transport(endpoint, trigger_Options=triggerOptions, tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.InvalidCommand, + "DUT must responds with Status Code InvalidCommand.") + + # Step 27: Try to allocate transport with MotionTimeControl.InitialDuration = 0 + self.step(27) + zoneList = [] + triggerOptions = {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kMotion, + "motionZones": zoneList, + "motionSensitivity": 3, + "motionTimeControl": {"initialDuration": 0, "augmentationDuration": 1, "maxDuration": 1, "blindDuration": 1}} + status = await self.allocate_one_pushav_transport(endpoint, trigger_Options=triggerOptions, tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.ConstraintError, + "DUT must responds with Status code ConstraintError") + + self.step(28) + zoneList = [] + triggerOptions = {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kMotion, + "motionZones": zoneList, + "motionSensitivity": 3, + "motionTimeControl": {"initialDuration": 1, "augmentationDuration": 1, "maxDuration": 0, "blindDuration": 1}} + status = await self.allocate_one_pushav_transport(endpoint, trigger_Options=triggerOptions, tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.ConstraintError, + "DUT must responds with Status code ConstraintError") + + # Step 29: Deallocate transport and allocate new one with MotionZones and MotionSensitivity NULL + self.step(29) + # First deallocate the existing transport + cmd = pvcluster.Commands.DeallocatePushTransport( + connectionID=aConnectionID_1 + ) + status = await self.psvt_deallocate_push_transport(cmd) + asserts.assert_true(status == Status.Success, + "DUT responds with SUCCESS status code.") + zoneList = [] + triggerOptions = {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kMotion, + "maxPreRollLen": 4000, + "motionZones": zoneList, + "MotionSensitivity": NullValue, + "motionTimeControl": {"initialDuration": 1, "augmentationDuration": 1, "maxDuration": 1, "blindDuration": 1}} + + status = await self.allocate_one_pushav_transport(endpoint, trigger_Options=triggerOptions, tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.Success, + "DUT must responds with Status Code Success.") + current_connections = await self.read_single_attribute_check_success( + endpoint=endpoint, cluster=pvcluster, attribute=pvcluster.Attributes.CurrentConnections + ) + aConnectionID = current_connections[len(current_connections)-1].connectionID + + # Step 30: Deallocate transport and allocate new one with empty MotionZones + self.step(30) + # First deallocate the existing transport + cmd = pvcluster.Commands.DeallocatePushTransport( + connectionID=aConnectionID_2 + ) + status = await self.psvt_deallocate_push_transport(cmd) + asserts.assert_true(status == Status.Success, + "DUT responds with SUCCESS status code.") + zoneList = [] + triggerOptions = {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kMotion, + "maxPreRollLen": 4000, + "motionZones": zoneList, + "motionTimeControl": {"initialDuration": 1, "augmentationDuration": 1, "maxDuration": 1, "blindDuration": 1}} + + status = await self.allocate_one_pushav_transport(endpoint, trigger_Options=triggerOptions, tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.Success, + "DUT must responds with Status Code Success.") + current_connections = await self.read_single_attribute_check_success( + endpoint=endpoint, cluster=pvcluster, attribute=pvcluster.Attributes.CurrentConnections + ) + aConnectionID = current_connections[len(current_connections)-1].connectionID + log.info(f"aConnectionID: {aConnectionID}") + + # Step 31: Try to allocate transport with invalid StreamUsage + self.step(31) + status = await self.allocate_one_pushav_transport( + endpoint, + stream_Usage=Clusters.Globals.Enums.StreamUsageEnum.kUnknownEnumValue, + tlsEndPoint=tlsEndpointId, + url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.ConstraintError, + "DUT must responds with Status code ConstraintError") + + # Step 32: Try to allocate transport with ContainerType = CMAF and CMAFContainerOptions omitted + self.step(32) + containerOptions = {"containerType": pvcluster.Enums.ContainerFormatEnum.kCmaf} + status = await self.allocate_one_pushav_transport(endpoint, container_Options=containerOptions, tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.InvalidCommand, + "DUT must responds with Status code InvalidCommand") + + # Step 33: Try to allocate transport with CMAFContainerOptions having invalid segment duration + self.step(33) + # Get the key frame interval from the first allocated video stream + keyFrameInterval = 1000 # Default value + if aAllocatedVideoStreams and len(aAllocatedVideoStreams) > 0: + # We don't have direct access to keyFrameInterval, so we'll use a value that's not a multiple + keyFrameInterval = 33 # This should not be a multiple of common segment durations + + # Create CMAF container options with segment duration that's not a multiple of keyFrameInterval + invalid_segment_container_options = { + "containerType": pvcluster.Enums.ContainerFormatEnum.kCmaf, + "CMAFContainerOptions": { + "CMAFInterface": pvcluster.Enums.CMAFInterfaceEnum.kInterface1, + "chunkDuration": 4, + "segmentDuration": 1001, # Not a multiple of common keyFrameIntervals + "sessionGroup": 3, + "trackName": "media" + } + } + status = await self.allocate_one_pushav_transport( + endpoint, + container_Options=invalid_segment_container_options, + tlsEndPoint=tlsEndpointId, + url=f"https://{host_ip}:1234/streams/{uploadStreamId}/", + expected_cluster_status=pvcluster.Enums.StatusCodeEnum.kInvalidOptions) + asserts.assert_equal(status, pvcluster.Enums.StatusCodeEnum.kInvalidOptions, + "Push AV Transport should return InvalidOptions for invalid segment duration") + + # Step 34: Try to allocate transport with StreamUsage not in SupportedStreamUsages + self.step(34) + # We'll use an invalid StreamUsage value + invalid_stream_usage = Clusters.Globals.Enums.StreamUsageEnum.kInternal + status = await self.allocate_one_pushav_transport( + endpoint, + stream_Usage=invalid_stream_usage, + tlsEndPoint=tlsEndpointId, + url=f"https://{host_ip}:1234/streams/{uploadStreamId}/", + expected_cluster_status=pvcluster.Enums.StatusCodeEnum.kInvalidStreamUsage) + asserts.assert_equal(status, pvcluster.Enums.StatusCodeEnum.kInvalidStreamUsage, + "Push AV Transport should return InvalidStreamUsage for invalid StreamUsage") + + # Step 35: Try to allocate transport with MaxPreRollLen less than KeyFrameInterval + self.step(35) + # Read the KeyFrameInterval from the allocated video stream + videoStreamConfig = await self.read_single_attribute_check_success( + endpoint=endpoint, + cluster=avcluster, + attribute=avattr.AllocatedVideoStreams + ) + keyFrameInterval = videoStreamConfig[0].keyFrameInterval + print(f"keyframeinterval: {keyFrameInterval}") + + # Send AllocatePushTransport with maxPreRollLen < KeyFrameInterval + triggerOptions = { + "triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kMotion, + "maxPreRollLen": 200, # Less than KeyFrameInterval + "motionZones": [], # Required for kMotion trigger type + # Required for kMotion trigger type + "motionTimeControl": {"initialDuration": 1, "augmentationDuration": 1, "maxDuration": 1, "blindDuration": 1} + } + + status = await self.allocate_one_pushav_transport( + endpoint, + trigger_Options=triggerOptions, + tlsEndPoint=tlsEndpointId, + url=f"https://{host_ip}:1234/streams/{uploadStreamId}/", + expected_cluster_status=pvcluster.Enums.StatusCodeEnum.kInvalidPreRollLength + ) + asserts.assert_equal( + status, pvcluster.Enums.StatusCodeEnum.kInvalidPreRollLength, + "DUT must respond with InvalidPreRollLength when maxPreRollLen < KeyFrameInterval" + ) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_PAVST_2_12.py b/src/python_testing/TC_PAVST_2_12.py new file mode 100644 index 00000000000..5bfa2716ee7 --- /dev/null +++ b/src/python_testing/TC_PAVST_2_12.py @@ -0,0 +1,392 @@ +# +# Copyright (c) 2025 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. + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${CAMERA_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --app-pipe /tmp/pavst_2_12_fifo --camera-test-videosrc --camera-test-audiosrc +# script-args: > +# --storage-path admin_storage.json +# --string-arg th_server_app_path:${PUSH_AV_SERVER} +# --string-arg host_ip:localhost +# --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 +# --endpoint 1 +# --app-pipe /tmp/pavst_2_12_fifo +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import asyncio +import logging +import time + +from mobly import asserts +from TC_PAVSTI_Utils import PAVSTIUtils, PushAvServerProcess +from TC_PAVSTTestBase import PAVSTTestBase + +import matter.clusters as Clusters +from matter.interaction_model import InteractionModelError, Status +from matter.testing.decorators import async_test_body, has_cluster, run_if_endpoint_matches +from matter.testing.event_attribute_reporting import EventSubscriptionHandler +from matter.testing.matter_testing import MatterBaseTest, TestStep +from matter.testing.runner import default_matter_test_main + +logger = logging.getLogger(__name__) + + +class TC_PAVST_2_12(MatterBaseTest, PAVSTTestBase, PAVSTIUtils): + def desc_TC_PAVST_2_12(self) -> str: + return "[TC-PAVST-2.12] Validate PushAV Clip record for Motion Trigger" + + def pics_TC_PAVST_2_12(self): + return ["PAVST.S", "AVSM.S", "ZONEMGMT.S"] + + @async_test_body + async def setup_class(self): + th_server_app = self.user_params.get("th_server_app_path", None) + self.server = PushAvServerProcess(server_path=th_server_app) + self.server.start( + expected_output="Running on https://0.0.0.0:1234", + timeout=30, + ) + super().setup_class() + + def teardown_class(self): + if self.server is not None: + self.server.terminate() + super().teardown_class() + + def steps_TC_PAVST_2_12(self) -> list[TestStep]: + return [ + TestStep("precondition", "Commissioning, already done", is_commissioning=True), + TestStep( + 1, + "TH Reads CurrentConnections attribute from PushAV Stream Transport Cluster on DUT", + "Verify the number of PushAV Connections is 0. If not 0, deallocate any existing connections.", + ), + TestStep( + 2, + "TH Reads AllocatedVideoStreams attribute from CameraAVStreamManagement Cluster on DUT", + "Store as aAllocatedVideoStreams.", + ), + TestStep( + 3, + "TH Reads AllocatedAudioStreams attribute from CameraAVStreamManagement Cluster on DUT", + "Store as aAllocatedAudioStreams.", + ), + TestStep( + 4, + "TH Reads Zones attribute from Zones Management Cluster on DUT", + "Store as aZones.", + ), + TestStep( + 5, + "If DUT supports TwoDCartesianZone and User defined zones, TH sends CreateTwoDCartesianZone command.", + "Verify that the DUT response contains a new zoneId, store in aZoneID"), + TestStep( + 6, + "TH sends AllocatePushTransport command with TriggerType = Motion, MotionZones = [aZoneID]", + "DUT responds with AllocatePushTransportResponse containing the allocated ConnectionID, TransportOptions, and TransportStatus in the TransportConfigurationStruct. Store ConnectionID as aConnectionID1."), + TestStep( + 7, + "TH sends SetTransportStatus command with ConnectionID = aConnectionID1 and TransportStatus = Active", + "DUT responds with SUCCESS status code.", + ), + TestStep( + 8, + "TH subscribes to the DUT's PushTransportBegin event and Motion Event triggers the DUT to generate PushAV Event", + "Successful completion of steps" + ), + TestStep( + 9, + "DUT generates a PushTransportBegin event with ConnectionID = aConnectionID1", + "TH waits for the events from DUT with timeout of 5 sec, Verifies that the PushTransportBegin event is triggered.", + ), + TestStep( + 10, + "TH sends DeallocatePushTransport command with ConnectionID = aConnectionID1", + "DUT responds with SUCCESS status code.", + ), + TestStep( + 11, + "TH Reads CurrentConnections attribute from PushAV Stream Transport Cluster on DUT", + "Verify the number of PushAV Connections is 0. If not 0, deallocate any existing connections.", + ), + TestStep( + 12, + "TH sends AllocatePushTransport command with TriggerType = Motion, MotionZones = [aZoneID]", + "DUT responds with AllocatePushTransportResponse containing the allocated ConnectionID, TransportOptions, and TransportStatus in the TransportConfigurationStruct. Store ConnectionID as aConnectionID2.", + ), + TestStep( + 13, + "Motion Event triggers the DUT to generate PushAV Event", + "Successful completion of steps." + ), + TestStep( + 14, + "TH waits for the events from DUT with timeout of 5 sec", + "Verifies that no PushTransportBegin event is triggered." + ), + TestStep( + 15, + "TH sends SetTransportStatus command with ConnectionID = aConnectionID2 and TransportStatus = Active", + "DUT responds with SUCCESS status code." + ), + TestStep( + 16, + "TH waits for the events from DUT with timeout of 5 sec", + "Verifies that the PushTransportBegin event with ConnectionID = aConnectionID2 is triggered.", + ), + TestStep( + 17, + "TH waits with a timeout of initial duration + pre-roll length sec for PushTransportEnd event then waits for 5 sec and sends DeallocatePushTransport command with ConnectionID = aConnectionID2", + "DUT responds with SUCCESS status code.", + ), + ] + + async def _trigger_motion_event(self, zone_id, prompt_msg=None): + # CI: Use app pipe to trigger zone event. + # Manual: User should trigger a motion event from the defined zone. + if self.is_pics_sdk_ci_only: + self.write_to_app_pipe({"Name": "ZoneTriggered", "ZoneId": zone_id}) + else: + if prompt_msg is None: + prompt_msg = f"Press enter and immediately start motion activity in zone {zone_id}." + self.wait_for_user_input(prompt_msg=prompt_msg) + + @run_if_endpoint_matches(has_cluster(Clusters.PushAvStreamTransport) and has_cluster(Clusters.ZoneManagement) and has_cluster(Clusters.CameraAvStreamManagement)) + async def test_TC_PAVST_2_12(self): + endpoint = self.get_endpoint() + self.endpoint = endpoint + self.node_id = self.dut_node_id + pvcluster = Clusters.PushAvStreamTransport + pvattr = Clusters.PushAvStreamTransport.Attributes + zmcluster = Clusters.ZoneManagement + zmattr = Clusters.ZoneManagement.Attributes + aAllocatedVideoStreams = [] + aAllocatedAudioStreams = [] + + aConnectionID1 = "" + + self.step("precondition") + host_ip = self.user_params.get("host_ip", None) + tlsEndpointId, host_ip = await self.precondition_provision_tls_endpoint(endpoint=endpoint, server=self.server, host_ip=host_ip) + uploadStreamId = self.server.create_stream() + + self.step(1) + # Commission DUT - already done + status = await self.check_and_delete_all_push_av_transports(endpoint, pvattr) + asserts.assert_equal( + status, Status.Success, "Status must be SUCCESS!" + ) + + self.step(2) + aAllocatedVideoStreams = await self.allocate_one_video_stream() + asserts.assert_greater_equal( + len(aAllocatedVideoStreams), + 1, + "AllocatedVideoStreams must not be empty", + ) + + self.step(3) + aAllocatedAudioStreams = await self.allocate_one_audio_stream() + asserts.assert_greater_equal( + len(aAllocatedAudioStreams), + 1, + "AllocatedAudioStreams must not be empty", + ) + + self.step(4) + aZones = await self.read_single_attribute_check_success( + endpoint=endpoint, cluster=zmcluster, attribute=zmattr.Zones + ) + logger.info(f"aZones: {aZones}") + + self.step(5) + aFeatureMap = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=zmcluster, attribute=zmattr.FeatureMap) + logger.info(f"Rx'd FeatureMap: {aFeatureMap}") + self.twoDCartSupported = aFeatureMap & zmcluster.Bitmaps.Feature.kTwoDimensionalCartesianZone + self.userDefinedSupported = aFeatureMap & zmcluster.Bitmaps.Feature.kUserDefined + self.perZoneSensSupported = aFeatureMap & zmcluster.Bitmaps.Feature.kPerZoneSensitivity + + if self.twoDCartSupported and self.userDefinedSupported: + + # Form the Create request and send + zoneVertices = [ + zmcluster.Structs.TwoDCartesianVertexStruct(10, 10), + zmcluster.Structs.TwoDCartesianVertexStruct(20, 10), + zmcluster.Structs.TwoDCartesianVertexStruct(20, 20), + zmcluster.Structs.TwoDCartesianVertexStruct(10, 20) + ] + zoneToCreate = zmcluster.Structs.TwoDCartesianZoneStruct( + name="Zone1", use=zmcluster.Enums.ZoneUseEnum.kMotion, vertices=zoneVertices, + color="#00FFFF") + createTwoDCartesianCmd = zmcluster.Commands.CreateTwoDCartesianZone( + zone=zoneToCreate + ) + cmdResponse = await self.send_single_cmd(endpoint=endpoint, cmd=createTwoDCartesianCmd) + logger.info(f"Rx'd CreateTwoDCartesianZoneResponse : {cmdResponse}") + asserts.assert_equal(type(cmdResponse), zmcluster.Commands.CreateTwoDCartesianZoneResponse, + "Incorrect response type") + asserts.assert_is_not_none( + cmdResponse.zoneID, "CreateTwoDCartesianCmdResponse does not contain ZoneID") + + # Check that created zoneID did not exist before + matchingZone = next( + (z for z in aZones if z.zoneID == cmdResponse.zoneID), None) + asserts.assert_is_none(matchingZone, "fZone with {cmdResponse.zoneID} already existed in Zones") + aZones = cmdResponse.zoneID + + self.step(6) + initDuration = 10 + augDuration = 5 + maxDuration = 20 + blindDuration = 1 + preRollLength = 4 + try: + zoneList = [{"zone": aZones, "sensitivity": 4}] + triggerOptions = {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kMotion, + "maxPreRollLen": preRollLength*1000, + "motionZones": zoneList, + "motionTimeControl": {"initialDuration": initDuration, "augmentationDuration": augDuration, "maxDuration": maxDuration, "blindDuration": blindDuration}} + status = await self.allocate_one_pushav_transport(endpoint, trigger_Options=triggerOptions, + tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.Success, + "DUT must respond with Status Code Success.") + except InteractionModelError as e: + asserts.assert_equal(e.clusterStatus, Status.Success, + "Unexpected error: DUT must respond with Status Code Success.") + + transportConfigs = await self.read_pavst_attribute_expect_success(endpoint, + pvattr.CurrentConnections, + ) + asserts.assert_greater_equal( + len(transportConfigs), 1, "TransportConfigurations must not be empty!" + ) + aConnectionID1 = transportConfigs[0].connectionID + + self.step(7) + cmd = pvcluster.Commands.SetTransportStatus( + connectionID=aConnectionID1, + transportStatus=pvcluster.Enums.TransportStatusEnum.kActive + ) + status = await self.psvt_set_transport_status(cmd) + asserts.assert_true( + status == Status.Success, + "DUT responds with SUCCESS status code.") + + self.step(8) + event_callback = EventSubscriptionHandler(expected_cluster=pvcluster) + await event_callback.start(self.default_controller, + self.dut_node_id, + self.get_endpoint()) + await self._trigger_motion_event(aZones, prompt_msg=f"Press enter and immediately start motion activity in zone {aZones} and stop any motion after {initDuration} seconds of pressing enter.") + + self.step(9) + event_data = event_callback.wait_for_event_report(pvcluster.Events.PushTransportBegin, timeout_sec=5) + logger.info(f"Event data {event_data}") + asserts.assert_equal(event_data.connectionID, aConnectionID1, "Unexpected value for ConnectionID returned") + + self.step(10) + cmd = pvcluster.Commands.DeallocatePushTransport( + connectionID=aConnectionID1 + ) + status = await self.psvt_deallocate_push_transport(cmd) + asserts.assert_true( + status == Status.Success, + "DUT responds with SUCCESS status code.") + + self.step(11) + status = await self.check_and_delete_all_push_av_transports(endpoint, pvattr) + asserts.assert_equal( + status, Status.Success, "Status must be SUCCESS!" + ) + + self.step(12) + try: + zoneList = [{"zone": aZones, "sensitivity": 4}] + triggerOptions = {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kMotion, + "maxPreRollLen": preRollLength*1000, + "motionZones": zoneList, + "motionTimeControl": {"initialDuration": initDuration, "augmentationDuration": augDuration, "maxDuration": maxDuration, "blindDuration": blindDuration}} + status = await self.allocate_one_pushav_transport(endpoint, trigger_Options=triggerOptions, + tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.Success, + "DUT must respond with Status Code Success.") + except InteractionModelError as e: + asserts.assert_equal(e.clusterStatus, Status.Success, + "Unexpected error: DUT must respond with Status Code Success.") + + transportConfigs = await self.read_pavst_attribute_expect_success(endpoint, + pvattr.CurrentConnections, + ) + asserts.assert_greater_equal( + len(transportConfigs), 1, "TransportConfigurations must not be empty!" + ) + aConnectionID2 = transportConfigs[0].connectionID + + self.step(13) + event_callback = EventSubscriptionHandler(expected_cluster=pvcluster) + await event_callback.start(self.default_controller, + self.dut_node_id, + self.get_endpoint()) + await self._trigger_motion_event(aZones, prompt_msg=f"Press enter and immediately start motion activity in zone {aZones} and stop any motion after {initDuration} seconds of pressing enter.") + + self.step(14) + event_data = event_callback.wait_for_event_expect_no_report(timeout_sec=5) + logger.info(f"Successfully timed out without receiving any PushTransportBegin event for zone: {aZones}") + + self.step(15) + cmd = pvcluster.Commands.SetTransportStatus( + connectionID=aConnectionID2, + transportStatus=pvcluster.Enums.TransportStatusEnum.kActive + ) + status = await self.psvt_set_transport_status(cmd) + asserts.assert_true( + status == Status.Success, + "DUT responds with SUCCESS status code.") + + self.step(16) + event_data = event_callback.wait_for_event_report(pvcluster.Events.PushTransportBegin, timeout_sec=5) + logger.info(f"Event data {event_data}") + asserts.assert_equal(event_data.connectionID, aConnectionID2, "Unexpected value for ConnectionID returned") + + self.step(17) + event_data = event_callback.wait_for_event_report(pvcluster.Events.PushTransportEnd, timeout_sec=initDuration+preRollLength) + logger.info(f"Event data {event_data}") + asserts.assert_equal(event_data.connectionID, aConnectionID2, "Unexpected value for ConnectionID returned") + + await asyncio.to_thread(time.sleep, 5) # Wait for 5 seconds before sending DeallocatePushTransport command + cmd = pvcluster.Commands.DeallocatePushTransport( + connectionID=aConnectionID2 + ) + status = await self.psvt_deallocate_push_transport(cmd) + asserts.assert_true( + status == Status.Success, + "DUT responds with SUCCESS status code.") + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_PAVST_2_13.py b/src/python_testing/TC_PAVST_2_13.py new file mode 100644 index 00000000000..9458465ec82 --- /dev/null +++ b/src/python_testing/TC_PAVST_2_13.py @@ -0,0 +1,508 @@ +# +# Copyright (c) 2025 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. + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${CAMERA_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --app-pipe /tmp/pavst_2_13_fifo --camera-test-videosrc --camera-test-audiosrc +# script-args: > +# --storage-path admin_storage.json +# --string-arg th_server_app_path:${PUSH_AV_SERVER} +# --string-arg host_ip:localhost +# --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 +# --endpoint 1 +# --app-pipe /tmp/pavst_2_13_fifo +# --timeout 300 +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import asyncio +import logging +import time + +from mobly import asserts +from TC_PAVSTI_Utils import PAVSTIUtils, PushAvServerProcess +from TC_PAVSTTestBase import PAVSTTestBase + +import matter.clusters as Clusters +from matter.interaction_model import InteractionModelError, Status +from matter.testing.decorators import async_test_body, has_cluster, run_if_endpoint_matches +from matter.testing.event_attribute_reporting import EventSubscriptionHandler +from matter.testing.matter_testing import MatterBaseTest, TestStep +from matter.testing.runner import default_matter_test_main + +logger = logging.getLogger(__name__) + + +class TC_PAVST_2_13(MatterBaseTest, PAVSTTestBase, PAVSTIUtils): + def desc_TC_PAVST_2_13(self) -> str: + return "[TC-PAVST-2.13] Verify time control fields with Manual and Motion Trigger" + + def pics_TC_PAVST_2_13(self): + return ["PAVST.S", "AVSM.S", "ZONEMGMT.S"] + + @async_test_body + async def setup_class(self): + th_server_app = self.user_params.get("th_server_app_path", None) + self.server = PushAvServerProcess(server_path=th_server_app) + self.server.start( + expected_output="Running on https://0.0.0.0:1234", + timeout=30, + ) + super().setup_class() + + def teardown_class(self): + if self.server is not None: + self.server.terminate() + super().teardown_class() + + def steps_TC_PAVST_2_13(self) -> list[TestStep]: + return [ + TestStep("precondition", "Commissioning, already done", is_commissioning=True), + TestStep( + 1, + "TH Reads CurrentConnections attribute from PushAV Stream Transport Cluster on DUT", + "Verify the number of PushAV Connections is 0. If not 0, deallocate any existing connections.", + ), + TestStep( + 2, + "TH Reads AllocatedVideoStreams attribute from CameraAVStreamManagement Cluster on DUT", + "Store as aAllocatedVideoStreams.", + ), + TestStep( + 3, + "TH Reads AllocatedAudioStreams attribute from CameraAVStreamManagement Cluster on DUT", + "Store as aAllocatedAudioStreams.", + ), + TestStep( + 4, + "TH Reads Zones attribute from Zones Management Cluster on DUT", + "Store as aZones.", + ), + TestStep( + 5, + "If DUT supports TwoDCartesianZone and User defined zones, TH sends CreateTwoDCartesianZone command.", + "Verify that the DUT response contains a new zoneId."), + TestStep( + 6, + "TH sends AllocatePushTransport command with TriggerType = Motion, MotionZones = [aZoneID]", + "DUT responds with AllocatePushTransportResponse containing the allocated ConnectionID, TransportOptions, and TransportStatus in the TransportConfigurationStruct. Store ConnectionID as aConnectionID1."), + TestStep( + 7, + "TH sends SetTransportStatus command with ConnectionID = aConnectionID1 and TransportStatus = Active", + "DUT responds with SUCCESS status code." + ), + TestStep( + 8, + "TH subscribes for the events from the DUT and sends the ManuallyTriggerTransport command with ConnectionID = aConnectionID1 and time control fields", + "DUT generates PushTransportBegin Event and responds with SUCCESS status code.", + ), + TestStep( + 9, + "TH waits with a timeout of 5 seconds for PushTransportBeginEvent from DUT and then Motion event triggers the DUT to increment the Clip duration by the AugmentationDuration - AUGMENTATION DURATION Check", + "Verify that the TH receives the PushTransportEnd event after (InitialDuration + AugmentationDuration) and the connectionID matches aConnectionID1.", + ), + TestStep( + 10, + "Motion Event triggers the DUT to generate PushAV Event during BlindDuration after PushTransportEnd event was received - BLIND DURATION Check", + "Verify that the TH receives the PushTransportBegin event.", + ), + TestStep( + 11, + "TH waits for PushTransportEnd event, then, after blind duration of previous recording passes, Motion Event triggers the DUT to generate PushAV Event and then TH waits for the events from DUT", + "Verify that the TH receives the PushTransportBegin event.", + ), + TestStep( + 12, + "Again Motion Event triggers the DUT to generate PushAV Event to increment the Clip duration by the AugmentationDuration - AUGMENTATION DURATION Check", + "Verify that the TH receives the PushTransportEnd event after (InitialDuration + AugmentationDuration) and the connectionID matches aConnectionID1.", + ), + TestStep( + 13, + "Motion Event triggers the DUT to generate PushAV Event during BlindDuration after PushTransportEnd event was received - BLIND DURATION check, no recording should start for trigger during blind duration", + "Verify that the TH receives no PushAV event.", + ), + TestStep( + 14, + "Motion Event triggers the DUT to generate PushAV Event - BLIND DURATION check, recording should start for trigger after blind duration", + "Verify that the TH receives the PushTransportBegin event and after InitialDuration it should receive PushTransportEnd event.", + ), + TestStep( + 15, + "Motion Event triggers the DUT to generate PushAV Event after BlindDuration of previous recording passes", + "Verify that PushTransportBegin event is triggered.", + ), + TestStep( + 16, + "TH sends DeallocatePushTransport command with ConnectionID = aConnectionID1", + "DUT responds with SUCCESS status code." + ), + TestStep( + 17, + "Repeat step-6 and step-7. Store ConnectionID as aConnectionID2", + "Successful completion of step." + ), + TestStep( + 18, + "Two consecutive Motion Event triggers the DUT to generate PushAV Events (InitialDuration + AugmentationDuration > MaxDuration).", + "Verify that the TH receives the PushTransportEnd event after MaxDuration and the connectionID matches aConnectionID2." + ), + + ] + + async def _trigger_motion_event(self, zone_id, prompt_msg=None): + # CI: Use app pipe to trigger zone event. + # Manual: User should trigger a motion event from the defined zone. + if self.is_pics_sdk_ci_only: + self.write_to_app_pipe({"Name": "ZoneTriggered", "ZoneId": zone_id}) + else: + if prompt_msg is None: + prompt_msg = f"Press enter and immediately start motion activity in zone {zone_id}." + self.wait_for_user_input(prompt_msg=prompt_msg) + + async def ensure_session_active(self): + """Ensure Matter session is active, reconnect if needed""" + try: + # Test session with a simple read from PushAvStreamTransport (we know this cluster exists) + await self.read_single_attribute_check_success( + endpoint=self.get_endpoint(), + cluster=Clusters.PushAvStreamTransport, + attribute=Clusters.PushAvStreamTransport.Attributes.FeatureMap + ) + except (TimeoutError, asyncio.CancelledError): + # Session timed out, re-establish + logger.info("Session timed out, re-establishing...") + await self.default_controller.EstablishSession(self.dut_node_id) + + @run_if_endpoint_matches(has_cluster(Clusters.PushAvStreamTransport) and has_cluster(Clusters.ZoneManagement) and has_cluster(Clusters.CameraAvStreamManagement)) + async def test_TC_PAVST_2_13(self): + endpoint = self.get_endpoint() + self.endpoint = endpoint + self.node_id = self.dut_node_id + pvcluster = Clusters.PushAvStreamTransport + pvattr = Clusters.PushAvStreamTransport.Attributes + zmcluster = Clusters.ZoneManagement + zmattr = Clusters.ZoneManagement.Attributes + aAllocatedVideoStreams = [] + aAllocatedAudioStreams = [] + aConnectionID = "" + zoneID1 = 1 # Default zone ID for testing + + self.step("precondition") + host_ip = self.user_params.get("host_ip", None) + tlsEndpointId, host_ip = await self.precondition_provision_tls_endpoint(endpoint=endpoint, server=self.server, host_ip=host_ip) + uploadStreamId = self.server.create_stream() + + self.step(1) + # Commission DUT - already done + status = await self.check_and_delete_all_push_av_transports(endpoint, pvattr) + asserts.assert_equal( + status, Status.Success, "Status must be SUCCESS!" + ) + + self.step(2) + aAllocatedVideoStreams = await self.allocate_one_video_stream() + asserts.assert_greater_equal( + len(aAllocatedVideoStreams), + 1, + "AllocatedVideoStreams must not be empty", + ) + + self.step(3) + aAllocatedAudioStreams = await self.allocate_one_audio_stream() + asserts.assert_greater_equal( + len(aAllocatedAudioStreams), + 1, + "AllocatedAudioStreams must not be empty", + ) + + self.step(4) + aZones = await self.read_single_attribute_check_success( + endpoint=endpoint, cluster=zmcluster, attribute=zmattr.Zones + ) + logger.info(f"aZones: {aZones}") + + self.step(5) + aFeatureMap = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=zmcluster, attribute=zmattr.FeatureMap) + logger.info(f"Rx'd FeatureMap: {aFeatureMap}") + self.twoDCartSupported = aFeatureMap & zmcluster.Bitmaps.Feature.kTwoDimensionalCartesianZone + self.userDefinedSupported = aFeatureMap & zmcluster.Bitmaps.Feature.kUserDefined + + if self.twoDCartSupported and self.userDefinedSupported: + # Form the Create request and send + zoneVertices = [ + zmcluster.Structs.TwoDCartesianVertexStruct(10, 10), + zmcluster.Structs.TwoDCartesianVertexStruct(20, 10), + zmcluster.Structs.TwoDCartesianVertexStruct(20, 20), + zmcluster.Structs.TwoDCartesianVertexStruct(10, 20) + ] + zoneToCreate = zmcluster.Structs.TwoDCartesianZoneStruct( + name="Zone1", use=zmcluster.Enums.ZoneUseEnum.kMotion, vertices=zoneVertices, + color="#00FFFF") + createTwoDCartesianCmd = zmcluster.Commands.CreateTwoDCartesianZone( + zone=zoneToCreate + ) + cmdResponse = await self.send_single_cmd(endpoint=endpoint, cmd=createTwoDCartesianCmd) + logger.info(f"Rx'd CreateTwoDCartesianZoneResponse : {cmdResponse}") + asserts.assert_equal(type(cmdResponse), zmcluster.Commands.CreateTwoDCartesianZoneResponse, + "Incorrect response type") + asserts.assert_is_not_none( + cmdResponse.zoneID, "CreateTwoDCartesianCmdResponse does not contain ZoneID") + + # Check that zoneID1 did not exist before + matchingZone = next( + (z for z in aZones if z.zoneID == cmdResponse.zoneID), None) + asserts.assert_is_none(matchingZone, "fZone with {cmdResponse.zoneID} already existed in Zones") + zoneID1 = cmdResponse.zoneID + + self.step(6) + # Initialze the time control fields + initDuration = 5 + augDuration = 2 + maxDuration = 15 + # blindDuration time set as 10 sec to ensure it is sufficient enough to receive the motion event at DUT post the clip recording is completed + blindDuration = 10 + maxPreRollLen = 4 + try: + zoneList = [{"zone": zoneID1, "sensitivity": 4}] + triggerOptions = {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kMotion, + "maxPreRollLen": 4000, + "motionZones": zoneList, + "motionTimeControl": {"initialDuration": initDuration, "augmentationDuration": augDuration, "maxDuration": maxDuration, "blindDuration": blindDuration}} + status = await self.allocate_one_pushav_transport(endpoint, trigger_Options=triggerOptions, + tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.Success, + "DUT must responds with Status Code Success.") + except InteractionModelError as e: + asserts.assert_equal(e.clusterStatus, Status.Success, + "DUT must responds with Status Code Success.") + + transportConfigs = await self.read_pavst_attribute_expect_success(endpoint, + pvattr.CurrentConnections, + ) + asserts.assert_greater_equal( + len(transportConfigs), 1, "TransportConfigurations must not be empty!" + ) + aConnectionID = transportConfigs[0].connectionID + + self.step(7) + cmd = pvcluster.Commands.SetTransportStatus( + connectionID=aConnectionID, + transportStatus=pvcluster.Enums.TransportStatusEnum.kActive + ) + status = await self.psvt_set_transport_status(cmd) + asserts.assert_true( + status == Status.Success, + "DUT responds with SUCCESS status code.") + + # Manual trigger + Motion trigger case -> Step handle Augmentation and blind duration + # Manual Trigger -> Recording start -> Motion trigger -> Clip Duration extended -> Recording stop -> Trigger motion event without waiting for blind period -> Recording should start + self.step(8) + event_callback = EventSubscriptionHandler(expected_cluster=pvcluster) + await event_callback.start(self.default_controller, + self.dut_node_id, + self.get_endpoint()) + + timeControl = {"initialDuration": initDuration, "augmentationDuration": augDuration, + "maxDuration": maxDuration, "blindDuration": blindDuration} + cmd = pvcluster.Commands.ManuallyTriggerTransport( + connectionID=aConnectionID, + activationReason=pvcluster.Enums.TriggerActivationReasonEnum.kEmergency, + timeControl=timeControl + ) + status = await self.psvt_manually_trigger_transport(cmd) + asserts.assert_true( + status == Status.Success, + "DUT responds with Success status code.", + ) + + self.step(9) + event_data = event_callback.wait_for_event_report(pvcluster.Events.PushTransportBegin, timeout_sec=5) + logger.info(f"Event data {event_data}") + asserts.assert_equal(event_data.connectionID, aConnectionID, "Unexpected value for ConnectionID returned") + + await self._trigger_motion_event(zoneID1, prompt_msg=f"Press enter and immediately start motion activity in zone {zoneID1} and stop any motion after {initDuration} seconds of pressing enter.") + # Clip duration is augmented + await asyncio.to_thread(time.sleep, initDuration + augDuration + 1) + + event_callback = EventSubscriptionHandler(expected_cluster=pvcluster) + await event_callback.start(self.default_controller, + self.dut_node_id, + self.get_endpoint()) + event_data = event_callback.wait_for_event_report(pvcluster.Events.PushTransportEnd, timeout_sec=5) + logger.info(f"Event data {event_data}") + asserts.assert_equal(event_data.connectionID, aConnectionID, "Unexpected value for ConnectionID returned") + + # Previous Recording stops and now new trigger came for which blind period is ignored and new recording should start because previous recording started due to manual trigger + self.step(10) + await self._trigger_motion_event(zoneID1, prompt_msg=f"Press enter and immediately start motion activity in zone {zoneID1} and stop any motion after {initDuration} seconds of pressing enter.") + # Since previous recording was started by manual trigger, blind period should be ignored and new recording should start + event_data = event_callback.wait_for_event_report(pvcluster.Events.PushTransportBegin, timeout_sec=5) + logger.info(f"Event data {event_data}") + asserts.assert_equal(event_data.connectionID, aConnectionID, "Unexpected value for ConnectionID returned") + + # Motion Trigger - Motion Trigger case (Check Augment duration and blind duration) + # Motion Trigger -> Recording Start -> Motion Trigger -> Clip Duration extended -> Recording stop -> Trigger motion event without waiting for blind period -> Recording should not start + self.step(11) + await asyncio.to_thread(time.sleep, initDuration + 1) + event_data = event_callback.wait_for_event_report(pvcluster.Events.PushTransportEnd, timeout_sec=5) + logger.info(f"Event data {event_data}") + asserts.assert_equal(event_data.connectionID, aConnectionID, "Unexpected value for ConnectionID returned") + await asyncio.to_thread(time.sleep, blindDuration + 1) + + event_callback = EventSubscriptionHandler(expected_cluster=pvcluster) + await event_callback.start(self.default_controller, + self.dut_node_id, + self.get_endpoint()) + + await self._trigger_motion_event(zoneID1, prompt_msg=f"Press enter and immediately start motion activity in zone {zoneID1} and stop any motion after {initDuration} seconds of pressing enter.") + + event_data = event_callback.wait_for_event_report(pvcluster.Events.PushTransportBegin, timeout_sec=5) + logger.info(f"Event data {event_data}") + asserts.assert_equal(event_data.connectionID, aConnectionID, "Unexpected value for ConnectionID returned") + + self.step(12) + await self._trigger_motion_event(zoneID1, prompt_msg=f"Press enter and immediately start motion activity in zone {zoneID1} and stop any motion after {initDuration} seconds of pressing enter.") + # Motion trigger during ongoing recording should NOT generate PushTransportBegin, only extend duration + # Clip duration augmented + await asyncio.to_thread(time.sleep, initDuration + augDuration + 1) + + event_data = event_callback.wait_for_event_report(pvcluster.Events.PushTransportEnd, timeout_sec=5) + logger.info(f"Event data {event_data}") + asserts.assert_equal(event_data.connectionID, aConnectionID, "Unexpected value for ConnectionID returned") + + # Previous recording stops, didn't waited for blind period-> sended another motion trigger -> new recording should not start -> Because previous Recording started due to motion trigger + self.step(13) + await self._trigger_motion_event(zoneID1, prompt_msg=f"Press enter and immediately start motion activity in zone {zoneID1} and stop any motion after {initDuration} seconds of pressing enter.") + event_data = event_callback.wait_for_event_expect_no_report(timeout_sec=blindDuration+1) + + # Motion Trigger - Motion Trigger case (Check blind duration) + # Trigger motion event-> wait for recording to stop. Wait for blind period to finish before sending another trigger -> Recording should start. + self.step(14) + await self._trigger_motion_event(zoneID1, prompt_msg=f"Press enter and immediately start motion activity in zone {zoneID1} and stop any motion after {initDuration} seconds of pressing enter.") + + event_data = event_callback.wait_for_event_report(pvcluster.Events.PushTransportBegin, timeout_sec=5) + logger.info(f"Event data {event_data}") + asserts.assert_equal(event_data.connectionID, aConnectionID, "Unexpected value for ConnectionID returned") + + await asyncio.to_thread(time.sleep, initDuration + 1) + + event_data = event_callback.wait_for_event_report(pvcluster.Events.PushTransportEnd, timeout_sec=5) + logger.info(f"Event data {event_data}") + asserts.assert_equal(event_data.connectionID, aConnectionID, "Unexpected value for ConnectionID returned") + + self.step(15) + # Recording stopped and now waiting for blind period to finish + await asyncio.to_thread(time.sleep, blindDuration + 1) + # Previous recording stops and also waited for blind period before triggering another motion event -> Recording starts + await self._trigger_motion_event(zoneID1, prompt_msg=f"Press enter and immediately start motion activity in zone {zoneID1} and stop any motion after {initDuration} seconds of pressing enter.") + event_data = event_callback.wait_for_event_report(pvcluster.Events.PushTransportBegin, timeout_sec=5) + logger.info(f"Event data {event_data}") + asserts.assert_equal(event_data.connectionID, aConnectionID, "Unexpected value for ConnectionID returned") + + await asyncio.to_thread(time.sleep, initDuration + maxPreRollLen + 1) + + event_data = event_callback.wait_for_event_report(pvcluster.Events.PushTransportEnd, timeout_sec=5) + logger.info(f"Event data {event_data}") + asserts.assert_equal(event_data.connectionID, aConnectionID, "Unexpected value for ConnectionID returned") + await asyncio.to_thread(time.sleep, blindDuration + 1) + + # Max Duration + # Deallocating all active connection -> Allocate one pushav with time control such that max duration is tested + self.step(16) + await self.ensure_session_active() + cmd = pvcluster.Commands.DeallocatePushTransport( + connectionID=aConnectionID + ) + status = await self.psvt_deallocate_push_transport(cmd) + asserts.assert_true( + status == Status.Success, + "DUT responds with SUCCESS status code.") + + status = await self.check_and_delete_all_push_av_transports(endpoint, pvattr) + asserts.assert_equal( + status, Status.Success, "Status must be SUCCESS!" + ) + + self.step(17) + # update maxDuration and augDuration fields to ensure initDuration + augDuration > maxDuration + maxDuration = 10 + augDuration = 15 + try: + zoneList = [{"zone": zoneID1, "sensitivity": 4}] + triggerOptions = {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kMotion, + "maxPreRollLen": 4000, + "motionZones": zoneList, + "motionTimeControl": {"initialDuration": initDuration, "augmentationDuration": augDuration, "maxDuration": maxDuration, "blindDuration": blindDuration}} + status = await self.allocate_one_pushav_transport(endpoint, trigger_Options=triggerOptions, + tlsEndPoint=tlsEndpointId, url=f"https://{host_ip}:1234/streams/{uploadStreamId}/") + asserts.assert_equal(status, Status.Success, + "DUT must responds with Status Code Success.") + except InteractionModelError as e: + asserts.assert_equal(e.clusterStatus, Status.Success, + "DUT must responds with Status Code Success.") + + transportConfigs = await self.read_pavst_attribute_expect_success(endpoint, + pvattr.CurrentConnections, + ) + asserts.assert_greater_equal( + len(transportConfigs), 1, "TransportConfigurations must not be empty!" + ) + aConnectionID2 = transportConfigs[0].connectionID + + cmd = pvcluster.Commands.SetTransportStatus( + connectionID=aConnectionID2, + transportStatus=pvcluster.Enums.TransportStatusEnum.kActive + ) + status = await self.psvt_set_transport_status(cmd) + asserts.assert_true( + status == Status.Success, + "DUT responds with SUCCESS status code.") + + # MAX DURATION Check + # Triggering 2 motion event -> recording starts -> wait for max duration -> recording stops + self.step(18) + event_callback = EventSubscriptionHandler(expected_cluster=pvcluster) + await event_callback.start(self.default_controller, + self.dut_node_id, + self.get_endpoint()) + + await self._trigger_motion_event(zoneID1, prompt_msg=f"Press enter and immediately start motion activity in zone {zoneID1} and stop any motion after {initDuration} seconds of pressing enter.") + event_data = event_callback.wait_for_event_report(pvcluster.Events.PushTransportBegin, timeout_sec=5) + logger.info(f"Event data {event_data}") + asserts.assert_equal(event_data.connectionID, aConnectionID2, "Unexpected value for ConnectionID returned") + + await self._trigger_motion_event(zoneID1, prompt_msg=f"Press enter and immediately start motion activity in zone {zoneID1} and stop any motion after {initDuration} seconds of pressing enter.") + # Second motion trigger during ongoing recording should NOT generate PushTransportBegin, only extend duration + + await asyncio.to_thread(time.sleep, maxDuration + 1) + event_data = event_callback.wait_for_event_report(pvcluster.Events.PushTransportEnd, timeout_sec=5) + logger.info(f"Event data {event_data}") + asserts.assert_equal(event_data.connectionID, aConnectionID2, "Unexpected value for ConnectionID returned") + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_PAVST_2_3.py b/src/python_testing/TC_PAVST_2_3.py index 93353ba9c0a..c99132351b3 100644 --- a/src/python_testing/TC_PAVST_2_3.py +++ b/src/python_testing/TC_PAVST_2_3.py @@ -370,13 +370,13 @@ async def test_TC_PAVST_2_3(self): streamUsage = aStreamUsagePriorities[0] containerOptions = { "containerType": pvcluster.Enums.ContainerFormatEnum.kCmaf, - "CMAFContainerOptions": {"CMAFInterface": pvcluster.Enums.CMAFInterfaceEnum.kInterface1, "chunkDuration": 4, "segmentDuration": 3, + "CMAFContainerOptions": {"CMAFInterface": pvcluster.Enums.CMAFInterfaceEnum.kInterface1, "chunkDuration": 4, "segmentDuration": 4000, "sessionGroup": 3, "trackName": "media"}, } status = await self.send_single_cmd(cmd=pvcluster.Commands.AllocatePushTransport( {"streamUsage": streamUsage, - "TLSEndpointID": endpoint, - "url": "https://{host_ip}:1234/streams/1", + "TLSEndpointID": tlsEndpointId, + "url": f"https://{host_ip}:1234/streams/1/", "triggerOptions": {"triggerType": pvcluster.Enums.TransportTriggerTypeEnum.kContinuous}, "ingestMethod": pvcluster.Enums.IngestMethodsEnum.kCMAFIngest, "containerOptions": containerOptions, diff --git a/src/python_testing/TC_PAVST_2_4.py b/src/python_testing/TC_PAVST_2_4.py index 1c80e7e8a2b..77de02416e6 100644 --- a/src/python_testing/TC_PAVST_2_4.py +++ b/src/python_testing/TC_PAVST_2_4.py @@ -198,6 +198,9 @@ async def test_TC_PAVST_2_4(self): aModifiedTransportOptions = aTransportOptions.expiryTime aModifiedTransportOptions = aModifiedTransportOptions + 120 aTransportOptions.expiryTime = aModifiedTransportOptions + aTransportOptions.videoStreams = [] + aTransportOptions.audioStreams = [] + cmd = pvcluster.Commands.ModifyPushTransport( connectionID=aConnectionID, transportOptions=aTransportOptions, diff --git a/src/python_testing/TC_PAVST_2_6.py b/src/python_testing/TC_PAVST_2_6.py index 1c6e6845e0b..bf4bd35a16d 100644 --- a/src/python_testing/TC_PAVST_2_6.py +++ b/src/python_testing/TC_PAVST_2_6.py @@ -274,6 +274,8 @@ async def test_TC_PAVST_2_6(self): connectionID=Nullable(), transportStatus=Clusters.PushAvStreamTransport.Enums.TransportStatusEnum.kInactive ) + aTransportOptions.videoStreams = [] + aTransportOptions.audioStreams = [] status = await self.psvt_set_transport_status(cmd) asserts.assert_true( status == Status.Success, diff --git a/src/python_testing/TC_SC_3_5.py b/src/python_testing/TC_SC_3_5.py index 9e93fa833c9..dd6e325cc29 100644 --- a/src/python_testing/TC_SC_3_5.py +++ b/src/python_testing/TC_SC_3_5.py @@ -27,19 +27,24 @@ # --PICS src/app/tests/suites/certification/ci-pics-values # === END CI TEST ARGUMENTS === +import asyncio import logging import os import tempfile -from time import sleep from mobly import asserts import matter.clusters as Clusters from matter import ChipDeviceCtrl +from matter.clusters.Types import NullValue from matter.fault_injection import CHIPFaultId from matter.interaction_model import InteractionModelError from matter.testing.apps import AppServerSubprocess -from matter.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from matter.testing.decorators import async_test_body +from matter.testing.matter_testing import MatterBaseTest +from matter.testing.runner import TestStep, default_matter_test_main + +log = logging.getLogger(__name__) class TC_SC_3_5(MatterBaseTest): @@ -49,6 +54,10 @@ def setup_class(self): self.th_server = None self.storage = None + # We assume that DUT_Commissioner has ICAC in its NOC Chain unless determined otherwise in step 1c. + # When running in CI, we also want this to be True to avoid skipping steps. + self.dut_has_icac = True + self.th_client = self.default_controller self.th_server_local_nodeid = 1111 self.th_server_discriminator = 1234 @@ -75,59 +84,72 @@ def desc_TC_SC_3_5(self) -> str: return "[TC-SC-3.5] CASE Error Handling [DUT_Initiator] " def pics_TC_SC_3_5(self) -> list[str]: - pics = [ + return [ "MCORE.ROLE.COMMISSIONER", ] - return pics def steps_TC_SC_3_5(self) -> list[TestStep]: - steps = [ + return [ TestStep("precondition", "TH_SERVER has been commissioned to TH_CLIENT", is_commissioning=True), - TestStep("1a", "TH Client sends an OpenCommissioningWindow command to TH_SERVER to allow it to be commissioned by DUT_Initiator and trigger CASE Handshake", + TestStep("1a", "TH Client sends an OpenCommissioningWindow command to TH_SERVER to allow it to be commissioned by DUT_Commissioner to determine if the DUT_Commissioner has an ICAC in its NOC Chain", + "Verify that the TH_SERVER returns SUCCESS"), + + TestStep("1b", "TH prompts the user to Commission DUT_Commissioner to TH_SERVER", + "Verify that the DUT commissioned TH_SERVER successfully"), + + TestStep("1c", "TH Client Reads the NOCs attribute on TH_SERVER and checks if DUT_Commissioner has ICAC in its NOC Chain", + "Verify that NOCs attribute returns two NOCStructs and determine if DUT_Commissioner has ICAC"), + + TestStep("1d", "TH Client removes the DUT_Commissioner's fabric from TH_SERVER", + "Verify that the DUT_Commissioner's fabric is removed from TH_SERVER"), + + TestStep("2a", "TH Client sends an OpenCommissioningWindow command to TH_SERVER to allow it to be commissioned by DUT_Commissioner and trigger CASE Handshake", "Verify that the TH_SERVER returns SUCCESS"), - TestStep("1b", "TH Client sends FailAtFault command to FaultInjection cluster on TH_SERVER to include a corrupt TBEData2Encrypted in the Sigma2 it will send during CASE Handshake", + TestStep("2b", "TH Client sends FailAtFault command to FaultInjection cluster on TH_SERVER to include a corrupt TBEData2Encrypted in the Sigma2 it will send during CASE Handshake", "Verify that the TH_SERVER receives the message"), - TestStep("1c", "TH prompts the user to Commission DUT_Initiator to TH_SERVER", - "Verify that the DUT sends a status report to TH_SERVER with a FAILURE general code (value 1), protocol ID of SECURE_CHANNEL (0x0000), and Protocol code of INVALID_PARAMETER (0X0002)."), + TestStep("2c", "TH prompts the user to Commission DUT_Commissioner to TH_SERVER", + "Verify that the DUT sends a status report to TH_SERVER with a FAILURE general code (value 1), protocol ID of SECURE_CHANNEL (0x0000), and Protocol code of INVALID_PARAMETER (0X0002). Verify that the commissioning failed by checking that the commissioning window is still open on TH_SERVER."), - TestStep("2a", "TH Client revokes the Commissioning Window and resends an OpenCommissioningWindow command to TH_SERVER to allow commissioning by DUT_Initiator again and re-trigger the CASE handshake.", + TestStep("3a", "TH Client revokes the Commissioning Window and resends an OpenCommissioningWindow command to TH_SERVER to allow commissioning by DUT_Commissioner again and re-trigger the CASE handshake.", "Verify that the TH_SERVER returns SUCCESS"), - TestStep("2b", "TH Client sends FailAtFault command to FaultInjection cluster on TH_SERVER to include a corrupt responderNOC in the Sigma2 it will send during CASE Handshake", + TestStep("3b", "TH Client sends FailAtFault command to FaultInjection cluster on TH_SERVER to include a corrupt responderNOC in the Sigma2 it will send during CASE Handshake", "Verify that the TH_SERVER receives the message"), - TestStep("2c", "TH prompts the user to Commission DUT_Initiator to TH_SERVER again", - "Verify that the DUT sends a status report to TH_SERVER with a FAILURE general code (value 1), protocol ID of SECURE_CHANNEL (0x0000), and Protocol code of INVALID_PARAMETER (0X0002)."), + TestStep("3c", "TH prompts the user to Commission DUT_Commissioner to TH_SERVER again", + "Verify that the DUT sends a status report to TH_SERVER with a FAILURE general code (value 1), protocol ID of SECURE_CHANNEL (0x0000), and Protocol code of INVALID_PARAMETER (0X0002). Verify that the commissioning failed by checking that the commissioning window is still open on TH_SERVER."), - TestStep("3a", "TH Client revokes the Commissioning Window and resends an OpenCommissioningWindow command to TH_SERVER to allow commissioning by DUT_Initiator again and re-trigger the CASE handshake.", + TestStep("4a", "TH Client revokes the Commissioning Window and resends an OpenCommissioningWindow command to TH_SERVER to allow commissioning by DUT_Commissioner again and re-trigger the CASE handshake." + " This Test Step is skipped if DUT_Commissioner does not have ICAC in its NOC Chain", "Verify that the TH_SERVER returns SUCCESS"), - TestStep("3b", "TH Client sends FailAtFault command to FaultInjection cluster on TH_SERVER to include a corrupt responderICAC in the Sigma2 it will send during CASE Handshake", + TestStep("4b", "TH Client sends FailAtFault command to FaultInjection cluster on TH_SERVER to include a corrupt responderICAC in the Sigma2 it will send during CASE Handshake." + " This Test Step is skipped if DUT_Commissioner does not have ICAC in its NOC Chain", "Verify that the TH_SERVER receives the message"), - TestStep("3c", "TH prompts the user to Commission DUT_Initiator to TH_SERVER again", - "Verify that the DUT sends a status report to TH_SERVER with a FAILURE general code (value 1), protocol ID of SECURE_CHANNEL (0x0000), and Protocol code of INVALID_PARAMETER (0X0002)."), + TestStep("4c", "TH prompts the user to Commission DUT_Commissioner to TH_SERVER again." + " This Test Step is skipped if DUT_Commissioner does not have ICAC in its NOC Chain", + "Verify that the DUT sends a status report to TH_SERVER with a FAILURE general code (value 1), protocol ID of SECURE_CHANNEL (0x0000), and Protocol code of INVALID_PARAMETER (0X0002). Verify that the commissioning failed by checking that the commissioning window is still open on TH_SERVER."), - TestStep("4a", "TH Client revokes the Commissioning Window and resends an OpenCommissioningWindow command to TH_SERVER to allow commissioning by DUT_Initiator again and re-trigger the CASE handshake.", + TestStep("5a", "TH Client revokes the Commissioning Window and resends an OpenCommissioningWindow command to TH_SERVER to allow commissioning by DUT_Commissioner again and re-trigger the CASE handshake.", "Verify that the TH_SERVER returns SUCCESS"), - TestStep("4b", "TH Client sends FailAtFault command to FaultInjection cluster on TH_SERVER to include a corrupt Signature in the Sigma2 it will send during CASE Handshake", + TestStep("5b", "TH Client sends FailAtFault command to FaultInjection cluster on TH_SERVER to include a corrupt Signature in the Sigma2 it will send during CASE Handshake", "Verify that the TH_SERVER receives the message"), - TestStep("4c", "TH prompts the user to Commission DUT_Initiator to TH_SERVER again", - "Verify that the DUT sends a status report to TH_SERVER with a FAILURE general code (value 1), protocol ID of SECURE_CHANNEL (0x0000), and Protocol code of INVALID_PARAMETER (0X0002)."), + TestStep("5c", "TH prompts the user to Commission DUT_Commissioner to TH_SERVER again", + "Verify that the DUT sends a status report to TH_SERVER with a FAILURE general code (value 1), protocol ID of SECURE_CHANNEL (0x0000), and Protocol code of INVALID_PARAMETER (0X0002). Verify that the commissioning failed by checking that the commissioning window is still open on TH_SERVER."), ] - return steps def start_th_server(self): @@ -138,7 +160,7 @@ def start_th_server(self): # Create a temporary storage directory for keeping KVS files. self.storage = tempfile.TemporaryDirectory(prefix=self.__class__.__name__) - logging.info("Temporary storage directory: %s", self.storage.name) + log.info("Temporary storage directory: %s", self.storage.name) self.th_server = AppServerSubprocess( self.th_server_app, @@ -157,17 +179,29 @@ async def open_commissioning_window(self): params = await self.th_client.OpenCommissioningWindow( nodeId=self.th_server_local_nodeid, timeout=3*60, iteration=10000, discriminator=self.th_server_discriminator, option=1) new_random_passcode = params.setupPinCode - sleep(1) - logging.info("OpenCommissioningWindow complete") + await asyncio.sleep(1) + log.info("OpenCommissioningWindow complete") return new_random_passcode - async def reopen_commissioning_window(self): - ''' Before reopening Commissioning Window, we need to instruct TH_Server to revoke any active OpenCommissioningWindows ''' + async def revoke_and_open_commissioning_window(self): + ''' Before reopening Commissioning Window, we need to instruct TH_SERVER to revoke any active OpenCommissioningWindows.''' - revokeCmd = Clusters.AdministratorCommissioning.Commands.RevokeCommissioning() - await self.th_client.SendCommand(nodeId=self.th_server_local_nodeid, endpoint=0, payload=revokeCmd, timedRequestTimeoutMs=9000) - sleep(1) + try: + revokeCmd = Clusters.AdministratorCommissioning.Commands.RevokeCommissioning() + await self.th_client.SendCommand(nodeId=self.th_server_local_nodeid, endpoint=0, payload=revokeCmd, timedRequestTimeoutMs=9000) + except InteractionModelError as e: + # If the window is already closed, we just go ahead with opening the commissioning window + if e.status == Clusters.AdministratorCommissioning.Enums.StatusCode.kWindowNotOpen: + pass + else: + log.exception('Error running RevokeCommissioning command: %s', e) + asserts.fail(f"RevokeCommissioning failed with error: {e.status}") + except Exception as e: + log.exception('Error running RevokeCommissioning command: %s', e) + asserts.fail(f"RevokeCommissioning failed with error: {str(e)}") + + await asyncio.sleep(1) return await self.open_commissioning_window() @@ -190,54 +224,108 @@ async def send_fault_injection_command(self, faultID: CHIPFaultId): except InteractionModelError: asserts.fail("Fault Injection Command Failed, is the TH_SERVER app built with the FaultInjection Cluster?") + async def assert_dut_commissioner_failed_to_complete_commissioning(self): + '''Helper to assert that DUT_Commissioner failed to commission TH_SERVER; We do this by checking that the commissioning window is still open. + NOTE: This method should only be called when testing CASE Error failure AND after TH_Client has opened commissioning window for DUT_Commissioner. + ''' + + AC_cluster = Clusters.AdministratorCommissioning + window_status = await self.read_single_attribute_check_success( + dev_ctrl=self.th_client, + node_id=self.th_server_local_nodeid, + fabric_filtered=False, + endpoint=0, + cluster=AC_cluster, + attribute=AC_cluster.Attributes.WindowStatus + ) + + asserts.assert_not_equal(window_status, AC_cluster.Enums.CommissioningWindowStatusEnum.kWindowNotOpen, + "Commissioning window is expected to be open, but was found to be closed. This indicates that DUT_Commissioner completed commissioning successfully, which is not expected in this test step") + @async_test_body async def test_TC_SC_3_5(self): self.step("precondition") await self.th_client.CommissionOnNetwork(nodeId=self.th_server_local_nodeid, setupPinCode=self.th_server_passcode, filterType=ChipDeviceCtrl.DiscoveryFilterType.LONG_DISCRIMINATOR, filter=self.th_server_discriminator) - logging.info("Commissioning TH_SERVER complete") + log.info("Commissioning TH_SERVER complete") - self.step("1a") - th_server_passcode = await self.open_commissioning_window() - - self.step("1b") - await self.send_fault_injection_command(CHIPFaultId.CASECorruptTBEData2Encrypted) - - self.step("1c") - prompt_msg = ( - "\nPlease commission the TH server app from DUT:\n" - f" pairing onnetwork 1 {th_server_passcode}\n" - "Input 'Y' if commissioner DUT fails commissioning AND TH Server Logs display CHIP ERROR = 0x00000054 (INVALID CASE PARAMETER) equivalent to Status Report with protocol code 2 \n" - "Input 'N' if commissioner DUT commissions successfully \n " - "Or failure in TH Server Logs IS NOT = 'INVALID CASE PARAMETER'\n" - ) + # ------------------------------------------- Determine if DUT Commissioner has ICAC in its NOC Chain--------------------------------------------- if self.is_pics_sdk_ci_only: - resp = 'Y' + log.info("Skip steps 1a-1d since we are running in CI and there is no DUT Commissioner in CI to check for its ICAC") + self.skip_step("1a") + self.skip_step("1b") + self.skip_step("1c") + self.skip_step("1d") + else: + self.step("1a") + th_server_passcode = await self.open_commissioning_window() + + self.step("1b") + prompt_msg = ( + "\nPlease commission the TH_SERVER app from DUT:\n" + f" pairing onnetwork 1 {th_server_passcode}\n" + "Input 'Y' if commissioner DUT commissions TH server app successfully \n" + "Input 'N' if commissioner DUT fails commissioning \n " + ) + resp = self.wait_for_user_input(prompt_msg) - expected_error_found = resp.lower() == 'y' + commissioning_success = resp.lower() == 'y' - # Verify results - asserts.assert_equal( - expected_error_found, - True, - f"Expected Error in TH_SERVER logs is {'found' if expected_error_found else 'not found'}" - ) + # Verify that DUT commissioned TH_SERVER successfully + asserts.assert_true( + commissioning_success, + "Expected DUT_Commissioner to commission TH_SERVER app successfully" + ) + + self.step("1c") + nocStructs = await self.read_single_attribute_check_success(dev_ctrl=self.th_client, + node_id=self.th_server_local_nodeid, + cluster=Clusters.OperationalCredentials, + attribute=Clusters.OperationalCredentials.Attributes.NOCs, + fabric_filtered=False) + + asserts.assert_equal(len(nocStructs), 2, + f"Expected 2 NOCStructs (1 for TH Client, 1 for DUT Commissioner), got {len(nocStructs)}") + + dut_commissioner_noc_struct = next((noc for noc in nocStructs if noc.fabricIndex != self.th_client.fabricId), None) + + asserts.assert_is_not_none( + dut_commissioner_noc_struct, + "Could not find a NOCStruct for DUT Commissioner. Please ensure that DUT Commissioner commissioned TH Server successfully." + ) - '''------------------------------------------- Inject Fault into Sigma2 responderNOC--------------------------------------------- ''' + dut_commissioner_icac = dut_commissioner_noc_struct.icac + dut_commissioner_fabric_index = dut_commissioner_noc_struct.fabricIndex + # Determine if DUT_Commissioner has ICAC in its NOC Chain + if dut_commissioner_icac == NullValue: + log.info("DUT_Commissioner does not have ICAC in its NOC Chain") + self.dut_has_icac = False + else: + log.info("DUT_Commissioner has ICAC in its NOC Chain") + self.dut_has_icac = True + + # Remove DUT_Commissioner's fabric from TH_SERVER to prepare for commissioning DUT_Commissioner in next step + self.step("1d") + + cmd = Clusters.OperationalCredentials.Commands.RemoveFabric(fabricIndex=dut_commissioner_fabric_index) + resp = await self.send_single_cmd(dev_ctrl=self.th_client, node_id=self.th_server_local_nodeid, cmd=cmd) + asserts.assert_equal( + resp.statusCode, Clusters.OperationalCredentials.Enums.NodeOperationalCertStatusEnum.kOk) + + # ------------------------------------------- Inject Fault into Sigma2 TBEData2Encrypted--------------------------------------------- self.step("2a") - th_server_passcode = await self.reopen_commissioning_window() + th_server_passcode = await self.open_commissioning_window() self.step("2b") - await self.send_fault_injection_command(CHIPFaultId.CASECorruptSigma2NOC) + await self.send_fault_injection_command(CHIPFaultId.CASECorruptTBEData2Encrypted) self.step("2c") prompt_msg = ( - "\nPlease commission the TH server app from DUT:\n" - "\nWARNING: Make sure that the Commissioner restarts commissioning from scratch, such as by changing NodeID or by restarting the commissioner\n" + "\nPlease commission the TH_SERVER app from DUT:\n" f" pairing onnetwork 2 {th_server_passcode}\n" "Input 'Y' if commissioner DUT fails commissioning AND TH Server Logs display CHIP ERROR = 0x00000054 (INVALID CASE PARAMETER) equivalent to Status Report with protocol code 2 \n" "Input 'N' if commissioner DUT commissions successfully \n " @@ -258,17 +346,19 @@ async def test_TC_SC_3_5(self): f"Expected Error in TH_SERVER logs is {'found' if expected_error_found else 'not found'}" ) - '''------------------------------------------- Inject Fault into Sigma2 responderICAC--------------------------------------------- ''' + await self.assert_dut_commissioner_failed_to_complete_commissioning() + + # ------------------------------------------- Inject Fault into Sigma2 responderNOC--------------------------------------------- self.step("3a") - th_server_passcode = await self.reopen_commissioning_window() + th_server_passcode = await self.revoke_and_open_commissioning_window() self.step("3b") - await self.send_fault_injection_command(CHIPFaultId.CASECorruptSigma2ICAC) + await self.send_fault_injection_command(CHIPFaultId.CASECorruptSigma2NOC) self.step("3c") prompt_msg = ( - "\nPlease commission the TH server app from DUT:\n" + "\nPlease commission the TH_SERVER app from DUT:\n" "\nWARNING: Make sure that the Commissioner restarts commissioning from scratch, such as by changing NodeID or by restarting the commissioner\n" f" pairing onnetwork 3 {th_server_passcode}\n" "Input 'Y' if commissioner DUT fails commissioning AND TH Server Logs display CHIP ERROR = 0x00000054 (INVALID CASE PARAMETER) equivalent to Status Report with protocol code 2 \n" @@ -290,25 +380,65 @@ async def test_TC_SC_3_5(self): f"Expected Error in TH_SERVER logs is {'found' if expected_error_found else 'not found'}" ) - '''------------------------------------------- Inject Fault into Sigma2 Signature--------------------------------------------- ''' + await self.assert_dut_commissioner_failed_to_complete_commissioning() + + # ------------------------------------------- Inject Fault into Sigma2 responderICAC--------------------------------------------- + + if not self.dut_has_icac: + log.info("DUT_Commissioner does not have ICAC in its NOC Chain, skipping ICAC Fault Injection testcase") + self.skip_step("4a") + self.skip_step("4b") + self.skip_step("4c") + else: + self.step("4a") + th_server_passcode = await self.revoke_and_open_commissioning_window() + + self.step("4b") + await self.send_fault_injection_command(CHIPFaultId.CASECorruptSigma2ICAC) + + self.step("4c") + prompt_msg = ( + "\nPlease commission the TH_SERVER app from DUT:\n" + "\nWARNING: Make sure that the Commissioner restarts commissioning from scratch, such as by changing NodeID or by restarting the commissioner\n" + f" pairing onnetwork 4 {th_server_passcode}\n" + "Input 'Y' if commissioner DUT fails commissioning AND TH Server Logs display CHIP ERROR = 0x00000054 (INVALID CASE PARAMETER) equivalent to Status Report with protocol code 2 \n" + "Input 'N' if commissioner DUT commissions successfully \n " + "Or failure in TH Server Logs IS NOT = 'INVALID CASE PARAMETER'\n" + ) + + if self.is_pics_sdk_ci_only: + resp = 'Y' + else: + resp = self.wait_for_user_input(prompt_msg) - self.step("4a") - th_server_passcode = await self.reopen_commissioning_window() + expected_error_found = resp.lower() == 'y' - self.step("4b") + # Verify results + asserts.assert_equal( + expected_error_found, + True, + f"Expected Error in TH_SERVER logs is {'found' if expected_error_found else 'not found'}" + ) + + await self.assert_dut_commissioner_failed_to_complete_commissioning() + + # ------------------------------------------- Inject Fault into Sigma2 Signature--------------------------------------------- + + self.step("5a") + th_server_passcode = await self.revoke_and_open_commissioning_window() + + self.step("5b") await self.send_fault_injection_command(CHIPFaultId.CASECorruptSigma2Signature) - self.step("4c") + self.step("5c") prompt_msg = ( - "\nPlease commission the TH server app from DUT:\n" + "\nPlease commission the TH_SERVER app from DUT:\n" "\nWARNING: Make sure that the Commissioner restarts commissioning from scratch, such as by changing NodeID or by restarting the commissioner\n" - f" pairing onnetwork 4 {th_server_passcode}\n" + f" pairing onnetwork 5 {th_server_passcode}\n" "Input 'Y' if commissioner DUT fails commissioning AND TH Server Logs display CHIP ERROR = 0x00000054 (INVALID CASE PARAMETER) equivalent to Status Report with protocol code 2 \n" "Input 'N' if commissioner DUT commissions successfully \n " "Or failure in TH Server Logs IS NOT = 'INVALID CASE PARAMETER'\n" ) - - print(f"self.is_pics_sdk_ci_only = {self.is_pics_sdk_ci_only}") if self.is_pics_sdk_ci_only: resp = 'Y' else: @@ -323,6 +453,8 @@ async def test_TC_SC_3_5(self): f"Expected Error in TH_SERVER logs is {'found' if expected_error_found else 'not found'}" ) + await self.assert_dut_commissioner_failed_to_complete_commissioning() + if __name__ == "__main__": default_matter_test_main() diff --git a/src/python_testing/TC_SC_4_1.py b/src/python_testing/TC_SC_4_1.py new file mode 100644 index 00000000000..3f17775a1e1 --- /dev/null +++ b/src/python_testing/TC_SC_4_1.py @@ -0,0 +1,884 @@ +# +# Copyright (c) 2025-2026 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. +# + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# factory-reset: true +# quiet: true +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --manual-code 10054912339 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# run2: +# app: ${ALL_CLUSTERS_APP} +# factory-reset: true +# quiet: true +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --qr-code MT:-24J0KQS02-10648G00 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# run3: +# app: ${LIT_ICD_APP} +# factory-reset: true +# quiet: true +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --qr-code MT:-24J0KQS02-10648G00 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# === END CI TEST ARGUMENTS === + +import asyncio +import enum +import logging +from typing import Optional + +from mdns_discovery.mdns_discovery import MdnsDiscovery, MdnsServiceType +from mdns_discovery.utils.asserts import (assert_is_commissionable_type, assert_valid_cm_key, + assert_valid_commissionable_instance_name, assert_valid_d_key, + assert_valid_devtype_subtype, assert_valid_dn_key, assert_valid_dt_key, + assert_valid_hostname, assert_valid_icd_key, assert_valid_ipv6_addresses, + assert_valid_long_discriminator_subtype, assert_valid_ph_key, + assert_valid_ph_pi_relationship, assert_valid_pi_key, assert_valid_ri_key, + assert_valid_sai_key, assert_valid_sat_key, assert_valid_short_discriminator_subtype, + assert_valid_sii_key, assert_valid_t_key, assert_valid_vendor_subtype, + assert_valid_vp_key) +from mdns_discovery.utils.network import is_dut_tcp_supported +from mobly import asserts + +import matter.clusters as Clusters +from matter.testing.commissioning import get_setup_payload_info_config +from matter.testing.decorators import async_test_body +from matter.testing.matter_testing import MatterBaseTest +from matter.testing.runner import TestStep, default_matter_test_main + +log = logging.getLogger(__name__) + +''' +Purpose +The purpose of this test case is to verify that a device is able to +correctly advertise Commissionable Node Discovery service. + +Test Plan +https://github.com/CHIP-Specifications/chip-test-plans/blob/master/src/securechannel.adoc#341-tc-sc-41-commissionable-node-discovery-dut_commissionee +''' + +TCP_PICS_STR = "MCORE.SC.TCP" +ROOT_NODE_ENDPOINT_ID = 0 + + +class SetupCodeType(enum.IntEnum): + MANUAL_CODE = 0 + QR_CODE = 1 + NONE_SUPLIED = 2 + + +class TC_SC_4_1(MatterBaseTest): + + def steps_TC_SC_4_1(self): + return [ + # DUT DETAILS + # + TestStep(1, "DUT is commissioned.", is_commissioning=True), + + TestStep(2, """Check if the ICD Management cluster is present""", + """TH reads from the DUT the ServerList attribute from the Descriptor cluster on EP0 + - Set supports_icd to True if present, otherwise, to False + - If supports_icd is True + - TH reads ActiveModeThreshold from the ICD Management cluster on EP0 and saves as active_mode_threshold_ms"""), + + TestStep(3, """Check if the LITS (Long Idle Time Support) feature is supported""", + """If supports_icd is True: + - TH checks for support of the LITS feature by reading from the DUT the FeatureMap attribute from the ICD Management cluster on EP0 + - Set supports_lit to True if supported, otherwise, to False"""), + + TestStep(4, """Check if the DUT supports TCP""", + """Set supports_tcp_dut to True if supported, otherwise, to False"""), + + TestStep(5, """Check if TCP is supported per PICS""", + """Set supports_tcp_pics to True if supported, otherwise, to False"""), + + TestStep(6, """Check the setup code type used during commissioning (QR or Manual)""", + """Save as setup_code_type"""), + + TestStep(7, """Check if the Open Basic Commissioning Window command is supported""", + """Set supports_obcw to True if supported, otherwise, to False"""), + + # OPEN BASIC COMMISSIONING WINDOW + # + TestStep(8, """DUT is put in Commissioning Mode using the Open Basic Commissioning Window command if supported (supports_obcw)""", + """DUT starts advertising Commissionable Node Discovery service through DNS-SD"""), + + TestStep(9, """TH gets the discriminator from the DUT and constructs the Discriminator subtype (Long or Short) based on the setup code type (QR or Manual)""", + """If setup code type is QR, construct the 'Long Discriminator Subtype' + - Verify that the discriminator value is a valid 12-bit variable length decimal number in ASCII text, omitting any leading zeros + If setup code type is Manual, construct the 'Short Discriminator Subtype' + - Verify that the discriminator value is a valid 4-bit variable length decimal number in ASCII text, omitting any leading zeros + Save as 'discriminator_subtype'."""), + + TestStep(10, """Get the Discriminator Subtype (Long or Short from the previous step) PTR record's instance name""", + """TH performs a PTR record query against the Discriminator Subtype (Long or Short from the previous step) + - Verify that there is one, and only one, 'Discriminator Subtype' PTR record + - Save the 'Discriminator Subtype' PTR record's instance name as 'discriminator_subtype_ptr_instance_name'"""), + + TestStep(11, """Verify commissionable subtype advertisements""", + """See the 'Commissionable Subtypes Verifications' table in the Notes/Testing considerations + section of the Test Plan for the list of verifications to be performed"""), + + TestStep(12, """Verify SRV record advertisements""", + """See the 'SRV Record Verifications' table in the Notes/Testing considerations + section of the Test Plan for the list of verifications to be performed"""), + + TestStep(13, """Verify TXT record advertisements""", + """See the 'TXT Record Verifications' table in the Notes/Testing considerations + section of the Test Plan for the list of verifications to be performed. Expected CM TXT key value = 1"""), + + TestStep(14, """Verify AAAA records""", + """See the 'AAAA Record Verifications' table in the Notes/Testing considerations + section of the Test Plan for the list of verifications to be performed"""), + + TestStep(15, """Close commissioning window""", + """DUT stops advertising Commissionable Node Discovery services"""), + + # OPEN COMISSIONING WINDOW + # + TestStep(16, """TH gets the Long Discriminator from the DUT and constructs the Long Discriminator Subtype""", + """Verify that the Long discriminator value is a valid 12-bit variable length decimal number in ASCII text, + omitting any leading zeros + Save 'Long Discriminator' value as long_discriminator + Save the 'Long Discriminator Subtype' as long_discriminator_subtype"""), + + TestStep(17, """DUT is put in Commissioning Mode using Open Commissioning Window command""", + """DUT starts advertising Commissionable Node Discovery service through DNS-SD"""), + + TestStep(18, """Get the 'Long Discriminator Subtype' PTR record's instance name""", + """TH performs a PTR record query against the 'Long Discriminator Subtype' + - Verify that there is one, and only one, 'Long Discriminator Subtype' PTR record + - Save the 'Long Discriminator Subtype' PTR record's instance name as long_discriminator_subtype_ptr_instance_name"""), + + TestStep(19, """Verify commissionable subtype advertisements""", + """See the 'Commissionable Subtypes Verifications' table in the Notes/Testing considerations + section of the Test Plan for the list of verifications to be performed"""), + + TestStep(20, """Verify SRV record advertisements""", + """See the 'SRV Record Verifications' table in the Notes/Testing considerations + section of the Test Plan for the list of verifications to be performed"""), + + TestStep(21, """Verify TXT record advertisements""", + """See the 'TXT Record Verifications' table in the Notes/Testing considerations + section of the Test Plan for the list of verifications to be performed. Expected CM TXT key value = 2"""), + + TestStep(22, """Verify AAAA records""", + """See the 'AAAA Record Verifications' table in the Notes/Testing considerations + section of the Test Plan for the list of verifications to be performed"""), + + TestStep(23, """Close commissioning window""", + """DUT stops advertising Commissionable Node Discovery services"""), + + # EXTENDED DISCOVERY MODE + # + TestStep(24, """Check if DUT Extended Discovery mode is active""", + """Get the 'Long Discriminator Subtype' PTR record's instance name + - If the DUT's 'Long Discriminator Subtype' PTR record's instance name is present, + Extended Discovery mode is active, if so, save the 'Long Discriminator Subtype' + PTR record's instance name as 'long_discriminator_subtype_ptr_instance_name'"""), + + TestStep(25, """Verify commissionable subtype advertisements""", + """See the 'Commissionable Subtypes Verifications' table in the Notes/Testing considerations + section of the Test Plan for the list of verifications to be performed"""), + + TestStep(26, """Verify SRV record advertisements""", + """See the 'SRV Record Verifications' table in the Notes/Testing considerations + section of the Test Plan for the list of verifications to be performed"""), + + TestStep(27, """Verify TXT record advertisements""", + """See the 'TXT Record Verifications' table in the Notes/Testing considerations + section of the Test Plan for the list of verifications to be performed. Expected + CM TXT key value = 0 or omitted key"""), + + TestStep(28, """Verify AAAA records""", + """See the 'AAAA Record Verifications' table in the Notes/Testing considerations + section of the Test Plan for the list of verifications to be performed"""), + ] + + async def get_descriptor_server_list(self): + return await self.read_single_attribute_check_success( + endpoint=ROOT_NODE_ENDPOINT_ID, + dev_ctrl=self.default_controller, + cluster=Clusters.Descriptor, + attribute=Clusters.Descriptor.Attributes.ServerList + ) + + async def get_active_mode_threshold_ms(self): + return await self.read_single_attribute_check_success( + endpoint=ROOT_NODE_ENDPOINT_ID, + dev_ctrl=self.default_controller, + cluster=Clusters.IcdManagement, + attribute=Clusters.IcdManagement.Attributes.ActiveModeThreshold + ) + + async def get_icd_feature_map(self): + return await self.read_single_attribute_check_success( + endpoint=ROOT_NODE_ENDPOINT_ID, + dev_ctrl=self.default_controller, + cluster=Clusters.IcdManagement, + attribute=Clusters.IcdManagement.Attributes.FeatureMap + ) + + def get_dut_instance_name(self, log_result: bool = False) -> str: + node_id = self.dut_node_id + compressed_fabric_id = self.default_controller.GetCompressedFabricId() + instance_name = f'{compressed_fabric_id:016X}-{node_id:016X}' + if log_result: + log.info(f"\n\n\tDUT Instance Name: {instance_name}\n") + return instance_name + + def get_discriminator_subtype(self, is_obcw: bool = False) -> Optional[tuple[str, str]]: + # TH constructs the Discriminator Subtype using the DUT's Long or Short Discriminator + discriminator: str | None = None + discriminator_subtype: str | None = None + setup_payload_info = get_setup_payload_info_config(self.matter_test_config) + + if setup_payload_info: + discriminator = setup_payload_info[0].filter_value + if not is_obcw or self.setup_code_type == SetupCodeType.QR_CODE: + discriminator_subtype = f"_L{discriminator}._sub.{MdnsServiceType.COMMISSIONABLE.value}" + + # Verify that it contains a valid 12-bit variable length decimal number + # in ASCII text, omitting any leading zeros 'Long Discriminator' value + assert_valid_long_discriminator_subtype(discriminator_subtype) + elif self.setup_code_type == SetupCodeType.MANUAL_CODE: + discriminator_subtype = f"_S{discriminator}._sub.{MdnsServiceType.COMMISSIONABLE.value}" + + # Verify that it contains a valid 4-bit variable length decimal number + # in ASCII text, omitting any leading zeros 'Short Discriminator' value + assert_valid_short_discriminator_subtype(discriminator_subtype) + else: + asserts.fail("Setup Code Type must be either QR code or Manual.") + log.info(f"\n\n\t** discriminator subtype: {discriminator_subtype}\n") + + return discriminator_subtype, discriminator + asserts.fail("Failed to get the discriminator value from the setup payload info.") + + return None + + async def _get_verify_discriminator_subtype_ptr_instance_name(self, discriminator_subtype: str, must_be_present: bool = True) -> Optional[str]: + + # TH performs a PTR record query against the Discriminator Subtype + ptr_records = await MdnsDiscovery().get_ptr_records( + service_types=[discriminator_subtype], + log_output=True + ) + + if must_be_present or ptr_records: + # Verify that there is one, and only one, Discriminator Subtype PTR record + asserts.assert_equal(len(ptr_records), 1, + f"There must only be one Long or Short Discriminator Subtype ({discriminator_subtype}) PTR record, found {len(ptr_records)}.") + + return ptr_records[0].instance_name + + return None + + async def _verify_discriminator_subtype_advertisements(self, subtypes: list[str], discriminator: str, discriminator_subtype: str, discriminator_ptr_instance_name: str, is_long_discriminator: bool) -> None: + # Determine discriminator type (Long or Short) to verify + size_txt = "Long" if is_long_discriminator else "Short" + assert_valid_discriminator_subtype = ( + assert_valid_long_discriminator_subtype if is_long_discriminator else assert_valid_short_discriminator_subtype + ) + + # Verify that the Discriminator subtype is present + asserts.assert_in(discriminator_subtype, subtypes, f"'{size_txt} Discriminator Subtype' must be present.") + + # Verify that it contains a valid 12-bit (Long) or 4 bit (Short) variable + # length decimal number in ASCII text, omitting any leading zeros value + assert_valid_discriminator_subtype(discriminator_subtype) + + # TH performs a PTR record query against the short discriminator subtype + # when the long discriminator is provided, as it can be derived from it. + # This is used to verify that the instance name is the same for both. + # The inverse derivation isn't possible (e.g. short -> long) + if is_long_discriminator: + # Derive the short discriminator subtype from the long discriminator + short_discriminator = (int(discriminator) >> 8) & 0x0F + short_discriminator_subtype = f"_S{short_discriminator}._sub.{MdnsServiceType.COMMISSIONABLE.value}" + + # Performs PTR record query + ptr_records = await MdnsDiscovery().get_ptr_records( + service_types=[short_discriminator_subtype], + log_output=True + ) + + # Verify that there is one, and only one, Short Discriminator subtype PTR record + asserts.assert_equal(len(ptr_records), 1, "There must only be one 'Short Discriminator Subtype' PTR record.") + short_discriminator_ptr = ptr_records[0] + + # Verify that the Short and Long Discriminator Subtype PTR record's instance names are equal + asserts.assert_equal(short_discriminator_ptr.instance_name, discriminator_ptr_instance_name, + "Short and Long Discriminator Subtype PTR record's instance names must be equal.") + + async def _verify_commissionable_subtypes(self, discriminator: str, discriminator_subtype: str, discriminator_ptr_instance_name: str, is_long_discriminator: bool, extended_discovery: bool = False) -> None: + # Construct CM subtype + cm_subtype = f"_CM._sub.{MdnsServiceType.COMMISSIONABLE.value}" + + # TH performs a browse for the rest of the 'Commissionable Service' subtypes + subtypes = await MdnsDiscovery().get_commissionable_subtypes(log_output=True) + + # *** LONG/SHORT DISCRIMINATOR SUBTYPE *** + await self._verify_discriminator_subtype_advertisements(subtypes, discriminator, discriminator_subtype, discriminator_ptr_instance_name, is_long_discriminator) + + # *** IN COMMISSIONING MODE SUBTYPE *** + # Verify the expected presence of the 'In Commissioning Mode Subtype' _CM + if extended_discovery: + # When in Extended Discovery Dode, verify that the _CM subtype is NOT present + asserts.assert_not_in(cm_subtype, subtypes, f"In Commissioning Mode Subtype '{cm_subtype}' must NOT be present.") + else: + # When NOT in Extended Discovery Mode, verify that the _CM subtype is present + asserts.assert_in(cm_subtype, subtypes, f"In Commissioning Mode Subtype '{cm_subtype}' must be present.") + + # TH performs a PTR record query against the 'In Commissioning Mode Subtype' + ptr_records = await MdnsDiscovery().get_ptr_records( + service_types=[cm_subtype], + log_output=True + ) + + # Verify that there is one, and only one, 'In Commissioning Mode Subtype' PTR record + asserts.assert_equal(len(ptr_records), 1, "There must only be one 'In Commissioning Mode Subtype' subtype PTR record.") + cm_ptr = ptr_records[0] + + # Verify that the 'In Commissioning Mode Subtype' PTR record's instance name + # is equal to the Discriminator Subtype PTR record's instance name + asserts.assert_equal(cm_ptr.instance_name, discriminator_ptr_instance_name, + "'In Commissioning Mode Subtype' PTR record's instance name must be equal to the 'Long Discriminator Subtype' PTR record's instance name.") + + # *** VENDOR SUBTYPE *** + # Check for the presence of the 'Vendor Subtype' _V + vendor_subtype = next((s for s in subtypes if s.startswith('_V')), None) + + # If present: + if vendor_subtype: + # Verify that it contains a valid 16-bit variable length decimal + # number in ASCII text, omitting any leading zeros 'Vendor Subtype' value + assert_valid_vendor_subtype(vendor_subtype) + + # TH performs a PTR record query against the 'Vendor Subtype' + ptr_records = await MdnsDiscovery().get_ptr_records( + service_types=[vendor_subtype], + log_output=True + ) + + # If present: + if len(ptr_records) > 0: + # Verify that the 'Vendor Subtype' PTR record's instance name + # is equal to the Discriminator Subtype PTR record's instance name + vendor_subtype_ptr = ptr_records[0] + asserts.assert_equal(vendor_subtype_ptr.instance_name, discriminator_ptr_instance_name, + "'Vendor Subtype' PTR record's instance name must be equal to the 'Long Discriminator Subtype' PTR record's instance name.") + + # *** DEVTYPE SUBTYPE *** + # Check for the presence of the 'Devtype Subtype' _T + devtype_subtype = next((s for s in subtypes if s.startswith('_T')), None) + + # If present: + if devtype_subtype: + # Verify that it contains a valid 32-bit variable length decimal + # number in ASCII text, omitting any leading zeros 'Devtype Subtype' value + assert_valid_devtype_subtype(devtype_subtype) + + # TH performs a PTR record query against the 'Devtype Subtype' + ptr_records = await MdnsDiscovery().get_ptr_records( + service_types=[devtype_subtype], + log_output=True + ) + + # If present: + if len(ptr_records) > 0: + # Verify that the 'Devtype Subtype' PTR record's instance name + # is equal to the Discriminator Subtype PTR record's instance name. + devtype_subtype_ptr = ptr_records[0] + asserts.assert_equal(devtype_subtype_ptr.instance_name, discriminator_ptr_instance_name, + "'Devtype Subtype' PTR record's instance name must be equal to the 'Long Discriminator Subtype' PTR record's instance name.") + + async def _get_verify_srv_record(self, long_discriminator_ptr_instance_name: str) -> str: + # TH performs a 'Commissionable Service' SRV record query + # against 'long_discriminator_subtype_ptr_instance_name' + srv_record = await MdnsDiscovery().get_srv_record( + service_name=f"{long_discriminator_ptr_instance_name}.{MdnsServiceType.COMMISSIONABLE.value}", + service_type=MdnsServiceType.COMMISSIONABLE.value, + log_output=True + ) + + # Verify SRV record is returned + asserts.assert_true(srv_record is not None, "SRV record was not returned") + + # Verify that the SRV record's instance name is equal + # to 'long_discriminator_subtype_ptr_instance_name' + asserts.assert_equal(srv_record.instance_name, long_discriminator_ptr_instance_name, + "SRV record's instance name must be equal to the 'Long Discriminator Subtype' PTR record's instance name.") + + # Verify that the DUT's SRV record's instance name is a 64-bit randomly + # selected ID expressed as a sixteen-char hex string with capital letters + assert_valid_commissionable_instance_name(srv_record.instance_name) + + # Verify that the DUT's SRV record's service type + # is '_matterc._udp' and service domain '.local.' + assert_is_commissionable_type(srv_record.service_type) + + # Verify that the target hostname is derived from the 48bit or 64bit MAC + # address expressed as a twelve or sixteen capital letter hex string + assert_valid_hostname(srv_record.hostname) + + return srv_record.hostname + + async def _verify_txt_record_keys(self, long_discriminator_ptr_instance_name: str, expected_cm: str) -> None: + # TH performs a 'Commissionable Service' TXT record query against 'long_discriminator_subtype_ptr_instance_name' + # The device may omit the TXT record if there are no mandatory TXT keys + txt_record = await MdnsDiscovery().get_txt_record( + service_name=f"{long_discriminator_ptr_instance_name}.{MdnsServiceType.COMMISSIONABLE.value}", + service_type=MdnsServiceType.COMMISSIONABLE.value, + log_output=True + ) + + # Verify that the TXT record is returned and is non-empty + txt_record_returned = (txt_record is not None) and (len(txt_record.txt) > 0) + asserts.assert_true(txt_record_returned, + "TXT record was not returned or contains no values") + + # Verify that the TXT record's instance name is equal to 'long_discriminator_subtype_ptr_instance_name' + asserts.assert_equal(txt_record.instance_name, long_discriminator_ptr_instance_name, + "TXT record's instance name must be equal to the 'Long Discriminator Subtype' PTR record's instance name.") + + # *** ICD KEY *** + icd_key: str | None = None + if self.supports_lit: + # Verify that the 'ICD' key is present and non-empty + asserts.assert_in('ICD', txt_record.txt, "'ICD' key must be present.") + icd_key = txt_record.txt.get('ICD') + asserts.assert_true(icd_key, "'ICD' key is present but has no value.") + + # Verify that the 'ICD' key has the value of 0 or 1 encoded + # as a decimal number in ASCII text ommiting any leading zeros + assert_valid_icd_key(icd_key) + else: + # Verify that the 'ICD' TXT key is NOT present + asserts.assert_not_in('ICD', txt_record.txt, "'ICD' key must NOT be present.") + + # Set sit_mode = True when: + # - supports_icd is True and supports_lit is False. + # - supports_icd is True and supports_lit is True and ICD == '0' + # Set sit_mode = False when: + # - supports_icd is False. + # - supports_icd is True and supports_lit is True and ICD == '1' + sit_mode = self.supports_icd and (not self.supports_lit or icd_key == '0') + log.info(f"\n\n\t** sit_mode: {sit_mode}\n") + + # *** SII KEY *** + if sit_mode: + # Verify that the 'SII' key is present and non-empty if 'sit_mode' is True + asserts.assert_in('SII', txt_record.txt, "'SII' key must be present.") + sii_key = txt_record.txt['SII'] + asserts.assert_true(sii_key, "'SII' key is present but has no value.") + + # Verify that the 'SII' key is an unsigned integer with units of milliseconds + # encoded as a variable length decimal number in ASCII text, omitting any + # leading zeros, and shall not exceed 3600000 + assert_valid_sii_key(sii_key) + + # *** SAI KEY *** + if self.supports_icd: + # Verify that the 'SAI' key is present and non-empty if 'supports_icd' is True + asserts.assert_in('SAI', txt_record.txt, "'SAI' key must be present.") + sai_key = txt_record.txt['SAI'] + asserts.assert_true(sai_key, "'SAI' key is present but has no value.") + + # Verify that the 'SAI' key is an unsigned integer with units of milliseconds + # encoded as a variable length decimal number in ASCII text, omitting any + # leading zeros, and shall not exceed 3600000 + assert_valid_sai_key(sai_key) + + # *** SAT KEY *** + # If the 'SAT' key is present: + if 'SAT' in txt_record.txt: + sat_key = txt_record.txt['SAT'] + + # Verify that it is non-empty + asserts.assert_true(sat_key, "'SAT' key is present but has no value.") + + # Verify that it is an unsigned integer with units of milliseconds encoded as + # a variable length decimal number in ASCII text, omitting any leading zeros, + # and shall be less than or equal to 65535 + assert_valid_sat_key(sat_key) + + # If the 'SAT' key is present and supports_icd is true, verify + # that the value is equal to 'active_mode_threshold_ms' + if self.supports_icd: + asserts.assert_equal(int(sat_key), self.active_mode_threshold_ms, + f"'SAT' key value ({sat_key}) must be equal to 'active_mode_threshold_ms' ({self.active_mode_threshold_ms})") + + # Verify that the 'SAI' key is present if the 'SAT' key is present + asserts.assert_true( + 'SAT' not in txt_record.txt + or 'SAI' in txt_record.txt, + "SAI key must be present if SAT key is present." + ) + + # *** D KEY *** + # Verify that the 'D' key is present and non-empty + asserts.assert_in('D', txt_record.txt, "'D' key must be present.") + d_key = txt_record.txt['D'] + asserts.assert_true(d_key, "'D' key is present but has no value.") + + # Verify that it is a full 12-bit discriminator encoded as a variable length + # decimal number in ASCII text, omitting any leading zeros, and up to 4 digits + assert_valid_d_key(d_key) + + # *** VP KEY *** + # If the VP key is present + if 'VP' in txt_record.txt: + # Verify that it is non-empty + vp_key = txt_record.txt['VP'] + asserts.assert_true(vp_key, "'VP' key is present but has no value.") + + # Verify that it contain at least Vendor ID, and if Product ID + # is present, both values must be separated by a + sign + assert_valid_vp_key(vp_key) + + # *** T KEY *** + t_key_present = 'T' in txt_record.txt + t_key = txt_record.txt.get('T', None) + assert_valid_t_key(t_key, t_key_present, self.supports_tcp_dut, self.supports_tcp_pics, enforce_provisional=False) + + # *** CM KEY *** + # If the 'CM' key is present + # At this point, we've already established if the DUT is + # in Extended Discovery Mode earlier in the code and are + # expecting a 'CM' key value of 0 if the key is present + if 'CM' in txt_record.txt: + # Verify that it is non-empty + cm_key = txt_record.txt['CM'] + asserts.assert_true(cm_key, "'CM' key is present but has no value.") + + # Verify value is a decimal number in ASCII text with allowed values (0, 1, 2, 3) + assert_valid_cm_key(cm_key) + + # Verify that the 'CM' key value is equal to the expected value + asserts.assert_true(cm_key == expected_cm, f"'CM' key must be '{expected_cm}', got '{cm_key}'") + else: + # If the 'CM' key is not present but the expected value was 0, it's + # also a valid scenario where the DUT is in Extended Discovery Mode + valid_extended_discovery_mode = expected_cm == "0" + asserts.assert_true(valid_extended_discovery_mode, + f"When the 'CM' key is not present in the TXT record, the expected 'CM' key value must be '0', got '{expected_cm}'.") + + # *** DT KEY *** + # If the DT key is present + if 'DT' in txt_record.txt: + # Verify that it is non-empty + dt_key = txt_record.txt['DT'] + asserts.assert_true(dt_key, "'DT' key is present but has no value.") + + # Verify that it contains the device type identifier encoded as a + # variable length decimal number in ASCII text without leading zeros + assert_valid_dt_key(dt_key) + + # *** DN KEY *** + # If the DN key is present + if 'DN' in txt_record.txt: + # Verify that it is non-empty + dn_key = txt_record.txt['DN'] + asserts.assert_true(dn_key, "'DN' key is present but has no value.") + + # Verify that it is a valid UTF-8 encoded string of maximum length of 32 bytes + assert_valid_dn_key(dn_key) + + # *** RI KEY *** + # If the RI key is present + if 'RI' in txt_record.txt: + # Verify that it is non-empty + ri_key = txt_record.txt['RI'] + asserts.assert_true(ri_key, "'RI' key is present but has no value.") + + # Verify that it is encoded as an uppercase string with a maximum length of + # 100 chars (each octet encoded as a 2-digit hex number, max 50 octets) + assert_valid_ri_key(ri_key) + + # *** PH KEY *** + # If the PH key is present + if 'PH' in txt_record.txt: + # Verify that it is non-empty + ph_key = txt_record.txt['PH'] + asserts.assert_true(ph_key, "'PH' key is present but has no value.") + + # Verify that it is encoded as a variable-length decimal number in ASCII + # text, omitting any leading zeros, and value different than '0' + assert_valid_ph_key(ph_key) + + # *** PI KEY *** + # If the PI key is present + if 'PI' in txt_record.txt: + # Verify that it is non-empty + pi_key = txt_record.txt['PI'] + asserts.assert_true(pi_key, "'PI' key is present but has no value.") + + # Verify it is encoded as a valid UTF-8 string + # with a maximum length of 128 bytes + assert_valid_pi_key(pi_key) + + # Verify the relationship between PH and PI keys + assert_valid_ph_pi_relationship(txt_record.txt) + + @staticmethod + async def _verify_aaaa_records(srv_hostname: str) -> None: + # TH performs a AAAA record query against the target 'hostname' + # listed in the 'Commissionable Service' SRV record + quada_records = await MdnsDiscovery().get_quada_records(hostname=srv_hostname, log_output=True) + + # Verify that at least 1 AAAA record is returned for each IPv6 a address + asserts.assert_greater(len(quada_records), 0, f"No AAAA addresses were resolved for hostname '{srv_hostname}'") + + # Verify that each AAAA record contains a valid IPv6 address + ipv6_addresses = [f"{r.address}%{r.interface}" for r in quada_records] + assert_valid_ipv6_addresses(ipv6_addresses) + + async def close_commissioning_window(self) -> None: + revoke_cmd = Clusters.AdministratorCommissioning.Commands.RevokeCommissioning() + await self.default_controller.SendCommand(nodeId=self.dut_node_id, + endpoint=0, + payload=revoke_cmd, + timedRequestTimeoutMs=6000) + await asyncio.sleep(1) # Give some time for failsafe cleanup scheduling + + def desc_TC_TC_SC_4_1(self) -> str: + return "[TC-SC-4.1] Commissionable Node Discovery with DUT as Commissionee" + + @async_test_body + async def test_TC_SC_4_1(self): + self.endpoint = self.get_endpoint() + self.supports_icd = False + self.supports_lit = False + self.setup_code_type = None + obcw_cmd = Clusters.AdministratorCommissioning.Commands.OpenBasicCommissioningWindow(180) + + # *** STEP 1 *** + # DUT is Commissioned. + self.step(1) + + # *** STEP 2 *** + # Check if the ICD Management cluster is present + self.step(2) + ep0_servers = await self.get_descriptor_server_list() + + # Check if ep0_servers contain the ICD Management cluster ID (0x0046) + self.supports_icd = Clusters.IcdManagement.id in ep0_servers + log.info(f"\n\n\t** supports_icd: {self.supports_icd}\n") + + # Read the ActiveModeThreshold attribute if ICD is supported + if self.supports_icd: + self.active_mode_threshold_ms = await self.get_active_mode_threshold_ms() + log.info(f"\n\n\t** active_mode_threshold_ms: {self.active_mode_threshold_ms}\n") + + # *** STEP 3 *** + # Check if the LITS feature is supported + self.step(3) + if self.supports_icd: + feature_map = await self.get_icd_feature_map() + LITS = Clusters.IcdManagement.Bitmaps.Feature.kLongIdleTimeSupport + self.supports_lit = bool(feature_map & LITS == LITS) + log.info(f"\n\n\t** supports_lit: {self.supports_lit}\n") + + # *** STEP 4 *** + # Check if the DUT supports TCP + self.step(4) + instance_name = self.get_dut_instance_name(log_result=True) + instance_qname = f"{instance_name}.{MdnsServiceType.OPERATIONAL.value}" + self.supports_tcp_dut = await is_dut_tcp_supported(instance_qname) + log.info(f"\n\n\t** supports_tcp_dut: {self.supports_tcp_dut}\n") + + # *** STEP 5 *** + # Check if TCP is supported per PICS + self.step(5) + self.supports_tcp_pics = self.check_pics(TCP_PICS_STR) + log.info(f"\n\n\t** supports_tcp_pics: {self.supports_tcp_pics}\n") + + # *** STEP 6 *** + # Check the setup code type used during commissioning (QR or Manual) + self.step(6) + if self.matter_test_config.manual_code: + self.setup_code_type = SetupCodeType.MANUAL_CODE + elif self.matter_test_config.qr_code_content: + self.setup_code_type = SetupCodeType.QR_CODE + else: + self.setup_code_type = SetupCodeType.NONE_SUPLIED + is_long_discriminator = self.setup_code_type == SetupCodeType.QR_CODE + + # *** STEP 7 *** + # Check if the Open Basic Commissioning Window command is supported + self.step(7) + supports_obcw = await self.feature_guard( + endpoint=ROOT_NODE_ENDPOINT_ID, + cluster=Clusters.AdministratorCommissioning, + feature_int=Clusters.AdministratorCommissioning.Bitmaps.Feature.kBasic) + + # *** STEP 8 *** + # DUT is put in Commissioning Mode using the Open Basic Commissioning Window command if supported (supports_obcw) + if supports_obcw: + self.step(8) + log.info("\n\n\t ** Open Basic Commissioning Window supported\n") + await self.default_controller.SendCommand( + nodeId=self.dut_node_id, + endpoint=0, + payload=obcw_cmd, + timedRequestTimeoutMs=6000 + ) + + # *** STEP 9 *** + # TH gets the discriminator from the DUT and constructs the Discriminator + # subtype (Long or Short)based on the setup code type (QR or Manual) + self.step(9) + discriminator_subtype, discriminator = self.get_discriminator_subtype(is_obcw=True) + + # *** STEP 10 *** + # Get the Discriminator Subtype (Long or Short) PTR record's instance name + self.step(10) + discriminator_ptr_instance_name = await self._get_verify_discriminator_subtype_ptr_instance_name(discriminator_subtype) + + # *** STEP 11 *** + # Verify commissionable subtype advertisements + self.step(11) + await self._verify_commissionable_subtypes(discriminator, discriminator_subtype, discriminator_ptr_instance_name, is_long_discriminator) + + # *** STEP 12 *** + # Verify SRV record advertisements + self.step(12) + srv_hostname = await self._get_verify_srv_record(discriminator_ptr_instance_name) + + # *** STEP 13 *** + # Verify TXT record advertisements + self.step(13) + await self._verify_txt_record_keys(discriminator_ptr_instance_name, expected_cm="1") + + # *** STEP 14 *** + # Verify AAAA records + self.step(14) + await self._verify_aaaa_records(srv_hostname) + + # *** STEP 15 *** + # Close commissioning window + self.step(15) + await self.close_commissioning_window() + else: + log.info("\n\n\t ** Open Basic Commissioning Window command is unsupported, skipping advertisement verification steps.\n") + self.mark_step_range_skipped(8, 15) + + # *** STEP 16 *** + # TH gets the Long Discriminator from the DUT and constructs the Long Discriminator Subtype + self.step(16) + long_discriminator_subtype, long_discriminator = self.get_discriminator_subtype(is_obcw=False) + + # *** STEP 17 *** + # DUT is put in Commissioning Mode using Open Commissioning Window command + self.step(17) + await self.default_controller.OpenCommissioningWindow( + nodeId=self.dut_node_id, + timeout=180, + iteration=10000, + discriminator=long_discriminator, + option=1 + ) + + # *** STEP 18 *** + # Get the 'Long Discriminator Subtype' PTR record's instance name + self.step(18) + long_discriminator_ptr_instance_name = await self._get_verify_discriminator_subtype_ptr_instance_name(long_discriminator_subtype) + + # *** STEP 19 *** + # Verify commissionable subtype advertisements + self.step(19) + await self._verify_commissionable_subtypes(long_discriminator, long_discriminator_subtype, long_discriminator_ptr_instance_name, is_long_discriminator=True) + + # *** STEP 20 *** + # Verify SRV record advertisements + self.step(20) + srv_hostname = await self._get_verify_srv_record(long_discriminator_ptr_instance_name) + + # *** STEP 21 *** + # Verify TXT record keys advertisements + self.step(21) + await self._verify_txt_record_keys(long_discriminator_ptr_instance_name, expected_cm="2") + + # *** STEP 22 *** + # Verify AAAA records + self.step(22) + await self._verify_aaaa_records(srv_hostname) + + # *** STEP 23 *** + # Close commissioning window + self.step(23) + await self.close_commissioning_window() + + # *** STEP 24 *** + # Check if DUT Extended Discovery mode is active + self.step(24) + # Get the 'Long Discriminator Subtype' PTR record's instance name + long_discriminator_ptr_instance_name = await self._get_verify_discriminator_subtype_ptr_instance_name(long_discriminator_subtype, must_be_present=False) + + # If the DUT's 'Long Discriminator Subtype' PTR record's instance name is present, Extended Discovery mode is active + extended_discovery_mode = long_discriminator_ptr_instance_name is not None + log.info(f"DUT Extended Discovery mode active: {extended_discovery_mode}") + + if extended_discovery_mode: + # *** STEP 25 *** + # Verify commissionable subtype advertisements + self.step(25) + await self._verify_commissionable_subtypes(long_discriminator, long_discriminator_subtype, long_discriminator_ptr_instance_name, is_long_discriminator=True, extended_discovery=extended_discovery_mode) + + # *** STEP 26 *** + # Verify SRV record advertisements + self.step(26) + srv_hostname = await self._get_verify_srv_record(long_discriminator_ptr_instance_name) + + # *** STEP 27 *** + # Verify TXT record keys advertisements + self.step(27) + await self._verify_txt_record_keys(long_discriminator_ptr_instance_name, expected_cm="0") + + # *** STEP 28 *** + # Verify AAAA records + self.step(28) + await self._verify_aaaa_records(srv_hostname) + else: + log.info("Skipping Extended Discovery mode advertisements verification steps.") + self.mark_step_range_skipped(25, 28) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_SC_4_3.py b/src/python_testing/TC_SC_4_3.py index 4f9de52aef5..05bca5df987 100644 --- a/src/python_testing/TC_SC_4_3.py +++ b/src/python_testing/TC_SC_4_3.py @@ -30,6 +30,7 @@ # --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 # run2: @@ -42,6 +43,7 @@ # --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 # === END CI TEST ARGUMENTS === @@ -51,10 +53,15 @@ from mdns_discovery.mdns_discovery import MdnsDiscovery, MdnsServiceType from mdns_discovery.utils.asserts import (assert_valid_hostname, assert_valid_icd_key, assert_valid_ipv6_addresses, assert_valid_sai_key, assert_valid_sat_key, assert_valid_sii_key, assert_valid_t_key) +from mdns_discovery.utils.network import is_dut_tcp_supported from mobly import asserts import matter.clusters as Clusters -from matter.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from matter.testing.decorators import async_test_body +from matter.testing.matter_testing import MatterBaseTest +from matter.testing.runner import TestStep, default_matter_test_main + +log = logging.getLogger(__name__) ''' Purpose @@ -80,18 +87,22 @@ def steps_TC_SC_4_3(self): TestStep(3, "If supports_icd is true, TH reads ActiveModeThreshold from the ICD Management cluster on EP0 and saves as active_mode_threshold.", ""), TestStep(4, "If supports_icd is true, TH reads FeatureMap from the ICD Management cluster on EP0. If the LITS feature is set, set supports_lit to true. Otherwise set supports_lit to false.", ""), - TestStep(5, "TH constructs the instance name for the DUT as the 64-bit compressed Fabric identifier, and the assigned 64-bit Node identifier, each expressed as a fixed-length sixteen-character hexadecimal string, encoded as ASCII (UTF-8) text using capital letters, separated by a hyphen.", ""), - TestStep(6, "TH performs a query for the SRV record against the qname instance_qname.", + TestStep(5, "TH checks if TCP is supported by the DUT.", + "Set supports_tcp_dut to True if supported, otherwise, to False"), + TestStep(6, "TH checks if TCP is supported by the PICS.", + "Set supports_tcp_pics to True if supported, otherwise, to False"), + TestStep(7, "TH constructs the instance name for the DUT as the 64-bit compressed Fabric identifier, and the assigned 64-bit Node identifier, each expressed as a fixed-length sixteen-character hexadecimal string, encoded as ASCII (UTF-8) text using capital letters, separated by a hyphen.", ""), + TestStep(8, "TH performs a query for the SRV record against the qname instance_qname.", "Verify SRV record is returned"), - TestStep(7, "TH performs a query for the TXT record against the qname instance_qname.", + TestStep(9, "TH performs a query for the TXT record against the qname instance_qname.", "Verify TXT record is returned if the device supports ICD or TCP. The TXT record MAY be returned if these are not supported, but it is not required."), - TestStep(8, "TH performs a query for the AAAA record against the target listed in the SRV record", + TestStep(10, "TH performs a query for the AAAA record against the target listed in the SRV record", "Verify AAAA record is returned"), - TestStep(9, "TH verifies the following from the returned records:", + TestStep(11, "TH verifies the following from the returned records:", "The hostname must be a fixed-length twelve-character (or sixteen-character) hexadecimal string, encoded as ASCII (UTF-8) text using capital letters.. ICD TXT key: • If supports_lit is false, verify that the ICD key is NOT present in the TXT record • If supports_lit is true, verify the ICD key IS present in the TXT record, and it has the value of 0 or 1 (ASCII) SII TXT key: • If supports_icd is true and supports_lit is false, set sit_mode to true • If supports_icd is true and supports_lit is true, set sit_mode to true if ICD=0 otherwise set sit_mode to false • If supports_icd is false, set sit_mode to false • If sit_mode is true, verify that the SII key IS present in the TXT record • if the SII key is present, verify it is a decimal value with no leading zeros and is less than or equal to 3600000 (1h in ms) SAI TXT key: • if supports_icd is true, verify that the SAI key is present in the TXT record • If the SAI key is present, verify it is a decimal value with no leading zeros and is less than or equal to 3600000 (1h in ms)"), - TestStep(10, "TH performs a DNS-SD browse for _I._sub._matter._tcp.local, where is the 64-bit compressed Fabric identifier, expressed as a fixed-length, sixteencharacter hexadecimal string, encoded as ASCII (UTF-8) text using capital letters.", + TestStep(12, "TH performs a DNS-SD browse for _I._sub._matter._tcp.local, where is the 64-bit compressed Fabric identifier, expressed as a fixed-length, sixteencharacter hexadecimal string, encoded as ASCII (UTF-8) text using capital letters.", "Verify DUT returns a PTR record with DNS-SD instance name set to instance_name"), - TestStep(11, "TH performs a DNS-SD browse for _matter._tcp.local", + TestStep(13, "TH performs a DNS-SD browse for _matter._tcp.local", "Verify DUT returns a PTR record with DNS-SD instance name set to instance_name"), ] @@ -124,14 +135,14 @@ def get_dut_instance_name(self, log_result: bool = False) -> str: compressed_fabric_id = self.default_controller.GetCompressedFabricId() instance_name = f'{compressed_fabric_id:016X}-{node_id:016X}' if log_result: - logging.info(f"\n\n\tDUT Instance Name: {instance_name}\n") + log.info(f"\n\n\tDUT Instance Name: {instance_name}\n") return instance_name def get_operational_subtype(self, log_result: bool = False) -> str: compressed_fabric_id = self.default_controller.GetCompressedFabricId() operational_subtype = f'_I{compressed_fabric_id:016X}._sub.{MdnsServiceType.OPERATIONAL.value}' if log_result: - logging.info(f"\n\n\tOperational Subtype: {operational_subtype}\n") + log.info(f"\n\n\tOperational Subtype: {operational_subtype}\n") return operational_subtype @staticmethod @@ -148,45 +159,40 @@ def verify_decimal_value(input_value, max_value: int): if input_int <= max_value: return (True, f"Input ({input_value}) is valid.") - else: - return (False, f"Input ({input_value}) exceeds the allowed value {max_value}.") + return (False, f"Input ({input_value}) exceeds the allowed value {max_value}.") except ValueError: return (False, f"Input ({input_value}) is not a valid decimal number.") - def verify_t_value(self, operational_record): - has_t = operational_record and operational_record.txt and 'T' in operational_record.txt - if not has_t: - asserts.assert_false(self.check_pics(TCP_PICS_STR), - f"T key must be included if TCP is supported - returned TXT record: {operational_record}") - return True, 'T is not provided or required' - - t_value = operational_record.txt['T'] - logging.info("T key is present in TXT record, verify if that it is a decimal value with no leading zeros and is less than or equal to 6. Convert the value to a bitmap and verify bit 0 is clear.") - # Verify t_value is a decimal number without leading zeros and less than or equal to 6 - try: - assert_valid_t_key(t_value, enforce_provisional=False) - - # Convert to bitmap and verify bit 0 is clear - T_int = int(t_value) - if T_int & 1 == 0: - return True, f"T value ({t_value}) is valid and bit 0 is clear." - else: - return False, f"Bit 0 is not clear. T value ({t_value})" - - # Check that the value can be either 2, 4 or 6 depending on whether - # DUT is a TCPClient, TCPServer or both. - if self.check_pics(TCP_PICS_STR): - if (T_int & 0x04 != 0): - return True, f"T value ({t_value}) represents valid TCP support info." - else: - return False, f"T value ({t_value}) does not have TCP bits set even though the MCORE.SC.TCP PICS indicates it is required." - else: - if (T_int & 0x04 != 0): - return False, f"T value ({t_value}) has the TCP bits set even though the MCORE.SC.TCP PICS is not set." - else: - return True, f"T value ({t_value}) is valid." - except ValueError: - return False, f"T value ({t_value}) is not a valid integer" + # def verify_t_value(self, operational_record): + # has_t = operational_record and operational_record.txt and 'T' in operational_record.txt + # if not has_t: + # asserts.assert_false(self.check_pics(TCP_PICS_STR), + # f"T key must be included if TCP is supported - returned TXT record: {operational_record}") + # return True, 'T is not provided or required' + + # t_value = operational_record.txt['T'] + # log.info("T key is present in TXT record, verify if that it is a decimal value with no leading zeros and is less than or equal to 6. Convert the value to a bitmap and verify bit 0 is clear.") + # # Verify t_value is a decimal number without leading zeros and less than or equal to 6 + # try: + # assert_valid_t_key(t_value, enforce_provisional=False) + + # # Convert to bitmap and verify bit 0 is clear + # T_int = int(t_value) + # if T_int & 1 == 0: + # return True, f"T value ({t_value}) is valid and bit 0 is clear." + # return False, f"Bit 0 is not clear. T value ({t_value})" + + # # Check that the value can be either 2, 4 or 6 depending on whether + # # DUT is a TCPClient, TCPServer or both. + # if self.check_pics(TCP_PICS_STR): + # if (T_int & 0x04 != 0): + # return True, f"T value ({t_value}) represents valid TCP support info." + # return False, f"T value ({t_value}) does not have TCP bits set even though the MCORE.SC.TCP PICS indicates it is required." + # if (T_int & 0x04 != 0): + # return False, f"T value ({t_value}) has the TCP bits set even though the MCORE.SC.TCP PICS is not set." + # return True, f"T value ({t_value}) is valid." + # except ValueError: + # return False, f"T value ({t_value}) is not a valid integer" @async_test_body async def test_TC_SC_4_3(self): @@ -206,7 +212,7 @@ async def test_TC_SC_4_3(self): # Check if ep0_servers contain the ICD Management cluster ID (0x0046) supports_icd = Clusters.IcdManagement.id in ep0_servers - logging.info(f"supports_icd: {supports_icd}") + log.info(f"supports_icd: {supports_icd}") # *** STEP 3 *** # If supports_icd is true, TH reads ActiveModeThreshold from the ICD Management cluster on EP0 and saves @@ -214,7 +220,7 @@ async def test_TC_SC_4_3(self): self.step(3) if supports_icd: active_mode_threshold_ms = await self.get_idle_mode_threshhold_ms() - logging.info(f"active_mode_threshold_ms: {active_mode_threshold_ms}") + log.info(f"active_mode_threshold_ms: {active_mode_threshold_ms}") # *** STEP 4 *** # If supports_icd is true, TH reads FeatureMap from the ICD Management cluster on EP0. If the LITS feature @@ -224,7 +230,7 @@ async def test_TC_SC_4_3(self): feature_map = await self.get_icd_feature_map() LITS = Clusters.IcdManagement.Bitmaps.Feature.kLongIdleTimeSupport supports_lit = bool(feature_map & LITS == LITS) - logging.info(f"kLongIdleTimeSupport set: {supports_lit}") + log.info(f"kLongIdleTimeSupport set: {supports_lit}") # *** STEP 5 *** # TH constructs the instance name for the DUT as the 64-bit compressed Fabric identifier, and the @@ -235,8 +241,18 @@ async def test_TC_SC_4_3(self): instance_qname = f"{instance_name}.{MdnsServiceType.OPERATIONAL.value}" # *** STEP 6 *** - # TH performs a query for the SRV record against the qname instance_qname. + # TH checks if TCP is supported by the DUT self.step(6) + supports_tcp_dut = await is_dut_tcp_supported(instance_qname) + + # *** STEP 7 *** + # TH checks if TCP is supported by the PICS + self.step(7) + supports_tcp_pics = self.check_pics(TCP_PICS_STR) + + # *** STEP 8 *** + # TH performs a query for the SRV record against the qname instance_qname. + self.step(8) mdns = MdnsDiscovery() srv_record = await mdns.get_srv_record( service_name=instance_qname, @@ -248,10 +264,10 @@ async def test_TC_SC_4_3(self): srv_record_returned = srv_record is not None and srv_record.service_name == instance_qname asserts.assert_true(srv_record_returned, "SRV record was not returned") - # *** STEP 7 *** + # *** STEP 9 *** # TH performs a query for the TXT record against the qname instance_qname. # Verify TXT record is returned - self.step(7) + self.step(9) txt_record = await mdns.get_txt_record( service_name=instance_qname, service_type=MdnsServiceType.OPERATIONAL.value, @@ -261,14 +277,14 @@ async def test_TC_SC_4_3(self): # Request the TXT record. The device may opt not to return a TXT record if there are no mandatory TXT keys txt_record_returned = txt_record is not None and txt_record.txt is not None and bool( txt_record.txt) - txt_record_required = supports_icd or self.check_pics(TCP_PICS_STR) + txt_record_required = supports_icd or supports_tcp_pics if txt_record_required: asserts.assert_true(txt_record_returned, "TXT record is required and was not returned or contains no values") - # *** STEP 8 *** + # *** STEP 10 *** # TH performs a query for the AAAA record against the target listed in the SRV record. - self.step(8) + self.step(10) quada_records = await mdns.get_quada_records( hostname=srv_record.hostname, log_output=True @@ -277,7 +293,7 @@ async def test_TC_SC_4_3(self): # Verify AAAA record is returned asserts.assert_greater(len(quada_records), 0, f"No AAAA addresses were resolved for hostname '{srv_record.hostname}'") - # # *** STEP 9 *** + # # *** STEP 11 *** # TH verifies the following from the returned records: The hostname must be a fixed-length twelve-character (or sixteen-character) # hexadecimal string, encoded as ASCII (UTF-8) text using capital letters.. ICD TXT key: • If supports_lit is false, verify that the # ICD key is NOT present in the TXT record • If supports_lit is true, verify the ICD key IS present in the TXT record, and it has the @@ -287,17 +303,17 @@ async def test_TC_SC_4_3(self): # it is a decimal value with no leading zeros and is less than or equal to 3600000 (1h in ms) SAI TXT key: • if supports_icd is true, # verify that the SAI key is present in the TXT record • If the SAI key is present, verify it is a decimal value with no leading # zeros and is less than or equal to 3600000 (1h in ms) - self.step(9) + self.step(11) def txt_has_key(key: str): - return txt_record_returned and key in txt_record.txt.keys() + return txt_record_returned and key in txt_record.txt # Verify hostname character length (12 or 16) assert_valid_hostname(srv_record.hostname) # ICD TXT KEY if supports_lit: - logging.info("supports_lit is true, verify the ICD key IS present in the TXT record, and it has the value of 0 or 1 (ASCII).") + log.info("supports_lit is true, verify the ICD key IS present in the TXT record, and it has the value of 0 or 1 (ASCII).") # Verify the ICD key IS present asserts.assert_true(txt_has_key('ICD'), "ICD key is NOT present in the TXT record.") @@ -305,7 +321,7 @@ def txt_has_key(key: str): # Verify it has the value of 0 or 1 (ASCII) assert_valid_icd_key(txt_record.txt['ICD']) else: - logging.info("supports_lit is false, verify that the ICD key is NOT present in the TXT record.") + log.info("supports_lit is false, verify that the ICD key is NOT present in the TXT record.") if txt_record_returned: asserts.assert_not_in('ICD', txt_record.txt, "ICD key is present in the TXT record.") @@ -323,44 +339,47 @@ def txt_has_key(key: str): sit_mode = False if sit_mode: - logging.info("sit_mode is True, verify the SII key IS present.") + log.info("sit_mode is True, verify the SII key IS present.") asserts.assert_true(txt_has_key('SII'), "SII key is NOT present in the TXT record.") - logging.info("Verify SII value is a decimal with no leading zeros and is less than or equal to 3600000 (1h in ms).") + log.info("Verify SII value is a decimal with no leading zeros and is less than or equal to 3600000 (1h in ms).") assert_valid_sii_key(txt_record.txt['SII']) # SAI TXT KEY if supports_icd: - logging.info("supports_icd is True, verify the SAI key IS present.") + log.info("supports_icd is True, verify the SAI key IS present.") asserts.assert_true(txt_has_key('SAI'), "SAI key is NOT present in the TXT record.") - logging.info("Verify SAI value is a decimal with no leading zeros and is less than or equal to 3600000 (1h in ms).") + log.info("Verify SAI value is a decimal with no leading zeros and is less than or equal to 3600000 (1h in ms).") assert_valid_sai_key(txt_record.txt['SAI']) # SAT TXT KEY if txt_has_key('SAT'): - logging.info( + log.info( "SAT key is present in TXT record, verify that it is a decimal value with no leading zeros and is less than or equal to 65535.") assert_valid_sat_key(txt_record.txt['SAT']) if supports_icd: - logging.info("supports_icd is True, verify the SAT value is equal to active_mode_threshold.") + log.info("supports_icd is True, verify the SAT value is equal to active_mode_threshold.") asserts.assert_equal(int(txt_record.txt['SAT']), active_mode_threshold_ms) # T TXT KEY - result, message = self.verify_t_value(txt_record) - asserts.assert_true(result, message) + t_key_present = 'T' in txt_record.txt + if supports_tcp_dut: + asserts.assert_true(t_key_present, "T key must be present if DUT supports TCP.") + t_key = txt_record.txt.get('T', None) + assert_valid_t_key(t_key, t_key_present, supports_tcp_dut, supports_tcp_pics, enforce_provisional=False) # Verify the AAAA records contain a valid IPv6 address - logging.info("Verify the AAAA record contains a valid IPv6 address") + log.info("Verify the AAAA record contains a valid IPv6 address") ipv6_addresses = [f"{r.address}%{r.interface}" for r in quada_records] assert_valid_ipv6_addresses(ipv6_addresses) - # # *** STEP 10 *** + # # *** STEP 12 *** # TH performs a DNS-SD browse for _I._sub._matter._tcp.local, where is the 64-bit compressed # Fabric identifier, expressed as a fixed-length, sixteencharacter hexadecimal string, encoded as ASCII (UTF-8) # text using capital letters. - self.step(10) + self.step(12) op_sub_type = self.get_operational_subtype(log_result=True) ptr_records = await mdns.get_ptr_records( service_types=[op_sub_type], @@ -373,9 +392,9 @@ def txt_has_key(key: str): f"No PTR record with DNS-SD instance name '{instance_name}' was found." ) - # # *** STEP 11 *** + # # *** STEP 13 *** # TH performs a DNS-SD browse for _matter._tcp.local - self.step(11) + self.step(13) ptr_records = await mdns.get_ptr_records( service_types=[MdnsServiceType.OPERATIONAL.value], log_output=True, diff --git a/src/python_testing/TC_TLSCERT_2_1.py b/src/python_testing/TC_TLSCERT_2_1.py new file mode 100644 index 00000000000..80249c6ab66 --- /dev/null +++ b/src/python_testing/TC_TLSCERT_2_1.py @@ -0,0 +1,87 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +from mobly import asserts +from TC_TLSCERT_Base import TC_TLSCERT_Base + +import matter.clusters as Clusters +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCERT_2_1(TC_TLSCERT_Base): + def pics_TC_TLSCERT_2_1(self): + return ["TLSCERT.S"] + + def desc_TC_TLSCERT_2_1(self) -> str: + return "[TC-TLSCERT-2.1] Attributes with Server as DUT" + + def steps_TC_TLSCERT_2_1(self) -> list[TestStep]: + return [ + *self.get_common_substeps(), + TestStep(2, "TH reads MaxRootCertificates attribute", "DUT replies with an uint8 value between 5 and 254."), + TestStep(3, "TH reads ProvisionedRootCertificates attribute", "DUT replies with an empty list of TLSCertStruct."), + TestStep(4, "TH reads MaxClientCertificates attribute", "DUT replies with an uint8 value between 2 and 254."), + TestStep(5, "TH reads ProvisionedClientCertificates attribute", + "DUT replies with an empty list of TLSClientCertificateDetailStruct."), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsCertificateManagement)) + async def test_TC_TLSCERT_2_1(self): + attributes = Clusters.TlsCertificateManagement.Attributes + + cr1_cmd = await self.common_setup() + + self.step(2) + max_root_certs = await cr1_cmd.read_tls_cert_attribute(attributes.MaxRootCertificates) + asserts.assert_greater_equal(max_root_certs, 5, "MaxRootCertificates should be >= 5") + asserts.assert_less_equal(max_root_certs, 254, "MaxRootCertificates should be <= 254") + + self.step(3) + provisioned_root_certs = await cr1_cmd.read_tls_cert_attribute(attributes.ProvisionedRootCertificates) + asserts.assert_equal(len(provisioned_root_certs), 0, "ProvisionedRootCertificates should be empty") + + self.step(4) + max_client_certs = await cr1_cmd.read_tls_cert_attribute(attributes.MaxClientCertificates) + asserts.assert_greater_equal(max_client_certs, 2, "MaxClientCertificates should be >= 2") + asserts.assert_less_equal(max_client_certs, 254, "MaxClientCertificates should be <= 254") + + self.step(5) + provisioned_client_certs = await cr1_cmd.read_tls_cert_attribute(attributes.ProvisionedClientCertificates) + asserts.assert_equal(len(provisioned_client_certs), 0, "ProvisionedClientCertificates should be empty") + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCERT_2_10.py b/src/python_testing/TC_TLSCERT_2_10.py new file mode 100644 index 00000000000..3864ae6088c --- /dev/null +++ b/src/python_testing/TC_TLSCERT_2_10.py @@ -0,0 +1,154 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import random + +import test_plan_support +from mobly import asserts +from TC_TLSCERT_Base import TC_TLSCERT_Base + +import matter.clusters as Clusters +from matter.interaction_model import Status +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCERT_2_10(TC_TLSCERT_Base): + def pics_TC_TLSCERT_2_10(self): + return ["TLSCERT.S"] + + def desc_TC_TLSCERT_2_10(self) -> str: + return "[TC-TLSCERT-2.10] ProvisionClientCertificate command verification with bad arguments" + + def steps_TC_TLSCERT_2_10(self) -> list[TestStep]: + return [ + *self.get_two_fabric_substeps(), + TestStep(2, "Populate myNonce with a random 32-octet values"), + TestStep(3, "CR1 sends sends ClientCSR command with Nonce set to myNonce.", + "DUT replies with CCDID, CSR and Nonce. Store TLSCCDID in myCcdid and CSR in myCsr."), + TestStep(4, + "Set myBigCert to a valid DER encoding of a valid, self-signed x509 certificate using the public key from csr. The certificate should be large enough that the DER encoding is larger than 3000 octets."), + TestStep(5, "Set myBadCert to an octstr under 3000 that is not a valid DER encoding."), + TestStep(6, + "Set myWrongKey to a valid DER encoding of a valid, self-signed x509 certificate using a public key not equal to that in myCsr."), + TestStep(7, + "Populate myIntermediateCerts with 1 DER-encoded x509 certificates that form a certificate chain up to (but not including) a root."), + TestStep(8, + "Populate myClientCert with a distinct, valid, DER-encoded x509 certificates using the public key from myCsr and signed by myIntermediateCerts[0]."), + TestStep(9, "CR1 sends ProvisionClientCertificate command with CCDID set to myCcdid and ClientCertificate set to myBigCert.", + test_plan_support.verify_status(Status.ConstraintError)), + TestStep(10, "CR1 sends ProvisionClientCertificate command with CCDID set to myCcdid, ClientCertificate set to myClientCert, and IntermediateCertificates set to myBigCert.", + test_plan_support.verify_status(Status.ConstraintError)), + TestStep(11, "CR1 sends ProvisionClientCertificate command with CCDID set to myCcdid and ClientCertificate set to myBadCert.", + test_plan_support.verify_status(Status.DynamicConstraintError)), + TestStep(12, "CR1 sends ProvisionClientCertificate command with CCDID set to myCcdid and ClientCertificate set to myWrongKey.", + test_plan_support.verify_status(Status.DynamicConstraintError)), + TestStep(13, "CR1 sends ProvisionClientCertificate command with CCDID set to myCcdid, ClientCertificate set to myClientCert, and IntermediateCertificates set to myBadCert.", + test_plan_support.verify_status(Status.DynamicConstraintError)), + TestStep(14, "CR1 sends ProvisionClientCertificate command with CCDID set to a value not equal to myCcdid and ClientCertificate set to myClientCert[0].", + test_plan_support.verify_status(Status.NotFound)), + TestStep(15, "CR2 sends ProvisionClientCertificate command with CCDID set to myCcdid and ClientCertificate set to myClientCert.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(16, "CR1 sends RemoveClientCertificate command with CCDID set to myCcdid.", + test_plan_support.verify_success()), + TestStep(17, test_plan_support.remove_fabric('CR2', 'CR1'), test_plan_support.verify_success()), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsCertificateManagement)) + async def test_TC_TLSCERT_2_10(self): + setup_data = await self.common_two_fabric_setup() + cr1_cmd = setup_data.cr1_cmd + cr2_cmd = setup_data.cr2_cmd + + self.step(2) + my_nonce = random.randbytes(32) + + self.step(3) + response = await cr1_cmd.send_csr_command(nonce=my_nonce) + cr1_cmd.assert_valid_ccdid(response.ccdid) + my_ccdid = response.ccdid + my_csr = cr1_cmd.assert_valid_csr(response, my_nonce) + + self.step(4) + root = cr1_cmd.get_key() + my_big_cert = cr1_cmd.gen_cert_with_key(signer=root, public_key=my_csr.public_key(), + builder_lambda=self.pad_out_certificate) + asserts.assert_greater(len(my_big_cert), 3000) + + self.step(5) + my_bad_cert = b"not a cert" + + self.step(6) + key_for_wrong_cert = cr1_cmd.get_key() + my_wrong_key_cert = cr1_cmd.gen_cert_with_key(key_for_wrong_cert, public_key=key_for_wrong_cert.public_key()) + + self.step(7) + certs_with_key = cr1_cmd.gen_cert_chain(key_for_wrong_cert, 1) + signer_key = certs_with_key[0].key + + self.step(8) + my_client_cert = cr1_cmd.gen_cert_with_key( + signer_key, public_key=my_csr.public_key(), subject=my_csr.subject) + + self.step(9) + await cr1_cmd.send_provision_client_command(ccdid=my_ccdid, certificate=my_big_cert, expected_status=Status.ConstraintError) + + self.step(10) + await cr1_cmd.send_provision_client_command(ccdid=my_ccdid, certificate=my_client_cert, intermediates=[my_big_cert], expected_status=Status.ConstraintError) + + self.step(11) + await cr1_cmd.send_provision_client_command(ccdid=my_ccdid, certificate=my_bad_cert, expected_status=Status.DynamicConstraintError) + + self.step(12) + await cr1_cmd.send_provision_client_command(ccdid=my_ccdid, certificate=my_wrong_key_cert, expected_status=Status.DynamicConstraintError) + + self.step(13) + await cr1_cmd.send_provision_client_command(ccdid=my_ccdid, certificate=my_client_cert, intermediates=[my_bad_cert], expected_status=Status.DynamicConstraintError) + + self.step(14) + await cr1_cmd.send_provision_client_command(ccdid=my_ccdid + 1, certificate=my_client_cert, expected_status=Status.NotFound) + + self.step(15) + await cr2_cmd.send_provision_client_command(ccdid=my_ccdid, certificate=my_client_cert, expected_status=Status.NotFound) + + self.step(16) + await cr1_cmd.send_remove_client_command(ccdid=my_ccdid) + + self.step(17) + await cr1_cmd.send_remove_fabric_command(cr2_cmd.fabric_index) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCERT_2_11.py b/src/python_testing/TC_TLSCERT_2_11.py new file mode 100644 index 00000000000..faa00b60346 --- /dev/null +++ b/src/python_testing/TC_TLSCERT_2_11.py @@ -0,0 +1,119 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import random + +import test_plan_support +from mobly import asserts +from TC_TLSCERT_Base import TC_TLSCERT_Base + +import matter.clusters as Clusters +from matter.clusters.Types import NullValue +from matter.interaction_model import Status +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCERT_2_11(TC_TLSCERT_Base): + def pics_TC_TLSCERT_2_11(self): + return ["TLSCERT.S"] + + def desc_TC_TLSCERT_2_11(self) -> str: + return "[TC-TLSCERT-2.11] FindClientCertificate command verification" + + def steps_TC_TLSCERT_2_11(self) -> list[TestStep]: + return [ + *self.get_two_fabric_substeps(), + TestStep(2, "Set myNonce to a random 32-octet value"), + TestStep(3, "CR1 sends FindClientCertificate command with null CCDID.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(4, "CR1 sends ClientCSR command with Nonce set to myNonce.", + "DUT replies with CCDID, CSR and Nonce. Store TLSCCDID in myCcdid."), + TestStep(5, "CR1 sends FindClientCertificate command with CCDID set to myCcdid.", + "DUT replies with a list of TLSClientCertificateDetailsStruct with one entry. The entry should have CCDID with value myCcdid with ClientCertificate and IntermediateCertificates unset."), + TestStep(6, "CR1 sends FindClientCertificate command with CCDID set to myCcdid + 1.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(7, "CR2 sends FindClientCertificate command with null CCDID.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(8, "CR2 sends FindClientCertificate command with CCDID set to myCcdid.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(9, "CR1 sends RemoveClientCertificate command with CCDID set to myCcdid.", + test_plan_support.verify_success()), + TestStep(10, test_plan_support.remove_fabric('CR2', 'CR1'), test_plan_support.verify_success()), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsCertificateManagement)) + async def test_TC_TLSCERT_2_11(self): + setup_data = await self.common_two_fabric_setup() + cr1_cmd = setup_data.cr1_cmd + cr2_cmd = setup_data.cr2_cmd + + self.step(2) + my_nonce = random.randbytes(32) + + self.step(3) + await cr1_cmd.send_find_client_command(expected_status=Status.NotFound) + + self.step(4) + response = await cr1_cmd.send_csr_command(nonce=my_nonce) + cr1_cmd.assert_valid_ccdid(response.ccdid) + cr1_cmd.assert_valid_csr(response, my_nonce) + my_ccdid = response.ccdid + + self.step(5) + find_response = await cr1_cmd.send_find_client_command(ccdid=my_ccdid) + asserts.assert_equal(len(find_response.certificateDetails), 1) + asserts.assert_equal(find_response.certificateDetails[0].ccdid, my_ccdid) + asserts.assert_equal(find_response.certificateDetails[0].clientCertificate, NullValue) + asserts.assert_equal(len(find_response.certificateDetails[0].intermediateCertificates), 0) + + self.step(6) + await cr1_cmd.send_find_client_command(ccdid=my_ccdid + 1, expected_status=Status.NotFound) + + self.step(7) + await cr2_cmd.send_find_client_command(expected_status=Status.NotFound) + + self.step(8) + await cr2_cmd.send_find_client_command(ccdid=my_ccdid, expected_status=Status.NotFound) + + self.step(9) + await cr1_cmd.send_remove_client_command(ccdid=my_ccdid) + + self.step(10) + await cr1_cmd.send_remove_fabric_command(cr2_cmd.fabric_index) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCERT_2_12.py b/src/python_testing/TC_TLSCERT_2_12.py new file mode 100644 index 00000000000..f3a5912885c --- /dev/null +++ b/src/python_testing/TC_TLSCERT_2_12.py @@ -0,0 +1,186 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import random + +import test_plan_support +from mobly import asserts +from TC_TLSCERT_Base import TC_TLSCERT_Base + +import matter.clusters as Clusters +from matter.interaction_model import Status +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCERT_2_12(TC_TLSCERT_Base): + def pics_TC_TLSCERT_2_12(self): + return ["TLSCERT.S"] + + def desc_TC_TLSCERT_2_12(self) -> str: + return "[TC-TLSCERT-2.12] LookupClientCertificate command verification" + + def steps_TC_TLSCERT_2_12(self) -> list[TestStep]: + return [ + *self.get_two_fabric_substeps(), + TestStep(2, "Populate myNonce[] with 3 distinct, random 32-octet values"), + TestStep(3, "CR1 sends LookupClientCertificate command with Fingerprint set to the empty octstr.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(4, "CR1 sends LookupClientCertificate command with Fingerprint set to and arbitrary octstr.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(5, "CR1 sends ClientCSR command with Nonce set to myNonce[i], for each i in [0..1].", + "DUT replies with CCDID, CSR and Nonce. Store TLSCCDID in myCcdid[i] and CSR in myCsr[i]."), + TestStep(6, "CR2 sends ClientCSR command with Nonce set to myNonce[2].", + "DUT replies with CCDID, CSR and Nonce. Store TLSCCDID in myCcdid[2] and CSR in myCsr[2]."), + TestStep(7, + "Populate myClientCert[] with 3 distinct, valid, self-signed, DER-encoded x509 certificates using each respective public key from myCsr[i]."), + TestStep(8, "Populate myClientCertFingerprint[] with the fingerprints corresponding to myClientCert[]."), + TestStep(9, "Set myBigFingerprint to myClientCertFingerprint[0] concatenated with enough characters to exceed 64."), + TestStep(10, "CR1 sends LookupClientCertificate command with Fingerprint set to the empty octstr.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(11, "CR1 sends LookupClientCertificate command with Fingerprint set to and arbitrary octstr.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(12, "CR1 sends LookupClientCertificate command with Fingerprint set to the myClientCertFingerprint[0]", + test_plan_support.verify_status(Status.NotFound)), + TestStep(13, "CR1 sends ProvisionClientCertificate command with CCDID set to myCcdid[i] and ClientCertificate set to myClientCert[i], for each i in [0..1].", + test_plan_support.verify_success()), + TestStep(14, "CR2 sends ProvisionClientCertificate command with CCDID set to myCcdid[2] and ClientCertificate set to myClientCert[2].", + test_plan_support.verify_success()), + TestStep(15, "CR1 sends LookupClientCertificate command with Fingerprint set to myClientCertFingerprint[0].", + "DUT replies with a TLSCCDID value equal to myCcdid[0]."), + TestStep(16, "CR1 sends LookupClientCertificate command with Fingerprint set to myClientCertFingerprint[1].", + "DUT replies with a TLSCCDID value equal to myCcdid[1]."), + TestStep(17, "CR1 sends LookupClientCertificate command with Fingerprint set to myClientCertFingerprint[2].", + test_plan_support.verify_status(Status.NotFound)), + TestStep(18, "CR2 sends LookupClientCertificate command with Fingerprint set to myClientCertFingerprint[2].", + "DUT replies with a TLSCCDID value equal to myCcdid[2]."), + TestStep(19, "CR1 sends LookupClientCertificate command with Fingerprint set to myBigFingerprint.", + test_plan_support.verify_status(Status.ConstraintError)), + TestStep(20, "CR1 sends RemoveClientCertificate command with CCDID set to myCcdid[i], for each i in [0..1].", + test_plan_support.verify_success()), + TestStep(21, "CR2 sends RemoveClientCertificate command with CCDID set to myCcdid[2].", + test_plan_support.verify_success()), + TestStep(22, test_plan_support.remove_fabric('CR2', 'CR1'), test_plan_support.verify_success()), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsCertificateManagement)) + async def test_TC_TLSCERT_2_12(self): + setup_data = await self.common_two_fabric_setup() + cr1_cmd = setup_data.cr1_cmd + cr2_cmd = setup_data.cr2_cmd + + self.step(2) + my_nonce = [random.randbytes(32) for _ in range(3)] + my_ccdid = [None] * 3 + my_csr = [None] * 3 + my_client_cert = [None] * 3 + + self.step(3) + await cr1_cmd.send_lookup_client_command(fingerprint=b'', expected_status=Status.NotFound) + + self.step(4) + await cr1_cmd.send_lookup_client_command(fingerprint=b'arbitrary', expected_status=Status.NotFound) + + self.step(5) + for i in range(2): + response = await cr1_cmd.send_csr_command(nonce=my_nonce[i]) + cr1_cmd.assert_valid_ccdid(response.ccdid) + my_ccdid[i] = response.ccdid + my_csr[i] = cr1_cmd.assert_valid_csr(response, my_nonce[i]) + + self.step(6) + response = await cr2_cmd.send_csr_command(nonce=my_nonce[2]) + cr2_cmd.assert_valid_ccdid(response.ccdid) + my_ccdid[2] = response.ccdid + my_csr[2] = cr2_cmd.assert_valid_csr(response, my_nonce[2]) + + self.step(7) + root = cr1_cmd.get_key() + for i in range(3): + my_client_cert[i] = cr1_cmd.gen_cert_with_key(root, public_key=my_csr[i].public_key(), subject=my_csr[i].subject) + + self.step(8) + my_client_cert_fingerprint = [cr1_cmd.get_fingerprint(cert) for cert in my_client_cert] + + self.step(9) + my_big_fingerprint = my_client_cert_fingerprint[0] + b'\x00' * (65 - len(my_client_cert_fingerprint[0])) + + self.step(10) + await cr1_cmd.send_lookup_client_command(fingerprint=b'', expected_status=Status.NotFound) + + self.step(11) + await cr1_cmd.send_lookup_client_command(fingerprint=b'arbitrary', expected_status=Status.NotFound) + + self.step(12) + await cr1_cmd.send_lookup_client_command(fingerprint=my_client_cert_fingerprint[0], expected_status=Status.NotFound) + + self.step(13) + for i in range(2): + await cr1_cmd.send_provision_client_command(ccdid=my_ccdid[i], certificate=my_client_cert[i]) + + self.step(14) + await cr2_cmd.send_provision_client_command(ccdid=my_ccdid[2], certificate=my_client_cert[2]) + + self.step(15) + response = await cr1_cmd.send_lookup_client_command(fingerprint=my_client_cert_fingerprint[0]) + asserts.assert_equal(response.ccdid, my_ccdid[0]) + + self.step(16) + response = await cr1_cmd.send_lookup_client_command(fingerprint=my_client_cert_fingerprint[1]) + asserts.assert_equal(response.ccdid, my_ccdid[1]) + + self.step(17) + await cr1_cmd.send_lookup_client_command(fingerprint=my_client_cert_fingerprint[2], expected_status=Status.NotFound) + + self.step(18) + response = await cr2_cmd.send_lookup_client_command(fingerprint=my_client_cert_fingerprint[2]) + asserts.assert_equal(response.ccdid, my_ccdid[2]) + + self.step(19) + await cr1_cmd.send_lookup_client_command(fingerprint=my_big_fingerprint, expected_status=Status.ConstraintError) + + self.step(20) + for i in range(2): + await cr1_cmd.send_remove_client_command(ccdid=my_ccdid[i]) + + self.step(21) + await cr2_cmd.send_remove_client_command(ccdid=my_ccdid[2]) + + self.step(22) + await cr1_cmd.send_remove_fabric_command(cr2_cmd.fabric_index) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCERT_2_13.py b/src/python_testing/TC_TLSCERT_2_13.py new file mode 100644 index 00000000000..de79b21594a --- /dev/null +++ b/src/python_testing/TC_TLSCERT_2_13.py @@ -0,0 +1,150 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import random + +import test_plan_support +from TC_TLSCERT_Base import TC_TLSCERT_Base + +import matter.clusters as Clusters +from matter.interaction_model import Status +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCERT_2_13(TC_TLSCERT_Base): + def pics_TC_TLSCERT_2_13(self): + return ["TLSCERT.S", "TLSCLIENT.S"] + + def desc_TC_TLSCERT_2_13(self) -> str: + return "[TC-TLSCERT-2.13] RemoveClientCertificate command verification" + + def steps_TC_TLSCERT_2_13(self) -> list[TestStep]: + return [ + *self.get_two_fabric_substeps(), + TestStep(2, "Set myNonce to a random 32-octet value"), + TestStep(3, "Set myRootCert to a valid, self-signed, DER-encoded x509 certificate"), + TestStep(4, "CR1 sends RemoveClientCertificate command with CCDID set to 1.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(5, "CR1 sends ClientCSR command with Nonce set to myNonce.", + "DUT replies with CCDID, CSR and Nonce. Store TLSCCDID in myCcdid."), + TestStep(6, "Populate myClientCert with a valid, self-signed, DER-encoded x509 certificate using the public key from the CSR."), + TestStep(7, "CR1 sends ProvisionClientCertificate command with CCDID set to myCcdid and ClientCertificate set to myClientCert.", + test_plan_support.verify_success()), + TestStep(8, "CR2 sends RemoveClientCertificate command with CCDID set to myCcdid.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(9, "CR1 sends ProvisionRootCertificate command with null CAID and Certificate set to myRootCert.", + "DUT replies with a TLSCAID value. Store the returned value as myCaid."), + TestStep(10, "CR1 sends ProvisionEndpoint command with valid Hostname, Port, CAID myCaid and null EndpointID.", + "DUT replies with a TLSEndpointID value. Store the returned value as myEndpoint."), + TestStep(11, "CR1 sends RemoveClientCertificate command with CCDID set to myCcdid.", + test_plan_support.verify_status(Status.InvalidInState)), + TestStep(12, "CR1 sends RemoveEndpoint command with EndpointID set to myEndpoint.", + test_plan_support.verify_success()), + TestStep(13, "CR1 sends RemoveClientCertificate command with CCDID set to myCcdid.", + test_plan_support.verify_success()), + TestStep(14, "CR1 sends FindClientCertificate command with CCDID set to myCcdid.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(15, "CR1 sends RemoveClientCertificate command with CCDID set to myCcdid.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(16, "CR1 sends RemoveRootCertificate command with CAID set to myCaid.", + test_plan_support.verify_success()), + TestStep(17, test_plan_support.remove_fabric('CR2', 'CR1'), test_plan_support.verify_success()), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsCertificateManagement)) + async def test_TC_TLSCERT_2_13(self): + setup_data = await self.common_two_fabric_setup() + cr1_cmd = setup_data.cr1_cmd + cr2_cmd = setup_data.cr2_cmd + + self.step(2) + my_nonce = random.randbytes(32) + + self.step(3) + my_root_cert = cr1_cmd.gen_cert() + + self.step(4) + await cr1_cmd.send_remove_client_command(ccdid=1, expected_status=Status.NotFound) + + self.step(5) + response = await cr1_cmd.send_csr_command(nonce=my_nonce) + cr1_cmd.assert_valid_ccdid(response.ccdid) + my_ccdid = response.ccdid + my_csr = cr1_cmd.assert_valid_csr(response, my_nonce) + + self.step(6) + root = cr1_cmd.get_key() + my_client_cert = cr1_cmd.gen_cert_with_key(root, public_key=my_csr.public_key(), subject=my_csr.subject) + + self.step(7) + await cr1_cmd.send_provision_client_command(ccdid=my_ccdid, certificate=my_client_cert) + + self.step(8) + await cr2_cmd.send_remove_client_command(ccdid=my_ccdid, expected_status=Status.NotFound) + + self.step(9) + response = await cr1_cmd.send_provision_root_command(certificate=my_root_cert) + cr1_cmd.assert_valid_caid(response.caid) + my_caid = response.caid + + self.step(10) + endpoint_response = await cr1_cmd.send_provision_tls_endpoint_command(hostname=b"my_hostname", port=1000, caid=my_caid, ccdid=my_ccdid) + my_endpoint = endpoint_response.endpointID + + self.step(11) + await cr1_cmd.send_remove_client_command(ccdid=my_ccdid, expected_status=Status.InvalidInState) + + self.step(12) + await cr1_cmd.send_remove_tls_endpoint_command(endpoint_id=my_endpoint) + + self.step(13) + await cr1_cmd.send_remove_client_command(ccdid=my_ccdid) + + self.step(14) + await cr1_cmd.send_find_client_command(ccdid=my_ccdid, expected_status=Status.NotFound) + + self.step(15) + await cr1_cmd.send_remove_client_command(ccdid=my_ccdid, expected_status=Status.NotFound) + + self.step(16) + await cr1_cmd.send_remove_root_command(caid=my_caid) + + self.step(17) + await cr1_cmd.send_remove_fabric_command(cr2_cmd.fabric_index) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCERT_2_2.py b/src/python_testing/TC_TLSCERT_2_2.py new file mode 100644 index 00000000000..bc8e278ea1c --- /dev/null +++ b/src/python_testing/TC_TLSCERT_2_2.py @@ -0,0 +1,212 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import test_plan_support +from mobly import asserts +from TC_TLSCERT_Base import TC_TLSCERT_Base + +import matter.clusters as Clusters +from matter.interaction_model import Status +from matter.testing import matter_asserts +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCERT_2_2(TC_TLSCERT_Base): + def pics_TC_TLSCERT_2_2(self): + """ This function returns a list of PICS for this test case that must be True for the test to be run""" + # In this case - there is no feature flags needed to run this test case + return ["TLSCERT.S"] + + def desc_TC_TLSCERT_2_2(self) -> str: + return "[TC-TLSCERT-2.2] ProvisionRootCertificate command basic insertion and modification" + + def steps_TC_TLSCERT_2_2(self) -> list[TestStep]: + return [ + *self.get_two_fabric_substeps(), + TestStep(2, "Populate myRootCert[] with 3 distinct, valid, self-signed, DER-encoded x509 certificates"), + TestStep(3, "CR1 sends ProvisionRootCertificate command with null CAID and Certificate set to myRootCert[0]", + "Verify returned TLSCAID value. Store the returned value as myCaid[0]."), + TestStep(4, "CR1 Reads ProvisionedRootCertificates attribute using a fabric-filtered read on Large Message-capable transport", + "Verify result is a list of TLSCertStruct with one entry. The entry should have CAID equal to myCaid[0] and Certificate equal to myRootCert[0]"), + TestStep(5, "CR1 Reads ProvisionedRootCertificates attribute using a fabric-filtered read", + "Verify result a list of TLSCertStruct with one entry. The entry should have CAID equal to myCaid[0] and Certificate not populated (null)"), + TestStep(6, "CR2 Reads ProvisionedRootCertificates attribute using a fabric-filtered read", + "Verify result is an empty list"), + TestStep(7, "CR1 sends ProvisionRootCertificate command with null CAID and Certificate set to myRootCert[0]", + test_plan_support.verify_status(Status.AlreadyExists)), + TestStep(8, "CR1 Reads ProvisionedRootCertificates attribute using a fabric-filtered read on Large Message-capable transport", + "Verify result is a list of TLSCertStruct with one entry. The entry should have CAID equal to myCaid[0] and Certificate equal to myRootCert[0]"), + TestStep(9, "CR1 sends FindRootCertificate command with null CAID", + "Verify result is a list of TLSCertStruct with one entry. The entry should have CAID equal to myCaid[0] and Certificate equal to myRootCert[0]"), + TestStep(10, "CR1 sends ProvisionRootCertificate command with CAID set to myCaid[0] and Certificate set to myRootCert[1]", + "Verify returned TLSCAID value equal to myCaid[0]"), + TestStep(11, "CR2 Reads ProvisionedRootCertificates attribute using a fabric-filtered read", + "Verify result is an empty list"), + TestStep(12, "CR1 sends FindRootCertificate command with null CAID", + "Verify result is a list of TLSCertStruct with one entry. The entry should have CAID equal to myCaid[0] and Certificate equal to myRootCert[1]"), + TestStep(13, "CR2 sends FindRootCertificate command with null CAID", + test_plan_support.verify_status(Status.NotFound)), + TestStep(14, "CR2 sends ProvisionRootCertificate command with CAID set to myCaid[0] and Certificate set to myRootCert[2]", + test_plan_support.verify_status(Status.NotFound)), + TestStep(15, "CR2 sends ProvisionRootCertificate command with null CAID and Certificate set to myRootCert[2]", + "Verify returned TLSCAID value. Store the returned value as myCaid[1]."), + TestStep(16, "CR2 sends ProvisionRootCertificate command with CAID set to myCaid[1] and Certificate set to myRootCert[2]", + test_plan_support.verify_status(Status.AlreadyExists)), + TestStep(17, "CR1 Reads ProvisionedRootCertificates attribute using a fabric-filtered read on Large Message-capable transport", + "Verify result is a list of TLSCertStruct with one entry. The entry should have CAID equal to myCaid[0] and Certificate equal to myRootCert[1]"), + TestStep(18, "CR2 Reads ProvisionedRootCertificates attribute using a fabric-filtered read on Large Message-capable transport", + "Verify result is a list of TLSCertStruct with one entry. The entry should have CAID equal to myCaid[1] and Certificate equal to myRootCert[2]"), + TestStep(19, "CR1 sends FindRootCertificate command with null CAID", + "Verify result is a list of TLSCertStruct with one entry. The entry should have CAID equal to myCaid[0] and Certificate equal to myRootCert[1]"), + TestStep(20, "CR2 sends FindRootCertificate command with null CAID", + "Verify result is a list of TLSCertStruct with one entry. The entry should have CAID equal to myCaid[1] and Certificate equal to myRootCert[2]"), + TestStep(21, "CR1 sends RemoveRootCertificate command with CAID set to myCaid[0]", + test_plan_support.verify_success()), + TestStep(22, test_plan_support.remove_fabric('CR2', 'CR1'), test_plan_support.verify_success()), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsCertificateManagement)) + async def test_TC_TLSCERT_2_2(self): + attributes = Clusters.TlsCertificateManagement.Attributes + + setup_data = await self.common_two_fabric_setup() + cr1_cmd = setup_data.cr1_cmd + cr2_cmd = setup_data.cr2_cmd + + self.step(2) + my_root_cert = [cr1_cmd.gen_cert(), cr1_cmd.gen_cert(), cr1_cmd.gen_cert()] + + self.step(3) + response = await cr1_cmd.send_provision_root_command(certificate=my_root_cert[0]) + cr1_cmd.assert_valid_caid(response.caid) + my_caid = [response.caid, None, None] + + self.step(4) + found_certs = await cr1_cmd.read_root_certs_attribute_as_map() + asserts.assert_in(response.caid, found_certs, "ProvisionedRootCertificates should contain provisioned root cert") + asserts.assert_equal(len(found_certs), 1, "Expected 1 certificate") + asserts.assert_equal(found_certs[my_caid[0]].certificate, my_root_cert[0], "Expected matching certificate detail") + + self.step(5) + # Must close session so we don't re-use large payload session + self.default_controller.ExpireSessions(self.dut_node_id) + found_certs = await cr1_cmd.read_root_certs_attribute_as_map() + asserts.assert_in(response.caid, found_certs, "ProvisionedRootCertificates should contain provisioned root cert") + asserts.assert_equal(len(found_certs), 1, "Expected 1 certificate") + asserts.assert_is_none(found_certs[my_caid[0]].certificate, "Expected no certificate over non-Large-Transport") + + self.step(6) + attribute_certs = await cr2_cmd.read_tls_cert_attribute(attributes.ProvisionedRootCertificates) + matter_asserts.assert_list(attribute_certs, "Expected empty list", max_length=0) + + self.step(7) + await cr1_cmd.send_provision_root_command(certificate=my_root_cert[0], expected_status=Status.AlreadyExists) + + self.step(8) + # Must close session so we don't re-use large payload session + self.default_controller.ExpireSessions(self.dut_node_id) + found_certs = await cr1_cmd.read_root_certs_attribute_as_map() + asserts.assert_in(response.caid, found_certs, "ProvisionedRootCertificates should contain provisioned root cert") + asserts.assert_equal(len(found_certs), 1, "Expected 1 certificate") + asserts.assert_is_none(found_certs[my_caid[0]].certificate, "Expected no certificate over non-Large-Transport") + + self.step(9) + find_response = await cr1_cmd.send_find_root_command() + asserts.assert_equal(len(find_response.certificateDetails), 1, "Expected single certificate") + asserts.assert_equal(find_response.certificateDetails[0].caid, my_caid[0]) + asserts.assert_equal(find_response.certificateDetails[0].certificate, my_root_cert[0]) + + self.step(10) + response = await cr1_cmd.send_provision_root_command(certificate=my_root_cert[1], caid=my_caid[0]) + asserts.assert_equal(response.caid, my_caid[0]) + + self.step(11) + attribute_certs = await cr2_cmd.read_tls_cert_attribute(attributes.ProvisionedRootCertificates) + matter_asserts.assert_list(attribute_certs, "Expected empty list", max_length=0) + + self.step(12) + find_response = await cr1_cmd.send_find_root_command() + asserts.assert_equal(len(find_response.certificateDetails), 1, "Expected single certificate") + asserts.assert_equal(find_response.certificateDetails[0].caid, my_caid[0]) + asserts.assert_equal(find_response.certificateDetails[0].certificate, my_root_cert[1]) + + self.step(13) + await cr2_cmd.send_find_root_command(caid=my_caid[0], expected_status=Status.NotFound) + + self.step(14) + await cr2_cmd.send_provision_root_command(certificate=my_root_cert[2], caid=my_caid[0], expected_status=Status.NotFound) + + self.step(15) + response = await cr2_cmd.send_provision_root_command(certificate=my_root_cert[2]) + cr2_cmd.assert_valid_caid(response.caid) + my_caid[1] = response.caid + + self.step(16) + await cr2_cmd.send_provision_root_command(certificate=my_root_cert[2], caid=my_caid[1], expected_status=Status.AlreadyExists) + + self.step(17) + found_certs = await cr1_cmd.read_root_certs_attribute_as_map() + asserts.assert_in(my_caid[0], found_certs, "ProvisionedRootCertificates should contain provisioned root cert") + asserts.assert_equal(len(found_certs), 1, "Expected 1 certificate") + asserts.assert_equal(found_certs[my_caid[0]].certificate, my_root_cert[1], "Expected matching certificate detail") + + self.step(18) + found_certs = await cr2_cmd.read_root_certs_attribute_as_map() + asserts.assert_in(my_caid[1], found_certs, "ProvisionedRootCertificates should contain provisioned root cert") + asserts.assert_equal(len(found_certs), 1, "Expected 1 certificate") + asserts.assert_equal(found_certs[my_caid[1]].certificate, my_root_cert[2], "Expected matching certificate detail") + + self.step(19) + find_response = await cr1_cmd.send_find_root_command() + asserts.assert_equal(len(find_response.certificateDetails), 1, "Expected single certificate") + asserts.assert_equal(find_response.certificateDetails[0].certificate, my_root_cert[1]) + asserts.assert_equal(find_response.certificateDetails[0].caid, my_caid[0]) + + self.step(20) + find_response = await cr2_cmd.send_find_root_command() + asserts.assert_equal(len(find_response.certificateDetails), 1, "Expected single certificate") + asserts.assert_equal(find_response.certificateDetails[0].certificate, my_root_cert[2]) + asserts.assert_equal(find_response.certificateDetails[0].caid, my_caid[1]) + + self.step(21) + await cr1_cmd.send_remove_root_command(caid=my_caid[0]) + + self.step(22) + await cr1_cmd.send_remove_fabric_command(cr2_cmd.fabric_index) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCERT_2_3.py b/src/python_testing/TC_TLSCERT_2_3.py new file mode 100644 index 00000000000..18342af4469 --- /dev/null +++ b/src/python_testing/TC_TLSCERT_2_3.py @@ -0,0 +1,182 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import logging + +import test_plan_support +from mobly import asserts +from TC_TLSCERT_Base import TC_TLSCERT_Base + +import matter.clusters as Clusters +from matter.ChipDeviceCtrl import TransportPayloadCapability +from matter.interaction_model import Status +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + +log = logging.getLogger(__name__) + + +class TC_TLSCERT_2_3(TC_TLSCERT_Base): + def pics_TC_TLSCERT_2_3(self): + return ["TLSCERT.S"] + + def desc_TC_TLSCERT_2_3(self) -> str: + return "[TC-TLSCERT-2.3] ProvisionRootCertificate command verification with several entries" + + def steps_TC_TLSCERT_2_3(self) -> list[TestStep]: + return [ + *self.get_two_fabric_substeps(), + TestStep(2, "CR2 reads MaxRootCertificates attribute into myMaxRootCerts."), + TestStep(3, "Populate myRootCert[] with myMaxRootCerts + 3 distinct, valid, self-signed, DER-encoded x509 certificates."), + TestStep(4, "CR1 sends ProvisionRootCertificate command with null CAID and Certificate set to myRootCert[i], for each i in [0..1].", + "DUT replies with a TLSCAID value. Store the returned value as myCaid[i]."), + TestStep(5, "CR2 sends ProvisionRootCertificate command with null CAID and Certificate set to myRootCert[i], for each i in [2..myMaxRootCerts+1].", + "DUT replies with a TLSCAID value. Store the returned value as myCaid[i]."), + TestStep(6, "CR1 reads ProvisionedRootCertificates attribute using a fabric-filtered read on Large Message-capable transport.", + "DUT replies with a list of TLSCertStruct with 2 entries. The entries should correspond to the first two entries in myRootCert and myCaid."), + TestStep(7, "CR2 reads ProvisionedRootCertificates attribute using a fabric-filtered read on Large Message-capable transport.", + "DUT replies with a list of TLSCertStruct with myMaxRootCerts entries. The entries should correspond to the entries 2 through myMaxRootCerts+1 of myRootCert and myCaid."), + TestStep(8, "CR1 sends FindRootCertificate command with null CAID.", + "DUT replies with a list of TLSCertStruct with 2 entries. The entries should correspond to the first two entries in myRootCert and myCaid."), + TestStep(9, "CR2 sends FindRootCertificate command with null CAID.", + "DUT replies with a list of TLSCertStruct with myMaxRootCerts entries. The entries should correspond to the entries 2 through myMaxRootCerts + 1 of myRootCert and myCaid."), + TestStep(10, "CR2 sends ProvisionRootCertificate command with null CAID and Certificate set to myRootCert[myMaxRootCerts+2].", + test_plan_support.verify_status(Status.ResourceExhausted)), + TestStep(11, "CR2 sends RemoveRootCertificate command with CAID set to myCaid[2].", + test_plan_support.verify_success()), + TestStep(12, "CR2 sends ProvisionRootCertificate command with null CAID and Certificate set to myRootCert[myMaxRootCerts+2].", + "DUT replies with a TLSCAID value. Store the returned value as myCaid[myMaxRootCerts+2]."), + TestStep(13, "CR2 reads ProvisionedRootCertificates attribute using a fabric-filtered read on Large Message-capable transport.", + "DUT replies with a list of TLSCertStruct with myMaxRootCerts entries."), + TestStep(14, "CR2 sends FindRootCertificate command with null CAID.", + "DUT replies with a list of TLSCertStruct with myMaxRootCerts entries."), + TestStep(15, "CR2 sends ProvisionRootCertificate command with null CAID and Certificate set to myRootCert[2].", + test_plan_support.verify_status(Status.ResourceExhausted)), + TestStep(16, test_plan_support.remove_fabric('CR2', 'CR1'), test_plan_support.verify_success()), + TestStep(17, "CR1 sends ProvisionRootCertificate command with null CAID and Certificate set to myRootCert[2].", + "DUT replies with a TLSCAID value."), + TestStep(18, "CR1 sends RemoveRootCertificate command with CAID set to myCaid[i], for each i in [0..1].", + test_plan_support.verify_success()), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsCertificateManagement)) + async def test_TC_TLSCERT_2_3(self): + attributes = Clusters.TlsCertificateManagement.Attributes + + setup_data = await self.common_two_fabric_setup() + cr1_cmd = setup_data.cr1_cmd + cr2_cmd = setup_data.cr2_cmd + + self.step(2) + my_max_root_certs = await cr2_cmd.read_tls_cert_attribute(attributes.MaxRootCertificates) + + self.step(3) + my_root_cert = [cr1_cmd.gen_cert() for _ in range(my_max_root_certs + 3)] + my_caid = [None] * (my_max_root_certs + 3) + + self.step(4) + for i in range(2): + response = await cr1_cmd.send_provision_root_command(certificate=my_root_cert[i]) + cr1_cmd.assert_valid_caid(response.caid) + my_caid[i] = response.caid + + self.step(5) + log.warning(f"maximum cert {my_max_root_certs}") + for i in range(2, my_max_root_certs + 2): + log.warning(f"Root cert {i}") + response = await cr2_cmd.send_provision_root_command(certificate=my_root_cert[i]) + cr2_cmd.assert_valid_caid(response.caid) + my_caid[i] = response.caid + + self.step(6) + found_certs = await cr1_cmd.read_root_certs_attribute_as_map(TransportPayloadCapability.LARGE_PAYLOAD) + asserts.assert_equal(len(found_certs), 2, "Expected 2 certificates for CR1") + for i in range(2): + asserts.assert_in(my_caid[i], found_certs) + asserts.assert_equal(found_certs[my_caid[i]].certificate, my_root_cert[i]) + + self.step(7) + found_certs = await cr2_cmd.read_root_certs_attribute_as_map(TransportPayloadCapability.LARGE_PAYLOAD) + asserts.assert_equal(len(found_certs), my_max_root_certs, "Expected myMaxRootCerts certificates for CR2") + for i in range(2, my_max_root_certs + 2): + asserts.assert_in(my_caid[i], found_certs) + asserts.assert_equal(found_certs[my_caid[i]].certificate, my_root_cert[i]) + + self.step(8) + find_response = await cr1_cmd.send_find_root_command() + asserts.assert_equal(len(find_response.certificateDetails), 2, "Expected 2 certificates for CR1") + + self.step(9) + find_response = await cr2_cmd.send_find_root_command() + asserts.assert_equal(len(find_response.certificateDetails), my_max_root_certs, + "Expected myMaxRootCerts certificates for CR2") + + self.step(10) + await cr2_cmd.send_provision_root_command(certificate=my_root_cert[my_max_root_certs + 2], expected_status=Status.ResourceExhausted) + + self.step(11) + await cr2_cmd.send_remove_root_command(caid=my_caid[2]) + + self.step(12) + response = await cr2_cmd.send_provision_root_command(certificate=my_root_cert[my_max_root_certs + 2]) + cr2_cmd.assert_valid_caid(response.caid) + my_caid[my_max_root_certs + 2] = response.caid + + self.step(13) + found_certs = await cr2_cmd.read_root_certs_attribute_as_map(TransportPayloadCapability.LARGE_PAYLOAD) + asserts.assert_equal(len(found_certs), my_max_root_certs, "Expected myMaxRootCerts certificates for CR2") + + self.step(14) + find_response = await cr2_cmd.send_find_root_command() + asserts.assert_equal(len(find_response.certificateDetails), my_max_root_certs, + "Expected myMaxRootCerts certificates for CR2") + + self.step(15) + await cr2_cmd.send_provision_root_command(certificate=my_root_cert[2], expected_status=Status.ResourceExhausted) + + self.step(16) + await cr1_cmd.send_remove_fabric_command(cr2_cmd.fabric_index) + + self.step(17) + response = await cr1_cmd.send_provision_root_command(certificate=my_root_cert[2]) + cr1_cmd.assert_valid_caid(response.caid) + + self.step(18) + for i in range(2): + await cr1_cmd.send_remove_root_command(caid=my_caid[i]) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCERT_2_4.py b/src/python_testing/TC_TLSCERT_2_4.py new file mode 100644 index 00000000000..3e73944c3a0 --- /dev/null +++ b/src/python_testing/TC_TLSCERT_2_4.py @@ -0,0 +1,93 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import test_plan_support +from mobly import asserts +from TC_TLSCERT_Base import TC_TLSCERT_Base + +import matter.clusters as Clusters +from matter.interaction_model import Status +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCERT_2_4(TC_TLSCERT_Base): + def pics_TC_TLSCERT_2_4(self): + return ["TLSCERT.S"] + + def desc_TC_TLSCERT_2_4(self) -> str: + return "[TC-TLSCERT-2.4] ProvisionRootCertificate command verification with bad arguments" + + def steps_TC_TLSCERT_2_4(self) -> list[TestStep]: + return [ + *self.get_common_substeps(), + TestStep(2, + "Set myBigRootCert to a valid DER encoding of a valid, self-signed x509 certificate. The certificate should be large enough that the DER encoding is larger than 3000 octets."), + TestStep(3, "Set myBadRootCert to an octstr under 3000 that is not a valid DER encoding."), + TestStep(4, "Set myRootCert to a valid, self-signed, DER-encoded x509 certificate."), + TestStep(5, "CR1 sends ProvisionRootCertificate command with null CAID and Certificate set to myBigRootCert.", + test_plan_support.verify_status(Status.ConstraintError)), + TestStep(6, "CR1 sends ProvisionRootCertificate command with null CAID and Certificate set to myBadRootCert.", + test_plan_support.verify_status(Status.DynamicConstraintError)), + TestStep(7, "CR1 sends ProvisionRootCertificate command with CAID set to 10 and Certificate set to myRootCert.", + test_plan_support.verify_status(Status.NotFound)), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsCertificateManagement)) + async def test_TC_TLSCERT_2_4(self): + cr1_cmd = await self.common_setup() + + self.step(2) + my_big_root_cert = cr1_cmd.gen_cert_with_key(signer=cr1_cmd.get_key(), builder_lambda=self.pad_out_certificate) + asserts.assert_greater(len(my_big_root_cert), 3000) + + self.step(3) + my_bad_root_cert = b"not a cert" + + self.step(4) + my_root_cert = cr1_cmd.gen_cert() + + self.step(5) + await cr1_cmd.send_provision_root_command(certificate=my_big_root_cert, expected_status=Status.ConstraintError) + + self.step(6) + await cr1_cmd.send_provision_root_command(certificate=my_bad_root_cert, expected_status=Status.DynamicConstraintError) + + self.step(7) + await cr1_cmd.send_provision_root_command(caid=10, certificate=my_root_cert, expected_status=Status.NotFound) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCERT_2_5.py b/src/python_testing/TC_TLSCERT_2_5.py new file mode 100644 index 00000000000..800a20004b8 --- /dev/null +++ b/src/python_testing/TC_TLSCERT_2_5.py @@ -0,0 +1,114 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import test_plan_support +from mobly import asserts +from TC_TLSCERT_Base import TC_TLSCERT_Base + +import matter.clusters as Clusters +from matter.interaction_model import Status +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCERT_2_5(TC_TLSCERT_Base): + def pics_TC_TLSCERT_2_5(self): + return ["TLSCERT.S"] + + def desc_TC_TLSCERT_2_5(self) -> str: + return "[TC-TLSCERT-2.5] FindRootCertificate command verification with bad arguments" + + def steps_TC_TLSCERT_2_5(self) -> list[TestStep]: + return [ + *self.get_two_fabric_substeps(), + TestStep(2, "Set myRootCert to a valid, self-signed, DER-encoded x509 certificate."), + TestStep(3, "CR1 sends FindRootCertificate command with CAID set to null.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(4, "CR1 sends ProvisionRootCertificate command with null CAID and Certificate set to myRootCert.", + "DUT replies with a TLSCAID value. Store the returned value as myCaid."), + TestStep(5, "CR1 sends FindRootCertificate command with CAID set to myCaid.", + "DUT replies with a list of TLSCertStruct with one entry. The entry should correspond to myRootCert and myCaid."), + TestStep(6, "CR1 sends FindRootCertificate command with CAID set to myCaid + 1.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(7, "CR2 sends FindRootCertificate command with CAID set to myCaid.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(8, "CR2 sends FindRootCertificate command with CAID set to null.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(9, "CR1 sends RemoveRootCertificate command with CAID set to myCaid.", + test_plan_support.verify_success()), + TestStep(10, test_plan_support.remove_fabric('CR2', 'CR1'), test_plan_support.verify_success()), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsCertificateManagement)) + async def test_TC_TLSCERT_2_5(self): + setup_data = await self.common_two_fabric_setup() + cr1_cmd = setup_data.cr1_cmd + cr2_cmd = setup_data.cr2_cmd + + self.step(2) + my_root_cert = cr1_cmd.gen_cert() + + self.step(3) + await cr1_cmd.send_find_root_command(expected_status=Status.NotFound) + + self.step(4) + response = await cr1_cmd.send_provision_root_command(certificate=my_root_cert) + cr1_cmd.assert_valid_caid(response.caid) + my_caid = response.caid + + self.step(5) + find_response = await cr1_cmd.send_find_root_command(caid=my_caid) + asserts.assert_equal(len(find_response.certificateDetails), 1) + asserts.assert_equal(find_response.certificateDetails[0].caid, my_caid) + asserts.assert_equal(find_response.certificateDetails[0].certificate, my_root_cert) + + self.step(6) + await cr1_cmd.send_find_root_command(caid=my_caid + 1, expected_status=Status.NotFound) + + self.step(7) + await cr2_cmd.send_find_root_command(caid=my_caid, expected_status=Status.NotFound) + + self.step(8) + await cr2_cmd.send_find_root_command(expected_status=Status.NotFound) + + self.step(9) + await cr1_cmd.send_remove_root_command(caid=my_caid) + + self.step(10) + await cr1_cmd.send_remove_fabric_command(cr2_cmd.fabric_index) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCERT_2_6.py b/src/python_testing/TC_TLSCERT_2_6.py new file mode 100644 index 00000000000..26ac9bbed4b --- /dev/null +++ b/src/python_testing/TC_TLSCERT_2_6.py @@ -0,0 +1,147 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import test_plan_support +from mobly import asserts +from TC_TLSCERT_Base import TC_TLSCERT_Base + +import matter.clusters as Clusters +from matter.interaction_model import Status +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCERT_2_6(TC_TLSCERT_Base): + def pics_TC_TLSCERT_2_6(self): + return ["TLSCERT.S"] + + def desc_TC_TLSCERT_2_6(self) -> str: + return "[TC-TLSCERT-2.6] LookupRootCertificate command verification" + + def steps_TC_TLSCERT_2_6(self) -> list[TestStep]: + return [ + *self.get_two_fabric_substeps(), + TestStep(2, "Populate myRootCert[] with 3 distinct, valid, self-signed, DER-encoded x509 certificates."), + TestStep(3, "Populate myRootCertFingerprint[] with the fingerprints corresponding to myRootCert[]."), + TestStep(4, "Set myBigFingerprint to myRootCertFingerprint[0] concatenated with enough characters to exceed 64."), + TestStep(5, "CR1 sends LookupRootCertificate command with Fingerprint set to the empty octstr.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(6, "CR1 sends LookupRootCertificate command with Fingerprint set to myRootCertFingerprint[0].", + test_plan_support.verify_status(Status.NotFound)), + TestStep(7, "CR1 sends ProvisionRootCertificate command with null CAID and Certificate set to myRootCert[i], for each i in [0..1].", + "DUT replies with a TLSCAID value. Store the returned value as myCaid[i]."), + TestStep(8, "CR2 sends ProvisionRootCertificate command with null CAID and Certificate set to myRootCert[2].", + "DUT replies with a TLSCAID value. Store the returned value as myCaid[2]."), + TestStep(9, "CR1 sends LookupRootCertificate command with Fingerprint set to myRootCertFingerprint[0].", + "DUT replies with a TLSCAID value equal to myCaid[0]."), + TestStep(10, "CR1 sends LookupRootCertificate command with Fingerprint set to myRootCertFingerprint[1].", + "DUT replies with a TLSCAID value equal to myCaid[1]."), + TestStep(11, "CR1 sends LookupRootCertificate command with Fingerprint set to myRootCertFingerprint[2].", + test_plan_support.verify_status(Status.NotFound)), + TestStep(12, "CR2 sends LookupRootCertificate command with Fingerprint set to myRootCertFingerprint[2].", + "DUT replies with a TLSCAID value equal to myCaid[2]."), + TestStep(13, "CR1 sends LookupRootCertificate command with Fingerprint set to myBigFingerprint.", + test_plan_support.verify_status(Status.ConstraintError)), + TestStep(14, "CR1 sends RemoveRootCertificate command with CAID set to myCaid[i], for each i in [0..1].", + test_plan_support.verify_success()), + TestStep(15, "CR2 sends RemoveRootCertificate command with CAID set to myCaid[2].", + test_plan_support.verify_success()), + TestStep(16, test_plan_support.remove_fabric('CR2', 'CR1'), test_plan_support.verify_success()), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsCertificateManagement)) + async def test_TC_TLSCERT_2_6(self): + setup_data = await self.common_two_fabric_setup() + cr1_cmd = setup_data.cr1_cmd + cr2_cmd = setup_data.cr2_cmd + + self.step(2) + my_root_cert = [cr1_cmd.gen_cert() for _ in range(3)] + my_caid = [None, None, None] + + self.step(3) + my_root_cert_fingerprint = [cr1_cmd.get_fingerprint(cert) for cert in my_root_cert] + + self.step(4) + my_big_fingerprint = my_root_cert_fingerprint[0] + b'\x00' * (65 - len(my_root_cert_fingerprint[0])) + + self.step(5) + await cr1_cmd.send_lookup_root_command(fingerprint=b'', expected_status=Status.NotFound) + + self.step(6) + await cr1_cmd.send_lookup_root_command(fingerprint=my_root_cert_fingerprint[0], expected_status=Status.NotFound) + + self.step(7) + for i in range(2): + response = await cr1_cmd.send_provision_root_command(certificate=my_root_cert[i]) + cr1_cmd.assert_valid_caid(response.caid) + my_caid[i] = response.caid + + self.step(8) + response = await cr2_cmd.send_provision_root_command(certificate=my_root_cert[2]) + cr2_cmd.assert_valid_caid(response.caid) + my_caid[2] = response.caid + + self.step(9) + response = await cr1_cmd.send_lookup_root_command(fingerprint=my_root_cert_fingerprint[0]) + asserts.assert_equal(response.caid, my_caid[0]) + + self.step(10) + response = await cr1_cmd.send_lookup_root_command(fingerprint=my_root_cert_fingerprint[1]) + asserts.assert_equal(response.caid, my_caid[1]) + + self.step(11) + await cr1_cmd.send_lookup_root_command(fingerprint=my_root_cert_fingerprint[2], expected_status=Status.NotFound) + + self.step(12) + response = await cr2_cmd.send_lookup_root_command(fingerprint=my_root_cert_fingerprint[2]) + asserts.assert_equal(response.caid, my_caid[2]) + + self.step(13) + await cr1_cmd.send_lookup_root_command(fingerprint=my_big_fingerprint, expected_status=Status.ConstraintError) + + self.step(14) + for i in range(2): + await cr1_cmd.send_remove_root_command(caid=my_caid[i]) + + self.step(15) + await cr2_cmd.send_remove_root_command(caid=my_caid[2]) + + self.step(16) + await cr1_cmd.send_remove_fabric_command(cr2_cmd.fabric_index) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCERT_2_7.py b/src/python_testing/TC_TLSCERT_2_7.py new file mode 100644 index 00000000000..d58e20372c3 --- /dev/null +++ b/src/python_testing/TC_TLSCERT_2_7.py @@ -0,0 +1,121 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import test_plan_support +from TC_TLSCERT_Base import TC_TLSCERT_Base + +import matter.clusters as Clusters +from matter.interaction_model import Status +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCERT_2_7(TC_TLSCERT_Base): + def pics_TC_TLSCERT_2_7(self): + return ["TLSCERT.S", "TLSCLIENT.S"] + + def desc_TC_TLSCERT_2_7(self) -> str: + return "[TC-TLSCERT-2.7] RemoveRootCertificate command verification" + + def steps_TC_TLSCERT_2_7(self) -> list[TestStep]: + return [ + *self.get_two_fabric_substeps(), + TestStep(2, "Set myRootCert to a valid, self-signed, DER-encoded x509 certificate."), + TestStep(3, "CR1 sends RemoveRootCertificate command with CAID set to 1.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(4, "CR1 sends ProvisionRootCertificate command with null CAID and Certificate set to myRootCert.", + "DUT replies with a TLSCAID value. Store the returned value as myCaid."), + TestStep(5, "CR2 sends RemoveRootCertificate command with CAID set to myCaid.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(6, "CR1 sends ProvisionEndpoint command with valid Hostname, Port, CAID myCaid and null EndpointID.", + "DUT replies with a TLSEndpointID value. Store the returned value as myEndpoint."), + TestStep(7, "CR1 sends RemoveRootCertificate command with CAID set to myCaid.", + test_plan_support.verify_status(Status.InvalidInState)), + TestStep(8, "CR1 sends RemoveEndpoint command with EndpointID set to myEndpoint.", + test_plan_support.verify_success()), + TestStep(9, "CR1 sends RemoveRootCertificate command with CAID set to myCaid.", + test_plan_support.verify_success()), + TestStep(10, "CR1 sends FindRootCertificate command with CAID set to myCaid.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(11, "CR1 sends RemoveRootCertificate command with CAID set to myCaid.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(12, test_plan_support.remove_fabric('CR2', 'CR1'), test_plan_support.verify_success()), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsCertificateManagement)) + async def test_TC_TLSCERT_2_7(self): + setup_data = await self.common_two_fabric_setup() + cr1_cmd = setup_data.cr1_cmd + cr2_cmd = setup_data.cr2_cmd + + self.step(2) + my_root_cert = cr1_cmd.gen_cert() + + self.step(3) + await cr1_cmd.send_remove_root_command(caid=1, expected_status=Status.NotFound) + + self.step(4) + response = await cr1_cmd.send_provision_root_command(certificate=my_root_cert) + cr1_cmd.assert_valid_caid(response.caid) + my_caid = response.caid + + self.step(5) + await cr2_cmd.send_remove_root_command(caid=my_caid, expected_status=Status.NotFound) + + self.step(6) + endpoint_response = await cr1_cmd.send_provision_tls_endpoint_command(hostname=b"my_hostname", port=1000, caid=my_caid) + my_endpoint = endpoint_response.endpointID + + self.step(7) + await cr1_cmd.send_remove_root_command(caid=my_caid, expected_status=Status.InvalidInState) + + self.step(8) + await cr1_cmd.send_remove_tls_endpoint_command(endpoint_id=my_endpoint) + + self.step(9) + await cr1_cmd.send_remove_root_command(caid=my_caid) + + self.step(10) + await cr1_cmd.send_find_root_command(caid=my_caid, expected_status=Status.NotFound) + + self.step(11) + await cr1_cmd.send_remove_root_command(caid=my_caid, expected_status=Status.NotFound) + + self.step(12) + await cr1_cmd.send_remove_fabric_command(cr2_cmd.fabric_index) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCERT_2_8.py b/src/python_testing/TC_TLSCERT_2_8.py new file mode 100644 index 00000000000..3deb7318e78 --- /dev/null +++ b/src/python_testing/TC_TLSCERT_2_8.py @@ -0,0 +1,169 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import random + +import test_plan_support +from mobly import asserts +from TC_TLSCERT_Base import TC_TLSCERT_Base + +import matter.clusters as Clusters +from matter.ChipDeviceCtrl import TransportPayloadCapability +from matter.clusters.Types import NullValue +from matter.interaction_model import Status +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCERT_2_8(TC_TLSCERT_Base): + def pics_TC_TLSCERT_2_8(self): + return ["TLSCERT.S"] + + def desc_TC_TLSCERT_2_8(self) -> str: + return "[TC-TLSCERT-2.8] ClientCSR command verification" + + def steps_TC_TLSCERT_2_8(self) -> list[TestStep]: + return [ + *self.get_two_fabric_substeps(), + TestStep(2, "CR2 reads MaxClientCertificates attribute into myMaxClientCerts."), + TestStep(3, "Populate myNonce[] with myMaxClientCerts+1 distinct, random 32-octet values."), + TestStep(4, "Set myBigNonce to a value exceeding 32 octets."), + TestStep(5, "CR1 sends ClientCSR command with Nonce set to myBigNonce.", + test_plan_support.verify_status(Status.ConstraintError)), + TestStep(6, "CR1 sends ClientCSR command with Nonce set to myNonce[0].", + "DUT replies with CCDID, CSR and Nonce. Store TLSCCDID in myCcdid[0]."), + TestStep(7, "CR2 sends ClientCSR command with Nonce set to myNonce[i], for each i in [1..myMaxClientCerts].", + "DUT replies with CCDID, CSR and Nonce. Store TLSCCDID in myCcdid[i]."), + TestStep(8, "CR1 reads ProvisionedClientCertificates attribute using a fabric-filtered read.", + "DUT replies with a list of TLSClientCertificateDetailStruct with one entry for myCcdid[0]."), + TestStep(9, "CR2 reads ProvisionedClientCertificates attribute using a fabric-filtered read.", + "DUT replies with a list of TLSClientCertificateDetailStruct with myMaxClientCerts entries."), + TestStep(10, "CR2 sends ClientCSR command with Nonce set to myNonce[myMaxClientCerts].", + test_plan_support.verify_status(Status.ResourceExhausted)), + TestStep(11, "CR2 sends RemoveClientCertificate command with CCDID set to myCcdid[1].", + test_plan_support.verify_success()), + TestStep(12, "CR2 sends ClientCSR command with Nonce set to myNonce[myMaxClientCerts].", + "DUT replies with CCDID, CSR and Nonce."), + TestStep(13, "CR2 reads ProvisionedClientCertificates attribute.", + "DUT replies with a list of TLSClientCertificateDetailStruct with myMaxClientCerts entries."), + TestStep(14, test_plan_support.remove_fabric('CR2', 'CR1'), test_plan_support.verify_success()), + TestStep(15, "CR1 sends RemoveClientCertificate command with CCDID set to myCcdid[0].", + test_plan_support.verify_success()), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsCertificateManagement)) + async def test_TC_TLSCERT_2_8(self): + attributes = Clusters.TlsCertificateManagement.Attributes + + setup_data = await self.common_two_fabric_setup() + cr1_cmd = setup_data.cr1_cmd + cr2_cmd = setup_data.cr2_cmd + + self.step(2) + my_max_client_certs = await cr2_cmd.read_tls_cert_attribute(attributes.MaxClientCertificates) + + self.step(3) + my_nonce = [random.randbytes(32) for _ in range(my_max_client_certs + 1)] + my_ccdid = [None] * (my_max_client_certs + 2) + + self.step(4) + my_big_nonce = random.randbytes(33) + + self.step(5) + await cr1_cmd.send_csr_command(nonce=my_big_nonce, expected_status=Status.ConstraintError) + + self.step(6) + response = await cr1_cmd.send_csr_command(nonce=my_nonce[0]) + cr1_cmd.assert_valid_ccdid(response.ccdid) + cr1_cmd.assert_valid_csr(response, my_nonce[0]) + my_ccdid[0] = response.ccdid + + self.step(7) + for i in range(1, my_max_client_certs + 1): + response = await cr2_cmd.send_csr_command(nonce=my_nonce[i]) + cr2_cmd.assert_valid_ccdid(response.ccdid) + cr1_cmd.assert_valid_csr(response, my_nonce[i]) + my_ccdid[i] = response.ccdid + + self.step(8) + client_certs = await cr1_cmd.read_client_certs_attribute_as_map(TransportPayloadCapability.LARGE_PAYLOAD) + asserts.assert_equal(len(client_certs), 1) + asserts.assert_in(my_ccdid[0], client_certs) + asserts.assert_equal(client_certs[my_ccdid[0]].clientCertificate, NullValue, + "Expected no certificate for unprovisioned certificate") + asserts.assert_equal(len(client_certs[my_ccdid[0]].intermediateCertificates), 0, + "Expected no intermediate certificates for unprovisioned certificate") + + self.step(9) + client_certs = await cr2_cmd.read_client_certs_attribute_as_map(TransportPayloadCapability.LARGE_PAYLOAD) + asserts.assert_equal(len(client_certs), my_max_client_certs) + for i in range(1, my_max_client_certs + 1): + asserts.assert_in(my_ccdid[i], client_certs) + asserts.assert_equal(client_certs[my_ccdid[i]].clientCertificate, NullValue, + "Expected no certificate for unprovisioned certificate") + asserts.assert_equal(len(client_certs[my_ccdid[i]].intermediateCertificates), 0, + "Expected no intermediate certificates for unprovisioned certificate") + + self.step(10) + await cr2_cmd.send_csr_command(nonce=my_nonce[my_max_client_certs], expected_status=Status.ResourceExhausted) + + self.step(11) + await cr2_cmd.send_remove_client_command(ccdid=my_ccdid[1]) + + self.step(12) + response = await cr2_cmd.send_csr_command(nonce=my_nonce[my_max_client_certs]) + cr2_cmd.assert_valid_ccdid(response.ccdid) + my_ccdid[my_max_client_certs + 1] = response.ccdid + cr1_cmd.assert_valid_csr(response, my_nonce[my_max_client_certs]) + + self.step(13) + client_certs = await cr2_cmd.read_client_certs_attribute_as_map() + asserts.assert_equal(len(client_certs), my_max_client_certs) + for i in range(2, my_max_client_certs + 2): + asserts.assert_in(my_ccdid[i], client_certs) + asserts.assert_equal(client_certs[my_ccdid[i]].clientCertificate, NullValue, + "Expected no certificate for unprovisioned certificate") + asserts.assert_equal(len(client_certs[my_ccdid[i]].intermediateCertificates), 0, + "Expected no intermediate certificates for unprovisioned certificate") + + self.step(14) + await cr1_cmd.send_remove_fabric_command(cr2_cmd.fabric_index) + + self.step(15) + await cr1_cmd.send_remove_client_command(ccdid=my_ccdid[0]) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCERT_2_9.py b/src/python_testing/TC_TLSCERT_2_9.py new file mode 100644 index 00000000000..8d737981d9c --- /dev/null +++ b/src/python_testing/TC_TLSCERT_2_9.py @@ -0,0 +1,246 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import random + +import test_plan_support +from mobly import asserts +from TC_TLSCERT_Base import TC_TLSCERT_Base + +import matter.clusters as Clusters +from matter.ChipDeviceCtrl import TransportPayloadCapability +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCERT_2_9(TC_TLSCERT_Base): + def desc_TC_TLSCERT_2_9(self) -> str: + return "[TC-TLSCERT-2.9] ProvisionClientCertificate command verification" + + def pics_TC_TLSCERT_2_9(self): + """ This function returns a list of PICS for this test case that must be True for the test to be run""" + # In this case - there is no feature flags needed to run this test case + return ["TLSCERT.S"] + + def steps_TC_TLSCERT_2_9(self) -> list[TestStep]: + return [ + *self.get_two_fabric_substeps(), + TestStep(2, "Populate my_nonce[] with 4 distinct, random 32-octet values"), + TestStep(3, "CR1 sends ClientCSR command with Nonce set to my_nonce[i], for each i in [0..1]", + "Verify the fields CCDID, CSR and Nonce with types TLSCCDID, octstr and octstr respectively. Store TLSCCDID in my_ccdid[i] and CSR in my_csr[i]."), + TestStep(4, "CR2 sends sends ClientCSR command with Nonce set to my_nonce[2]", + "Verify the fields CCDID, CSR and Nonce with types TLSCCDID, octstr and octstr respectively. Store TLSCCDID in my_ccdid[2] and CSR in my_csr[2]."), + TestStep(5, "Populate my_intermediate_certs_1 with 10 DER-encoded x509 certificates that form a certificate chain up to (but not including) a root"), + TestStep(6, "Populate my_intermediate_certs_2 with 1 DER-encoded x509 certificates that form a certificate chain up to (but not including) a root"), + TestStep(7, "Populate my_client_cert[] with 3 distinct, valid, DER-encoded x509 certificates using each respective public key from my_csr[i], signed by signed by [a root, my_intermediate_certs_1[0], my_intermediate_certs_2[0]]"), + TestStep( + 8, "CR1 sends ProvisionClientCertificate command with CCDID set to my_ccdid[0] and ClientCertificate set to my_client_cert[0]", test_plan_support.verify_success()), + TestStep( + 9, "CR1 sends ProvisionClientCertificate command with CCDID set to my_ccdid[1], ClientCertificate set to my_client_cert[1], and IntermediateCertificates set to my_intermediate_certs_1", test_plan_support.verify_success()), + TestStep( + 10, "CR2 sends ProvisionClientCertificate command with CCDID set to my_ccdid[2], ClientCertificate set to my_client_cert[2], and IntermediateCertificates set to my_intermediate_certs_2", test_plan_support.verify_success()), + TestStep(11, "CR1 reads ProvisionedClientCertificates attribute using a fabric-filtered read on Large Message-capable transport", + "Verify a list of TLSClientCertificateDetailStruct with two entries corresponding to my_ccdid[0..1]. The ClientCertificate value should be set to my_client_cert[0..1] and IntermediateCertificates set to my_intermediate_certs_1 for my my_ccdid[1]."), + TestStep(12, "CR2 reads ProvisionedClientCertificates attribute using a fabric-filtered read on Large Message-capable transport", + "Verify a list of TLSClientCertificateDetailStruct with one entry corresponding to my_ccdid[2]. The ClientCertificate value should be set to my_client_cert[2] and IntermediateCertificates set to my_intermediate_certs_2."), + TestStep(13, "CR1 reads ProvisionedClientCertificates attribute using a fabric-filtered read", + "Verify a list of TLSClientCertificateDetailStruct with two entries corresponding to my_ccdid[0..1]. The ClientCertificate and IntermediateCertificates values should not be populated (non-present)."), + TestStep(14, "CR1 sends FindClientCertificate command with null CCDID", + "Verify a list of TLSClientCertificateDetailStruct with two entries. The entries should correspond to my_client_cert[0..1]"), + TestStep(15, "CR2 sends FindClientCertificate command with null CCDID", + "Verify a list of TLSClientCertificateDetailStruct with one entry. The entry should correspond to my_client_cert[2]"), + TestStep(16, "CR1 sends ClientCSR command with CCDID set to my_ccdid[0] and Nonce set to my_nonce[3]", + "the fields CCDID, CSR and Nonce with types TLSCCDID, octstr and octstr respectively. CCDID should equal my_ccdid[0]. The public key of the resulting CSR should be equal to the public key in my_csr[0]. NonceSignature should be a signature of my_nonce[3] using public key in CSR"), + TestStep( + 17, "CR1 sends ProvisionClientCertificate command with CCDID set to my_ccdid[0] and ClientCertificateDetails set to my_client_cert[3]", test_plan_support.verify_success()), + TestStep(18, "CR1 reads ProvisionedClientCertificates attribute using a fabric-filtered read on Large Message-capable transport", + "Verify a list of TLSClientCertificateDetailStruct with two entries. The entries should correspond to my_client_cert[0,3]"), + TestStep(19, "CR2 reads ProvisionedClientCertificates attribute using a fabric-filtered read on Large Message-capable transport", + "Verify a list of TLSClientCertificateDetailStruct with one entry. The entry should correspond to my_client_cert[2]"), + TestStep(20, "CR1 sends FindClientCertificate command with CCDID set to my_ccdid[0]", + "Verify a list of TLSClientCertificateDetailStruct with one entry. The entry should correspond to my_client_cert[3]"), + TestStep(21, "CR2 sends FindClientCertificate command with CCDID set to my_ccdid[2]", + "Verify a list of TLSClientCertificateDetailStruct with one entry. The entry should correspond to my_client_cert[2]"), + TestStep(22, "CR1 sends RemoveClientCertificate command with CCDID set to my_ccdid[i], for each i in [0..1]", + test_plan_support.verify_success()), + TestStep(23, test_plan_support.remove_fabric('CR2', 'CR1'), test_plan_support.verify_success()), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsCertificateManagement)) + async def test_TC_TLSCERT_2_9(self): + + setup_data = await self.common_two_fabric_setup() + cr1_cmd = setup_data.cr1_cmd + cr2_cmd = setup_data.cr2_cmd + + self.step(2) + my_nonce = [random.randbytes(32), random.randbytes(32), random.randbytes(32), random.randbytes(32)] + my_ccdid = [None, None, None] + my_csr = [None, None, None, None] + + self.step(3) + for i in range(2): + response = await cr1_cmd.send_csr_command(nonce=my_nonce[i]) + cr1_cmd.assert_valid_ccdid(response.ccdid) + my_ccdid[i] = response.ccdid + my_csr[i] = cr1_cmd.assert_valid_csr(response, my_nonce[i]) + if i > 0: + asserts.assert_not_equal(my_ccdid[i-1], my_ccdid[i], "CCDID should be unique") + + self.step(4) + response = await cr2_cmd.send_csr_command(nonce=my_nonce[2]) + cr2_cmd.assert_valid_ccdid(response.ccdid) + my_ccdid[2] = response.ccdid + my_csr[2] = cr2_cmd.assert_valid_csr(response, my_nonce[2]) + + self.step(5) + # Don't have to use the same root, but may as well + root = cr1_cmd.get_key() + certs_with_key_1 = cr1_cmd.gen_cert_chain(root, 10) + my_intermediate_certs_1 = [x.cert for x in certs_with_key_1] + + self.step(6) + certs_with_key_2 = cr1_cmd.gen_cert_chain(root, 1) + my_intermediate_certs_2 = [x.cert for x in certs_with_key_2] + signers = [root, certs_with_key_1[0].key, certs_with_key_2[0].key] + + self.step(7) + my_client_cert = [None, None, None, None] + for i in range(3): + my_client_cert[i] = cr1_cmd.gen_cert_with_key(signers[i], public_key=my_csr[i].public_key(), subject=my_csr[i].subject) + + self.step(8) + await cr1_cmd.send_provision_client_command(ccdid=my_ccdid[0], certificate=my_client_cert[0]) + + self.step(9) + await cr1_cmd.send_provision_client_command(ccdid=my_ccdid[1], certificate=my_client_cert[1], intermediates=my_intermediate_certs_1) + + self.step(10) + await cr2_cmd.send_provision_client_command(ccdid=my_ccdid[2], certificate=my_client_cert[2], intermediates=my_intermediate_certs_2) + + self.step(11) + found_certs = await cr1_cmd.read_client_certs_attribute_as_map(TransportPayloadCapability.LARGE_PAYLOAD) + asserts.assert_equal(len(found_certs), 2, "Expected 2 certificates") + for i in range(2): + asserts.assert_in(my_ccdid[i], found_certs, "ProvisionedClientCertificates should contain provisioned client cert") + asserts.assert_equal(found_certs[my_ccdid[i]].clientCertificate, + my_client_cert[i], "Expected matching certificate detail") + asserts.assert_equal(found_certs[my_ccdid[1]].intermediateCertificates, + my_intermediate_certs_1, "Expected matching certificate detail") + + self.step(12) + found_certs = await cr2_cmd.read_client_certs_attribute_as_map(TransportPayloadCapability.LARGE_PAYLOAD) + asserts.assert_equal(len(found_certs), 1, "Expected 1 certificate") + asserts.assert_in(my_ccdid[2], found_certs, "ProvisionedClientCertificates should contain provisioned client cert") + asserts.assert_equal(found_certs[my_ccdid[2]].clientCertificate, my_client_cert[2], "Expected matching certificate detail") + asserts.assert_equal(found_certs[my_ccdid[2]].intermediateCertificates, + my_intermediate_certs_2, "Expected matching certificate detail") + + self.step(13) + # Must close session so we don't re-use large payload session + self.default_controller.ExpireSessions(self.dut_node_id) + found_certs = await cr1_cmd.read_client_certs_attribute_as_map() + asserts.assert_equal(len(found_certs), 2, "Expected 2 certificates") + for i in range(2): + asserts.assert_in(my_ccdid[i], found_certs, "ProvisionedClientCertificates should contain provisioned client cert") + asserts.assert_is_none(found_certs[my_ccdid[i]].clientCertificate, "Expected no certificate over non-Large-Transport") + + self.step(14) + found_certs = await cr1_cmd.send_find_client_command_as_map() + asserts.assert_equal(len(found_certs), 2, "Expected 2 certificates") + for i in range(2): + asserts.assert_in(my_ccdid[i], found_certs, "FindClientCertificate should contain provisioned client cert") + asserts.assert_equal(found_certs[my_ccdid[i]].clientCertificate, + my_client_cert[i], "Expected matching certificate detail") + asserts.assert_equal(found_certs[my_ccdid[1]].intermediateCertificates, + my_intermediate_certs_1, "Expected matching certificate detail") + + self.step(15) + found_certs = await cr2_cmd.send_find_client_command_as_map() + asserts.assert_equal(len(found_certs), 1, "Expected 1 certificate") + asserts.assert_in(my_ccdid[2], found_certs, "FindClientCertificate should contain provisioned client cert") + asserts.assert_equal(found_certs[my_ccdid[2]].clientCertificate, my_client_cert[2], "Expected matching certificate detail") + asserts.assert_equal(found_certs[my_ccdid[2]].intermediateCertificates, + my_intermediate_certs_2, "Expected matching certificate detail") + + self.step(16) + response = await cr1_cmd.send_csr_command(ccdid=my_ccdid[0], nonce=my_nonce[3]) + cr1_cmd.assert_valid_ccdid(response.ccdid) + asserts.assert_equal(response.ccdid, my_ccdid[0], "Expected same ID") + cr1_cmd.assert_valid_csr(response, my_nonce[3]) + my_client_cert[3] = cr1_cmd.gen_cert_with_key(root, public_key=my_csr[0].public_key(), subject=my_csr[0].subject) + + self.step(17) + await cr1_cmd.send_provision_client_command(ccdid=my_ccdid[0], certificate=my_client_cert[3]) + + self.step(18) + found_certs = await cr1_cmd.read_client_certs_attribute_as_map(TransportPayloadCapability.LARGE_PAYLOAD) + asserts.assert_equal(len(found_certs), 2, "Expected 2 certificates") + expected_certs = [my_client_cert[3], my_client_cert[1]] + for i in range(2): + asserts.assert_in(my_ccdid[i], found_certs, "ProvisionedClientCertificates should contain provisioned client cert") + asserts.assert_equal(found_certs[my_ccdid[i]].clientCertificate, + expected_certs[i], "Expected matching certificate detail") + + self.step(19) + found_certs = await cr2_cmd.read_client_certs_attribute_as_map(TransportPayloadCapability.LARGE_PAYLOAD) + asserts.assert_equal(len(found_certs), 1, "Expected 1 certificate") + asserts.assert_in(my_ccdid[2], found_certs, "ProvisionedClientCertificates should contain provisioned client cert") + asserts.assert_equal(found_certs[my_ccdid[2]].clientCertificate, my_client_cert[2], "Expected matching certificate detail") + + self.step(20) + find_response = await cr1_cmd.send_find_client_command(ccdid=my_ccdid[0]) + asserts.assert_equal(len(find_response.certificateDetails), 1, "Expected 1 certificate") + single_response = find_response.certificateDetails[0] + asserts.assert_equal(single_response.ccdid, my_ccdid[0], "FindClientCertificate should contain provisioned client cert") + asserts.assert_equal(single_response.clientCertificate, my_client_cert[3], "Expected matching certificate detail") + + self.step(21) + find_response = await cr2_cmd.send_find_client_command(ccdid=my_ccdid[2]) + asserts.assert_equal(len(find_response.certificateDetails), 1, "Expected 1 certificate") + single_response = find_response.certificateDetails[0] + asserts.assert_equal(single_response.ccdid, my_ccdid[2], "FindClientCertificate should contain provisioned client cert") + asserts.assert_equal(single_response.clientCertificate, my_client_cert[2], "Expected matching certificate detail") + + self.step(22) + for i in range(2): + await cr1_cmd.send_remove_client_command(ccdid=my_ccdid[i]) + + self.step(23) + await cr1_cmd.send_remove_fabric_command(cr2_cmd.fabric_index) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCERT_Base.py b/src/python_testing/TC_TLSCERT_Base.py new file mode 100644 index 00000000000..4cd4d0872f3 --- /dev/null +++ b/src/python_testing/TC_TLSCERT_Base.py @@ -0,0 +1,118 @@ +# +# Copyright (c) 2025 Project CHIP Authors +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import string + +import test_plan_support +from cryptography.x509 import CertificateBuilder, UnrecognizedExtension +from cryptography.x509.oid import ObjectIdentifier +from TC_TLS_Utils import TLSUtils + +import matter.clusters as Clusters +from matter.testing.matter_testing import MatterBaseTest +from matter.testing.runner import TestStep +from matter.utils import CommissioningBuildingBlocks + + +class TC_TLSCERT_Base(MatterBaseTest): + """Base class for TC_TLSCERT test cases with common setup methods.""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + class TwoFabricData: + def __init__(self, cr1_cmd: TLSUtils, cr2_cmd: TLSUtils): + self.cr1_cmd = cr1_cmd + self.cr2_cmd = cr2_cmd + + def get_common_substeps(self, step_prefix: string = "1") -> list[TestStep]: + return [ + TestStep(f'{step_prefix}.1', test_plan_support.commission_if_required('CR1'), is_commissioning=True), + TestStep(f'{step_prefix}.2', "CR1 reads ProvisionedRootCertificates attribute using a fabric-filtered read", + "A list of TLSCertStruct. Store all resulting CAID in caidToClean."), + TestStep( + f'{step_prefix}.3', "CR1 sends RemoveRootCertificate command with CAID set to caidToClean[i] for all entries returned", test_plan_support.verify_success()), + TestStep(f'{step_prefix}.4', "CR1 reads ProvisionedClientCertificates attribute using a fabric-filtered read", + "A list of TLSClientCertificateDetailStruct. Store all resulting CCDID in ccdidToClean."), + TestStep( + f'{step_prefix}.5', "CR1 sends RemoveClientCertificate command with CCDID set to ccdidToClean[i] for all entries returned.", test_plan_support.verify_success()), + ] + + async def common_setup(self, step_prefix: string = "1") -> TLSUtils: + self.step(f'{step_prefix}.1') + attributes = Clusters.TlsCertificateManagement.Attributes + endpoint = self.get_endpoint() + + # Establishing CR1 controller + cr1_cmd = TLSUtils(self, endpoint=endpoint) + + self.step(f'{step_prefix}.2') + root_certs = await cr1_cmd.read_tls_cert_attribute(attributes.ProvisionedRootCertificates) + + self.step(f'{step_prefix}.3') + for cert in root_certs: + await cr1_cmd.send_remove_root_command(caid=cert.caid) + + self.step(f'{step_prefix}.4') + client_certs = await cr1_cmd.read_tls_cert_attribute(attributes.ProvisionedClientCertificates) + + self.step(f'{step_prefix}.5') + for cert in client_certs: + await cr1_cmd.send_remove_client_command(ccdid=cert.ccdid) + + return cr1_cmd + + def get_two_fabric_substeps(self, step_prefix: string = "1") -> list[TestStep]: + return [ + *self.get_common_substeps(f'{step_prefix}.1'), + TestStep(f'{step_prefix}.2', test_plan_support.open_commissioning_window()), + TestStep(f'{step_prefix}.3', test_plan_support.commission_from_existing('CR1', 'CR2')), + ] + + async def common_two_fabric_setup(self, step_prefix: string = "1") -> TwoFabricData: + cr1_cmd = await self.common_setup(f'{step_prefix}.1') + cr1 = self.default_controller + endpoint = self.get_endpoint() + + self.step(f'{step_prefix}.2') + # Establishing CR2 controller + cr2_certificate_authority = self.certificate_authority_manager.NewCertificateAuthority() + cr2_fabric_admin = cr2_certificate_authority.NewFabricAdmin(vendorId=0xFFF1, fabricId=cr1.fabricId + 1) + cr2 = cr2_fabric_admin.NewController(nodeId=cr1.nodeId + 1) + cr2_dut_node_id = self.dut_node_id + 1 + + self.step(f'{step_prefix}.3') + _, noc_resp, _ = await CommissioningBuildingBlocks.AddNOCForNewFabricFromExisting( + commissionerDevCtrl=cr1, newFabricDevCtrl=cr2, + existingNodeId=self.dut_node_id, newNodeId=cr2_dut_node_id + ) + fabric_index_cr2 = noc_resp.fabricIndex + + cr2_cmd = TLSUtils(self, endpoint=endpoint, dev_ctrl=cr2, node_id=cr2_dut_node_id, fabric_index=fabric_index_cr2) + return self.TwoFabricData(cr1_cmd=cr1_cmd, cr2_cmd=cr2_cmd) + + def pad_out_certificate(self) -> CertificateBuilder: + builder = CertificateBuilder() + for i in range(100): + builder = builder.add_extension( + UnrecognizedExtension( + oid=ObjectIdentifier(f"1.1.{i}"), + value=b'\x23' * 20 + ), + critical=False + ) + return builder diff --git a/src/python_testing/TC_TLSCLIENT_2_1.py b/src/python_testing/TC_TLSCLIENT_2_1.py new file mode 100644 index 00000000000..30550010968 --- /dev/null +++ b/src/python_testing/TC_TLSCLIENT_2_1.py @@ -0,0 +1,77 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import test_plan_support +from mobly import asserts +from TC_TLS_Utils import TLSUtils + +import matter.clusters as Clusters +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.matter_testing import MatterBaseTest +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCLIENT_2_1(MatterBaseTest): + def pics_TC_TLSCLIENT_2_1(self): + return ["TLSCLIENT.S"] + + def desc_TC_TLSCLIENT_2_1(self) -> str: + return "[TC-TLSCLIENT-2.1] Attributes with Server as DUT" + + def steps_TC_TLSCLIENT_2_1(self) -> list[TestStep]: + return [ + TestStep(1, test_plan_support.commission_if_required('CR1'), is_commissioning=True), + TestStep(2, "TH reads MaxProvisioned attribute", "DUT replies with an uint8 value between 5 and 254."), + TestStep(3, "TH reads ProvisionedEndpoints attribute", "DUT replies with an empty list of TLSEndpointStruct."), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsClientManagement)) + async def test_TC_TLSCLIENT_2_1(self): + self.step(1) + attributes = Clusters.TlsClientManagement.Attributes + cr1_cmd = TLSUtils(self, endpoint=self.get_endpoint()) + + self.step(2) + max_provisioned = await cr1_cmd.read_tls_client_attribute(attributes.MaxProvisioned) + asserts.assert_greater_equal(max_provisioned, 5, "MaxProvisioned should be >= 5") + asserts.assert_less_equal(max_provisioned, 254, "MaxProvisioned should be <= 254") + + self.step(3) + provisioned_endpoints = await cr1_cmd.read_tls_client_attribute(attributes.ProvisionedEndpoints) + asserts.assert_equal(len(provisioned_endpoints), 0, "ProvisionedEndpoints should be empty") + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCLIENT_3_1.py b/src/python_testing/TC_TLSCLIENT_3_1.py new file mode 100644 index 00000000000..d437d6539fb --- /dev/null +++ b/src/python_testing/TC_TLSCLIENT_3_1.py @@ -0,0 +1,204 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import random + +import test_plan_support +from mobly import asserts +from TC_TLSCLIENT_Base import TC_TLSCLIENT_Base + +import matter.clusters as Clusters +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCLIENT_3_1(TC_TLSCLIENT_Base): + def pics_TC_TLSCLIENT_3_1(self): + return ["TLSCLIENT.S", "TLSCERT.S"] + + def desc_TC_TLSCLIENT_3_1(self) -> str: + return "[TC-TLSCLIENT-3.1] ProvisionEndpoint command basic insertion and modification" + + def steps_TC_TLSCLIENT_3_1(self) -> list[TestStep]: + return [ + *self.get_common_steps(), + TestStep(4, "Set myHostname to a valid value."), + TestStep(5, "Populate myPort[] 3 distinct valid values."), + TestStep(6, "Populate myRootCert[] with 2 distinct valid values."), + TestStep(7, "CR1 sends ProvisionRootCertificate command to the TLSCertificateManagementCluster with null CAID and Certificate set to myRootCert[0].", + "DUT replies with a TLSCAID value. Store the returned value as myCaid[0]."), + TestStep(8, "CR2 sends ProvisionRootCertificate command to the TLSCertificateManagementCluster with null CAID and Certificate set to myRootCert[1].", + "DUT replies with a TLSCAID value. Store the returned value as myCaid[1]."), + TestStep(9, "Populate myNonce[] with 2 distinct, random 32-octet values"), + TestStep(10, "CR1 sends ClientCSR command with Nonce set to myNonce[0]", + "DUT replies with CCDID, CSR and Nonce. Store TLSCCDID in myCcdid[0] and CSR in myCsr[0]."), + TestStep(11, "CR2 sends ClientCSR command with Nonce set to myNonce[1].", + "DUT replies with CCDID, CSR and Nonce. Store TLSCCDID in myCcdid[1] and CSR in myCsr[1]."), + TestStep(12, + "Populate myClientCert[] with 2 distinct, valid, self-signed, DER-encoded x509 certificates using each respective public key from myCsr[i]."), + TestStep( + 13, "CR1 sends ProvisionClientCertificate command to the TLSCertificateManagementCluster with CCDID set to myCcdid[0] and ClientCertificateDetails set to myClientCert[0].", test_plan_support.verify_success()), + TestStep( + 14, "CR2 sends ProvisionClientCertificate command to the TLSCertificateManagementCluster with CCDID set to myCcdid[1] and ClientCertificateDetails set to myClientCert[1].", test_plan_support.verify_success()), + TestStep(15, "CR1 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[0], CAID myCaid[0], CCDID myCcdid[0] and null EndpointID.", + "DUT replies with a TLSEndpointID value. Store the returned value as myEndpoint[0]."), + TestStep(16, "CR1 reads ProvisionedEndpoints attribute.", + "DUT replies with a list of TLSEndpointStruct with one entry. The entry should correspond to (myEndpoint[0], myHostname, myPort[0], myCaid[0], myCcdid[0], myReferenceCount) where myReferenceCount is 0"), + TestStep(17, "CR2 reads ProvisionedEndpoints attribute.", "DUT replies with an empty list of TLSEndpointStruct."), + TestStep(18, "CR2 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[1], CAID myCaid[1], CCDID myCcdid[1] and null EndpointID.", + "DUT replies with a TLSEndpointID value equal to myEndpoint[1]."), + TestStep(19, "CR1 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[2], CAID myCaid[0], CCDID myCcdid[0] and EndpointID myEndpoint[0].", + "DUT replies with a TLSEndpointID value equal to myEndpoint[0]."), + TestStep(20, "CR1 reads ProvisionedEndpoints attribute.", + "DUT replies with a list of TLSEndpointStruct with one entry. The entry should correspond to (myEndpoint[0], myHostname, myPort[2], myCaid[0], myCcdid[0], myReferenceCount) where myReferenceCount is 0"), + TestStep(21, "CR2 reads ProvisionedEndpoints attribute.", + "DUT replies with a list of TLSEndpointStruct with one entry. The entry should correspond to (myEndpoint[1], myHostname, myPort[1], myCaid[1], myCcdid[1], myReferenceCount) where myReferenceCount is 0"), + TestStep( + 22, "CR1 sends RemoveEndpoint command with EndpointID set to myEndpoint[0].", test_plan_support.verify_success()), + TestStep(23, test_plan_support.remove_fabric('CR2', 'CR1'), test_plan_support.verify_success()), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsClientManagement)) + async def test_TC_TLSCLIENT_3_1(self): + setup_data = await self.common_setup() + cr1_cmd = setup_data.cr1_cmd + cr2_cmd = setup_data.cr2_cmd + attributes = Clusters.TlsClientManagement.Attributes + + self.step(4) + my_hostname = b"myhostname.matter.com" + + self.step(5) + my_port = [1234, 5678, 9012] + + self.step(6) + my_root_cert = [cr1_cmd.gen_cert(), cr1_cmd.gen_cert()] + my_caid = [None, None] + + self.step(7) + res = await cr1_cmd.send_provision_root_command(certificate=my_root_cert[0]) + my_caid[0] = res.caid + + self.step(8) + res = await cr2_cmd.send_provision_root_command(certificate=my_root_cert[1]) + my_caid[1] = res.caid + + self.step(9) + my_nonce = [random.randbytes(32), random.randbytes(32)] + my_ccdid = [None, None] + my_csr = [None, None] + + self.step(10) + response = await cr1_cmd.send_csr_command(nonce=my_nonce[0]) + cr1_cmd.assert_valid_ccdid(response.ccdid) + my_ccdid[0] = response.ccdid + my_csr[0] = cr1_cmd.assert_valid_csr(response, my_nonce[0]) + + self.step(11) + response = await cr2_cmd.send_csr_command(nonce=my_nonce[1]) + cr2_cmd.assert_valid_ccdid(response.ccdid) + my_ccdid[1] = response.ccdid + my_csr[1] = cr2_cmd.assert_valid_csr(response, my_nonce[1]) + + self.step(12) + my_client_cert = [None, None] + root = cr1_cmd.get_key() + for i in range(2): + my_client_cert[i] = cr1_cmd.gen_cert_with_key(root, public_key=my_csr[i].public_key(), subject=my_csr[i].subject) + + self.step(13) + await cr1_cmd.send_provision_client_command(ccdid=my_ccdid[0], certificate=my_client_cert[0]) + + self.step(14) + await cr2_cmd.send_provision_client_command(ccdid=my_ccdid[1], certificate=my_client_cert[1]) + + self.step(15) + my_endpoint = [None, None] + res = await cr1_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[0], caid=my_caid[0], ccdid=my_ccdid[0]) + asserts.assert_is_not_none(res.endpointID) + my_endpoint[0] = res.endpointID + + self.step(16) + endpoints = await cr1_cmd.read_tls_client_attribute(attributes.ProvisionedEndpoints) + asserts.assert_equal(len(endpoints), 1) + asserts.assert_equal(endpoints[0].endpointID, my_endpoint[0]) + asserts.assert_equal(endpoints[0].hostname, my_hostname) + asserts.assert_equal(endpoints[0].port, my_port[0]) + asserts.assert_equal(endpoints[0].caid, my_caid[0]) + asserts.assert_equal(endpoints[0].ccdid, my_ccdid[0]) + asserts.assert_equal(endpoints[0].referenceCount, 0) + + self.step(17) + endpoints = await cr2_cmd.read_tls_client_attribute(attributes.ProvisionedEndpoints) + asserts.assert_equal(len(endpoints), 0) + + self.step(18) + res = await cr2_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[1], caid=my_caid[1], ccdid=my_ccdid[1]) + asserts.assert_is_not_none(res.endpointID) + my_endpoint[1] = res.endpointID + + self.step(19) + res = await cr1_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[2], caid=my_caid[0], ccdid=my_ccdid[0], endpoint_id=my_endpoint[0]) + asserts.assert_equal(res.endpointID, my_endpoint[0]) + + self.step(20) + endpoints = await cr1_cmd.read_tls_client_attribute(attributes.ProvisionedEndpoints) + asserts.assert_equal(len(endpoints), 1) + asserts.assert_equal(endpoints[0].endpointID, my_endpoint[0]) + asserts.assert_equal(endpoints[0].hostname, my_hostname) + asserts.assert_equal(endpoints[0].port, my_port[2]) + asserts.assert_equal(endpoints[0].caid, my_caid[0]) + asserts.assert_equal(endpoints[0].ccdid, my_ccdid[0]) + asserts.assert_equal(endpoints[0].referenceCount, 0) + + self.step(21) + endpoints = await cr2_cmd.read_tls_client_attribute(attributes.ProvisionedEndpoints) + asserts.assert_equal(len(endpoints), 1) + asserts.assert_equal(endpoints[0].endpointID, my_endpoint[1]) + asserts.assert_equal(endpoints[0].hostname, my_hostname) + asserts.assert_equal(endpoints[0].port, my_port[1]) + asserts.assert_equal(endpoints[0].caid, my_caid[1]) + asserts.assert_equal(endpoints[0].ccdid, my_ccdid[1]) + asserts.assert_equal(endpoints[0].referenceCount, 0) + + self.step(22) + await cr1_cmd.send_remove_tls_endpoint_command(endpoint_id=my_endpoint[0]) + + self.step(23) + await cr1_cmd.send_remove_fabric_command(cr2_cmd.fabric_index) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCLIENT_3_10.py b/src/python_testing/TC_TLSCLIENT_3_10.py new file mode 100644 index 00000000000..8a679b04d65 --- /dev/null +++ b/src/python_testing/TC_TLSCLIENT_3_10.py @@ -0,0 +1,150 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import random + +import test_plan_support +from mobly import asserts +from TC_TLSCLIENT_Base import TC_TLSCLIENT_Base + +import matter.clusters as Clusters +from matter.interaction_model import Status +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCLIENT_3_10(TC_TLSCLIENT_Base): + def pics_TC_TLSCLIENT_3_10(self): + return ["TLSCLIENT.S", "TLSCERT.S"] + + def desc_TC_TLSCLIENT_3_10(self) -> str: + return "[TC-TLSCLIENT-3.10] FindEndpoint command verification" + + def steps_TC_TLSCLIENT_3_10(self) -> list[TestStep]: + return [ + *self.get_common_steps(), + TestStep(4, "Set myHostname to a valid value."), + TestStep(5, "Set myPort to a valid port value."), + TestStep(6, "Set myRootCert to a valid value."), + TestStep(7, "CR1 sends ProvisionRootCertificate command to the TLSCertificateManagementCluster with null CAID and Certificate set to myRootCert.", + "DUT replies with a TLSCAID value. Store the returned value as myCaid."), + TestStep(8, "Populate myNonce with a distinct, random 32-octet values"), + TestStep(9, "CR1 sends ClientCSR command with Nonce set to myNonce", + "DUT replies with CCDID, CSR and Nonce. Store TLSCCDID in myCcdid and CSR in myCsr."), + TestStep(10, + "Populate myClientCert with a distinct, valid, self-signed, DER-encoded x509 certificates using each respective public key from myCsr."), + TestStep(11, "CR1 sends ProvisionClientCertificate command to the TLSCertificateManagementCluster with CCDID set to myCcdid and ClientCertificateDetails set to myClientCert.", + test_plan_support.verify_success()), + TestStep(12, "CR1 sends FindEndpoint command with EndpointID 0.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(13, "CR1 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort, CAID myCaid, CCDID myCcdid and null EndpointID.", + "DUT replies with a TLSEndpointID value. Store the returned value as myEndpoint."), + TestStep(14, "CR1 sends FindEndpoint command with EndpointID set to myEndpoint.", + "DUT replies with a TLSEndpointStruct with value (myEndpoint, myHostname, myPort, myCaid, myCcdid, myReferenceCount), where myReferenceCount is 0."), + TestStep(15, "CR1 sends FindEndpoint command with EndpointID set to myEndpoint + 1.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(16, "CR2 sends FindEndpoint command with EndpointID set to myEndpoint.", + test_plan_support.verify_status(Status.NotFound)), + TestStep( + 17, "CR1 sends RemoveEndpoint command with EndpointID set to myEndpoint.", test_plan_support.verify_success()), + TestStep(18, test_plan_support.remove_fabric('CR2', 'CR1'), test_plan_support.verify_success()), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsClientManagement)) + async def test_TC_TLSCLIENT_3_10(self): + setup_data = await self.common_setup() + cr1_cmd = setup_data.cr1_cmd + cr2_cmd = setup_data.cr2_cmd + + self.step(4) + my_hostname = b"myhostname.matter.com" + + self.step(5) + my_port = 1234 + + self.step(6) + my_root_cert = cr1_cmd.gen_cert() + + self.step(7) + res = await cr1_cmd.send_provision_root_command(certificate=my_root_cert) + my_caid = res.caid + + self.step(8) + my_nonce = random.randbytes(32) + + self.step(9) + res = await cr1_cmd.send_csr_command(nonce=my_nonce) + my_ccdid = res.ccdid + csr = cr1_cmd.assert_valid_csr(res, my_nonce) + + self.step(10) + my_client_cert = cr1_cmd.gen_cert_with_key( + cr1_cmd.get_key(), public_key=csr.public_key(), subject=csr.subject) + + self.step(11) + await cr1_cmd.send_provision_client_command(ccdid=my_ccdid, certificate=my_client_cert) + + self.step(12) + await cr1_cmd.send_find_tls_endpoint_command(endpoint_id=0, expected_status=Status.NotFound) + + self.step(13) + res = await cr1_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port, caid=my_caid, ccdid=my_ccdid) + asserts.assert_is_not_none(res.endpointID) + my_endpoint = res.endpointID + + self.step(14) + res = await cr1_cmd.send_find_tls_endpoint_command(endpoint_id=my_endpoint) + asserts.assert_equal(res.endpoint.endpointID, my_endpoint) + asserts.assert_equal(res.endpoint.hostname, my_hostname) + asserts.assert_equal(res.endpoint.port, my_port) + asserts.assert_equal(res.endpoint.caid, my_caid) + asserts.assert_equal(res.endpoint.ccdid, my_ccdid) + asserts.assert_equal(res.endpoint.referenceCount, 0) + + self.step(15) + await cr1_cmd.send_find_tls_endpoint_command(endpoint_id=my_endpoint + 1, expected_status=Status.NotFound) + + self.step(16) + await cr2_cmd.send_find_tls_endpoint_command(endpoint_id=my_endpoint, expected_status=Status.NotFound) + + self.step(17) + await cr1_cmd.send_remove_tls_endpoint_command(endpoint_id=my_endpoint) + + self.step(18) + await cr1_cmd.send_remove_fabric_command(cr2_cmd.fabric_index) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCLIENT_3_2.py b/src/python_testing/TC_TLSCLIENT_3_2.py new file mode 100644 index 00000000000..687520661f0 --- /dev/null +++ b/src/python_testing/TC_TLSCLIENT_3_2.py @@ -0,0 +1,226 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import random + +import test_plan_support +from mobly import asserts +from TC_TLSCLIENT_Base import TC_TLSCLIENT_Base + +import matter.clusters as Clusters +from matter.interaction_model import Status +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCLIENT_3_2(TC_TLSCLIENT_Base): + def pics_TC_TLSCLIENT_3_2(self): + return ["TLSCLIENT.S", "TLSCERT.S"] + + def desc_TC_TLSCLIENT_3_2(self) -> str: + return "[TC-TLSCLIENT-3.2] ProvisionEndpoint command verification with several entries" + + def steps_TC_TLSCLIENT_3_2(self) -> list[TestStep]: + return [ + *self.get_common_steps(), + TestStep(4, "Set myHostname to a valid value."), + TestStep(5, "Populate myPort[] with myMaxProvisioned + 3 distinct valid values."), + TestStep(6, "Populate myRootCert[] with 2 distinct, valid, self-signed, DER-encoded x509 certificates"), + TestStep( + 7, "CR1 sends ProvisionRootCertificate command to the TLSCertificateManagementCluster with null CAID and Certificate set to myRootCert[0].", "DUT replies with a TLSCAID value. Store the returned value as myCaid[0]."), + TestStep( + 8, "CR2 sends ProvisionRootCertificate command to the TLSCertificateManagementCluster with null CAID and Certificate set to myRootCert[1].", "DUT replies with a TLSCAID value. Store the returned value as myCaid[1]."), + TestStep(9, "Populate myNonce[] with 2 distinct, random 32-octet values"), + TestStep(10, "CR1 sends ClientCSR command with Nonce set to myNonce[0]", + "DUT replies with CCDID, CSR and Nonce. Store TLSCCDID in myCcdid[0] and CSR in myCsr[0]."), + TestStep(11, "CR2 sends ClientCSR command with Nonce set to myNonce[1].", + "DUT replies with CCDID, CSR and Nonce. Store TLSCCDID in myCcdid[1] and CSR in myCsr[1]."), + TestStep(12, + "Populate myClientCert[] with 2 distinct, valid, self-signed, DER-encoded x509 certificates using each respective public key from myCsr[i]."), + TestStep( + 13, "CR1 sends ProvisionClientCertificate command to the TLSCertificateManagementCluster with CCDID set to myCcdid[0] and ClientCertificateDetails set to myClientCert[0].", test_plan_support.verify_success()), + TestStep( + 14, "CR2 sends ProvisionClientCertificate command to the TLSCertificateManagementCluster with CCDID set to myCcdid[1] and ClientCertificateDetails set to myClientCert[1].", test_plan_support.verify_success()), + TestStep(15, "CR1 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[0], CAID myCaid[0], CCDID myCcdid[0] and null EndpointID.", + "DUT replies with a TLSEndpointID value. Store the returned value as myEndpoint[0]."), + TestStep(16, "CR2 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[i], CAID myCaid[1], CCDID myCcdid[1] and null EndpointID, for i in (1..myMaxProvisioned+1).", + "DUT replies with a TLSEndpointID value. Store the returned value as myEndpoint[i]."), + TestStep(17, "CR1 reads ProvisionedEndpoints attribute.", + "DUT replies with a list of TLSEndpointStruct with 1 entry. The entries should correspond to (myEndpoint[0], myHostname, myPort[i], myCaid[0], myCcdid[0], myReferenceCount) where myReferenceCount is 0"), + TestStep(18, "CR2 reads ProvisionedEndpoints attribute.", + "DUT replies with a list of TLSEndpointStruct with myMaxProvisioned entries. The entries should correspond to (myEndpoint[i], myHostname, myPort[i], myCaid[1], myCcdid[1], myReferenceCount) where myReferenceCount is 0, and i is [2..myMaxProvisioned-1]."), + TestStep(19, "CR2 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[myMaxProvisioned], CAID myCaid[1], CCDID myCcdid[1] and null EndpointID.", test_plan_support.verify_status( + Status.ResourceExhausted)), + TestStep(20, "CR2 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[myMaxProvisioned+1], CAID myCaid[1], CCDID myCcdid[1] and EndpointID set to myEndpoint[1]", + "DUT replies with a TLSEndpointID value equal to myEndpoint[1]"), + TestStep( + 21, "CR2 sends RemoveEndpoint command with EndpointID set to myEndpoint[2]", test_plan_support.verify_success()), + TestStep(22, "CR2 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[myMaxProvisioned+2], CAID myCaid[1], CCDID myCcdid[1] and null EndpointID, for i in (1..myMaxProvisioned+1).", + "DUT replies with a TLSEndpointID value. Store the returned value as myEndpoint[myMaxProvisioned+1]."), + TestStep(23, "CR2 reads ProvisionedEndpoints attribute.", + "DUT replies with a list of TLSEndpointStruct with myMaxProvisioned entries. The entries should correspond to (myEndpoint[i], myHostname, myPort[i], myCaid[1], myCcdid[1], myReferenceCount) where myReferenceCount is 0, and i is [2..myMaxProvisioned+2]."), + TestStep( + 24, "CR1 sends RemoveEndpoint command with EndpointID set to myEndpoint[0]", test_plan_support.verify_success()), + TestStep(25, test_plan_support.remove_fabric('CR2', 'CR1'), test_plan_support.verify_success()), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsClientManagement)) + async def test_TC_TLSCLIENT_3_2(self): + setup_data = await self.common_setup() + cr1_cmd = setup_data.cr1_cmd + cr2_cmd = setup_data.cr2_cmd + attributes = Clusters.TlsClientManagement.Attributes + + max_provisioned = await cr1_cmd.read_tls_client_attribute(attributes.MaxProvisioned) + + self.step(4) + my_hostname = b"myhostname.matter.com" + + self.step(5) + my_port = [1000 + i for i in range(max_provisioned + 3)] + + self.step(6) + my_root_cert = [cr1_cmd.gen_cert(), cr1_cmd.gen_cert()] + my_caid = [None, None] + + self.step(7) + res = await cr1_cmd.send_provision_root_command(certificate=my_root_cert[0]) + my_caid[0] = res.caid + + self.step(8) + res = await cr2_cmd.send_provision_root_command(certificate=my_root_cert[1]) + my_caid[1] = res.caid + + self.step(9) + my_nonce = [random.randbytes(32), random.randbytes(32)] + my_ccdid = [None, None] + my_csr = [None, None] + + self.step(10) + response = await cr1_cmd.send_csr_command(nonce=my_nonce[0]) + cr1_cmd.assert_valid_ccdid(response.ccdid) + my_ccdid[0] = response.ccdid + my_csr[0] = cr1_cmd.assert_valid_csr(response, my_nonce[0]) + + self.step(11) + response = await cr2_cmd.send_csr_command(nonce=my_nonce[1]) + cr2_cmd.assert_valid_ccdid(response.ccdid) + my_ccdid[1] = response.ccdid + my_csr[1] = cr2_cmd.assert_valid_csr(response, my_nonce[1]) + + self.step(12) + my_client_cert = [None, None] + root = cr1_cmd.get_key() + for i in range(2): + my_client_cert[i] = cr1_cmd.gen_cert_with_key(root, public_key=my_csr[i].public_key(), subject=my_csr[i].subject) + + self.step(13) + await cr1_cmd.send_provision_client_command(ccdid=my_ccdid[0], certificate=my_client_cert[0]) + + self.step(14) + await cr2_cmd.send_provision_client_command(ccdid=my_ccdid[1], certificate=my_client_cert[1]) + my_endpoint = [None] * (max_provisioned + 2) + + self.step(15) + res = await cr1_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[0], caid=my_caid[0], ccdid=my_ccdid[0]) + asserts.assert_is_not_none(res.endpointID) + my_endpoint[0] = res.endpointID + + self.step(16) + for i in range(1, max_provisioned+1): + res = await cr2_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[i], caid=my_caid[1], ccdid=my_ccdid[1]) + asserts.assert_is_not_none(res.endpointID) + my_endpoint[i] = res.endpointID + + self.step(17) + endpoints1 = await cr1_cmd.read_tls_client_attribute(attributes.ProvisionedEndpoints) + asserts.assert_equal(len(endpoints1), 1) + + self.step(18) + endpoints2 = await cr2_cmd.read_tls_client_attribute(attributes.ProvisionedEndpoints) + asserts.assert_equal(len(endpoints2), max_provisioned) + found_endpoints = {} + for ep in endpoints2: + found_endpoints[ep.endpointID] = ep + for i in range(1, max_provisioned+1): + ep = found_endpoints[my_endpoint[i]] + asserts.assert_equal(ep.hostname, my_hostname) + asserts.assert_equal(ep.port, my_port[i]) + asserts.assert_equal(ep.caid, my_caid[1]) + asserts.assert_equal(ep.ccdid, my_ccdid[1]) + asserts.assert_equal(ep.referenceCount, 0) + + self.step(19) + await cr2_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[max_provisioned+1], caid=my_caid[1], ccdid=my_ccdid[1], expected_status=Status.ResourceExhausted) + + self.step(20) + res = await cr2_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[max_provisioned+1], caid=my_caid[1], ccdid=my_ccdid[1], endpoint_id=my_endpoint[1]) + asserts.assert_equal(res.endpointID, my_endpoint[1]) + + self.step(21) + await cr2_cmd.send_remove_tls_endpoint_command(endpoint_id=my_endpoint[1]) + + self.step(22) + res = await cr2_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[max_provisioned+2], caid=my_caid[1], ccdid=my_ccdid[1]) + asserts.assert_is_not_none(res.endpointID) + my_endpoint[max_provisioned+1] = res.endpointID + + self.step(23) + endpoints2 = await cr2_cmd.read_tls_client_attribute(attributes.ProvisionedEndpoints) + asserts.assert_equal(len(endpoints2), max_provisioned) + found_endpoints = {} + for ep in endpoints2: + found_endpoints[ep.endpointID] = ep + for i in range(2, max_provisioned+2): + ep = found_endpoints[my_endpoint[i]] + asserts.assert_equal(ep.hostname, my_hostname) + if i == max_provisioned+1: + port = my_port[max_provisioned+2] + else: + port = my_port[i] + asserts.assert_equal(ep.port, port) + asserts.assert_equal(ep.caid, my_caid[1]) + asserts.assert_equal(ep.ccdid, my_ccdid[1]) + asserts.assert_equal(ep.referenceCount, 0) + + self.step(24) + await cr1_cmd.send_remove_tls_endpoint_command(endpoint_id=my_endpoint[0]) + + self.step(25) + await cr1_cmd.send_remove_fabric_command(cr2_cmd.fabric_index) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCLIENT_3_20.py b/src/python_testing/TC_TLSCLIENT_3_20.py new file mode 100644 index 00000000000..0fe0d921f11 --- /dev/null +++ b/src/python_testing/TC_TLSCLIENT_3_20.py @@ -0,0 +1,208 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import random + +import test_plan_support +from mobly import asserts +from TC_TLSCLIENT_Base import TC_TLSCLIENT_Base + +import matter.clusters as Clusters +from matter.interaction_model import Status +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCLIENT_3_20(TC_TLSCLIENT_Base): + def pics_TC_TLSCLIENT_3_20(self): + return ["TLSCLIENT.S", "TLSCERT.S"] + + def desc_TC_TLSCLIENT_3_20(self) -> str: + return "[TC-TLSCLIENT-3.20] RemoveEndpoint command verification" + + def steps_TC_TLSCLIENT_3_20(self) -> list[TestStep]: + return [ + *self.get_common_steps(), + TestStep(4, "Set myHostname to a valid value."), + TestStep(5, "Populate myPort[] with 3 distinct valid port values."), + TestStep(6, "Populate myRootCert[] with 2 distinct valid values."), + TestStep(7, "CR1 sends ProvisionRootCertificate command to the TLSCertificateManagementCluster with null CAID and Certificate set to myRootCert[0].", + "DUT replies with a TLSCAID value. Store the returned value as myCaid[0]."), + TestStep(8, "CR2 sends ProvisionRootCertificate command to the TLSCertificateManagementCluster with null CAID and Certificate set to myRootCert[1].", + "DUT replies with a TLSCAID value. Store the returned value as myCaid[1]."), + TestStep(9, "Populate myNonce[] with 2 distinct, random 32-octet values"), + TestStep(10, "CR1 sends ClientCSR command with Nonce set to myNonce[0]", + "DUT replies with CCDID, CSR and Nonce. Store TLSCCDID in myCcdid[0] and CSR in myCsr[0]."), + TestStep(11, "CR2 sends ClientCSR command with Nonce set to myNonce[1].", + "DUT replies with CCDID, CSR and Nonce. Store TLSCCDID in myCcdid[1] and CSR in myCsr[1]."), + TestStep(12, + "Populate myClientCert[] with 2 distinct, valid, self-signed, DER-encoded x509 certificates using each respective public key from myCsr[i]."), + TestStep(13, "CR1 sends ProvisionClientCertificate command to the TLSCertificateManagementCluster with CCDID set to myCcdid[0] and ClientCertificateDetails set to myClientCert[0].", + test_plan_support.verify_success()), + TestStep(14, "CR2 sends ProvisionClientCertificate command to the TLSCertificateManagementCluster with CCDID set to myCcdid[1] and ClientCertificateDetails set to myClientCert[1].", + test_plan_support.verify_success()), + TestStep(15, "CR1 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[0], CAID myCaid[0], CCDID myCcdid[0] and null EndpointID.", + "DUT replies with a TLSEndpointID value. Store the returned value as myEndpoint[0]."), + TestStep(16, "CR1 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[1], CAID myCaid[0], CCDID myCcdid[0] and null EndpointID.", + "DUT replies with a TLSEndpointID value. Store the returned value as myEndpoint[1]."), + TestStep(17, "CR2 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[2], CAID myCaid[1], CCDID myCcdid[1] and null EndpointID.", + "DUT replies with a TLSEndpointID value. Store the returned value as myEndpoint[2]."), + TestStep(18, "CR1 sends RemoveEndpoint command with EndpointID set to myEndpoint[0].", + test_plan_support.verify_success()), + TestStep(19, "CR1 sends FindEndpoint command with EndpointID set to myEndpoint[0].", + test_plan_support.verify_status(Status.NotFound)), + TestStep(20, "CR1 sends RemoveEndpoint command with EndpointID set to myEndpoint[0].", + test_plan_support.verify_status(Status.NotFound)), + TestStep(21, "CR2 sends RemoveEndpoint command with EndpointID set to myEndpoint[1].", + test_plan_support.verify_status(Status.NotFound)), + TestStep(22, "CR1 sends RemoveEndpoint command with EndpointID set to myEndpoint[1].", + test_plan_support.verify_success()), + TestStep(23, "CR2 sends RemoveRootCertificate command to the TLSCertificateManagementCluster with CAID myCaid[1].", + test_plan_support.verify_status(Status.InvalidInState)), + TestStep(24, "CR2 sends RemoveClientCertificate command to the TLSCertificateManagementCluster with CAID myCcdid[1].", + test_plan_support.verify_status(Status.InvalidInState)), + TestStep(25, "CR2 sends RemoveEndpoint command with EndpointID set to myEndpoint[2].", + test_plan_support.verify_success()), + TestStep(26, "CR2 sends RemoveRootCertificate command to the TLSCertificateManagementCluster with CAID myCaid[1].", + test_plan_support.verify_success()), + TestStep(27, "CR2 sends RemoveClientCertificate command to the TLSCertificateManagementCluster with CAID myCcdid[1].", + test_plan_support.verify_success()), + TestStep(28, test_plan_support.remove_fabric('CR2', 'CR1'), test_plan_support.verify_success()), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsClientManagement)) + async def test_TC_TLSCLIENT_3_20(self): + setup_data = await self.common_setup() + cr1_cmd = setup_data.cr1_cmd + cr2_cmd = setup_data.cr2_cmd + + self.step(4) + my_hostname = b"myhostname.matter.com" + + self.step(5) + my_port = [1000 + i for i in range(3)] + + self.step(6) + my_root_cert = [cr1_cmd.gen_cert(), cr2_cmd.gen_cert()] + my_caid = [None, None] + + self.step(7) + res = await cr1_cmd.send_provision_root_command(certificate=my_root_cert[0]) + my_caid[0] = res.caid + + self.step(8) + res = await cr2_cmd.send_provision_root_command(certificate=my_root_cert[1]) + my_caid[1] = res.caid + + self.step(9) + my_nonce = [random.randbytes(32), random.randbytes(32)] + my_ccdid = [None, None] + my_csr = [None, None] + + self.step(10) + res = await cr1_cmd.send_csr_command(nonce=my_nonce[0]) + my_ccdid[0] = res.ccdid + my_csr[0] = cr1_cmd.assert_valid_csr(res, my_nonce[0]) + + self.step(11) + res = await cr2_cmd.send_csr_command(nonce=my_nonce[1]) + my_ccdid[1] = res.ccdid + my_csr[1] = cr2_cmd.assert_valid_csr(res, my_nonce[1]) + + self.step(12) + my_client_cert = [None, None] + root = cr1_cmd.get_key() + for i in range(2): + my_client_cert[i] = cr1_cmd.gen_cert_with_key(root, public_key=my_csr[i].public_key(), subject=my_csr[i].subject) + + self.step(13) + await cr1_cmd.send_provision_client_command(ccdid=my_ccdid[0], certificate=my_client_cert[0]) + + self.step(14) + await cr2_cmd.send_provision_client_command(ccdid=my_ccdid[1], certificate=my_client_cert[1]) + + my_endpoint = [None] * 3 + + self.step(15) + res = await cr1_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[0], caid=my_caid[0], ccdid=my_ccdid[0]) + asserts.assert_is_not_none(res.endpointID) + my_endpoint[0] = res.endpointID + + self.step(16) + res = await cr1_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[1], caid=my_caid[0], ccdid=my_ccdid[0]) + asserts.assert_is_not_none(res.endpointID) + my_endpoint[1] = res.endpointID + + self.step(17) + res = await cr2_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[2], caid=my_caid[1], ccdid=my_ccdid[1]) + asserts.assert_is_not_none(res.endpointID) + my_endpoint[2] = res.endpointID + + self.step(18) + await cr1_cmd.send_remove_tls_endpoint_command(endpoint_id=my_endpoint[0]) + + self.step(19) + await cr1_cmd.send_find_tls_endpoint_command(endpoint_id=my_endpoint[0], expected_status=Status.NotFound) + + self.step(20) + await cr1_cmd.send_remove_tls_endpoint_command(endpoint_id=my_endpoint[0], expected_status=Status.NotFound) + + self.step(21) + await cr2_cmd.send_remove_tls_endpoint_command(endpoint_id=my_endpoint[1], expected_status=Status.NotFound) + + self.step(22) + await cr1_cmd.send_remove_tls_endpoint_command(endpoint_id=my_endpoint[1]) + + self.step(23) + await cr2_cmd.send_remove_root_command(caid=my_caid[1], expected_status=Status.InvalidInState) + + self.step(24) + await cr2_cmd.send_remove_client_command(ccdid=my_ccdid[1], expected_status=Status.InvalidInState) + + self.step(25) + await cr2_cmd.send_remove_tls_endpoint_command(endpoint_id=my_endpoint[2]) + + self.step(26) + await cr2_cmd.send_remove_root_command(caid=my_caid[1]) + + self.step(27) + await cr2_cmd.send_remove_client_command(ccdid=my_ccdid[1]) + + self.step(28) + await cr1_cmd.send_remove_fabric_command(cr2_cmd.fabric_index) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCLIENT_3_3.py b/src/python_testing/TC_TLSCLIENT_3_3.py new file mode 100644 index 00000000000..ccbf9a36cb4 --- /dev/null +++ b/src/python_testing/TC_TLSCLIENT_3_3.py @@ -0,0 +1,192 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --endpoint 1 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import random +import string + +import test_plan_support +from mobly import asserts +from TC_TLSCLIENT_Base import TC_TLSCLIENT_Base + +import matter.clusters as Clusters +from matter.interaction_model import Status +from matter.testing.decorators import has_cluster, run_if_endpoint_matches +from matter.testing.runner import TestStep, default_matter_test_main + + +class TC_TLSCLIENT_3_3(TC_TLSCLIENT_Base): + def pics_TC_TLSCLIENT_3_3(self): + return ["TLSCLIENT.S", "TLSCERT.S"] + + def desc_TC_TLSCLIENT_3_3(self) -> str: + return "[TC-TLSCLIENT-3.3] ProvisionEndpoint command verification with bad arguments" + + def steps_TC_TLSCLIENT_3_3(self) -> list[TestStep]: + return [ + *self.get_common_steps(), + TestStep(4, "Set myShortHostname to a value shorter than 4."), + TestStep(5, "Set myLongHostname to a value longer than 253."), + TestStep(6, "Set myHostname to a valid value."), + TestStep(7, "Populate myPort[] with 2 distinct valid values."), + TestStep(8, "Populate myRootCert[] with 2 distinct valid values."), + TestStep(9, "CR1 sends ProvisionRootCertificate command to the TLSCertificateManagementCluster with null CAID and Certificate set to myRootCert[0].", + "DUT replies with a TLSCAID value. Store the returned value as myCaid[0]."), + TestStep(10, "CR2 sends ProvisionRootCertificate command to the TLSCertificateManagementCluster with null CAID and Certificate set to myRootCert[1].", + "DUT replies with a TLSCAID value. Store the returned value as myCaid[1]."), + TestStep(11, "Populate myNonce[] with 2 distinct, random 32-octet values"), + TestStep(12, "CR1 sends ClientCSR command with Nonce set to myNonce[0]", + "DUT replies with CCDID, CSR and Nonce. Store TLSCCDID in myCcdid[0] and CSR in myCsr[0]."), + TestStep(13, "CR2 sends ClientCSR command with Nonce set to myNonce[1].", + "DUT replies with CCDID, CSR and Nonce. Store TLSCCDID in myCcdid[1] and CSR in myCsr[1]."), + TestStep(14, + "Populate myClientCert[] with 2 distinct, valid, self-signed, DER-encoded x509 certificates using each respective public key from myCsr[i]."), + TestStep(15, "CR1 sends ProvisionClientCertificate command to the TLSCertificateManagementCluster with CCDID set to myCcdid[0] and ClientCertificateDetails set to myClientCert[0].", + test_plan_support.verify_success()), + TestStep(16, "CR2 sends ProvisionClientCertificate command to the TLSCertificateManagementCluster with CCDID set to myCcdid[1] and ClientCertificateDetails set to myClientCert[1].", + test_plan_support.verify_success()), + TestStep(17, "CR1 sends ProvisionEndpoint command with valid Hostname myShortHostname, Port myPort[0], CAID myCaid[0], CCDID myCcdid[0] and null EndpointID.", + test_plan_support.verify_status(Status.ConstraintError)), + TestStep(18, "CR1 sends ProvisionEndpoint command with valid Hostname myLongHostname, Port myPort[0], CAID myCaid[0], CCDID myCcdid[0] and null EndpointID.", + test_plan_support.verify_status(Status.ConstraintError)), + TestStep(19, "CR2 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[0], CAID myCaid[0], CCDID myCcdid[1] and null EndpointID.", + "DUT replies with the cluster-specific error RootCertificateNotFound."), + TestStep(20, "CR2 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[0], CAID myCaid[1], CCDID myCcdid[0] and null EndpointID.", + "DUT replies with the cluster-specific error ClientCertificateNotFound."), + TestStep(21, "CR1 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[0], CAID myCaid[0], CCDID myCcdid[0] and null EndpointID.", + "DUT replies with a TLSEndpointID value. Store the returned value as myEndpoint[0]."), + TestStep(22, "CR1 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[0], CAID myCaid[0], CCDID myCcdid[0] and null EndpointID.", + "DUT replies with the cluster-specific error EndpointAlreadyInstalled."), + TestStep(23, "CR2 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[0], CAID myCaid[1], CCDID myCcdid[1] and null EndpointID.", + "DUT replies with a TLSEndpointID value"), + TestStep(24, "CR1 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[1], CAID myCaid[0], CCDID myCcdid[0] and EndpointID set to myEndpoint + 1.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(25, "CR2 sends ProvisionEndpoint command with valid Hostname myHostname, Port myPort[1], CAID myCaid[1], CCDID myCcdid[1] and EndpointID set to myEndpoint.", + test_plan_support.verify_status(Status.NotFound)), + TestStep(26, test_plan_support.remove_fabric('CR2', 'CR1'), test_plan_support.verify_success()), + ] + + @run_if_endpoint_matches(has_cluster(Clusters.TlsClientManagement)) + async def test_TC_TLSCLIENT_3_3(self): + setup_data = await self.common_setup() + cr1_cmd = setup_data.cr1_cmd + cr2_cmd = setup_data.cr2_cmd + + self.step(4) + my_short_hostname = b"abc" + + self.step(5) + my_long_hostname = ''.join(random.choices( + string.ascii_letters + string.digits, k=254)).encode('utf-8') + + self.step(6) + my_hostname = b"myhostname.matter.com" + + self.step(7) + my_port = [1234, 5678] + + self.step(8) + my_root_cert = [cr1_cmd.gen_cert(), cr2_cmd.gen_cert()] + my_caid = [None, None] + + self.step(9) + res = await cr1_cmd.send_provision_root_command(certificate=my_root_cert[0]) + my_caid[0] = res.caid + + self.step(10) + res = await cr2_cmd.send_provision_root_command(certificate=my_root_cert[1]) + my_caid[1] = res.caid + + self.step(11) + my_nonce = [random.randbytes(32), random.randbytes(32)] + my_ccdid = [None, None] + my_csr = [None, None] + + self.step(12) + response = await cr1_cmd.send_csr_command(nonce=my_nonce[0]) + my_ccdid[0] = response.ccdid + my_csr[0] = cr1_cmd.assert_valid_csr(response, my_nonce[0]) + + self.step(13) + response = await cr2_cmd.send_csr_command(nonce=my_nonce[1]) + my_ccdid[1] = response.ccdid + my_csr[1] = cr2_cmd.assert_valid_csr(response, my_nonce[1]) + + self.step(14) + my_client_cert = [None, None] + root = cr1_cmd.get_key() + for i in range(2): + my_client_cert[i] = cr1_cmd.gen_cert_with_key(root, public_key=my_csr[i].public_key(), subject=my_csr[i].subject) + + self.step(15) + await cr1_cmd.send_provision_client_command(ccdid=my_ccdid[0], certificate=my_client_cert[0]) + + self.step(16) + await cr2_cmd.send_provision_client_command(ccdid=my_ccdid[1], certificate=my_client_cert[1]) + + self.step(17) + await cr1_cmd.send_provision_tls_endpoint_command(hostname=my_short_hostname, port=my_port[0], caid=my_caid[0], ccdid=my_ccdid[0], expected_status=Status.ConstraintError) + + self.step(18) + await cr1_cmd.send_provision_tls_endpoint_command(hostname=my_long_hostname, port=my_port[0], caid=my_caid[0], ccdid=my_ccdid[0], expected_status=Status.ConstraintError) + + self.step(19) + await cr2_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[0], caid=my_caid[0], ccdid=my_ccdid[1], expected_status=Clusters.TlsClientManagement.Enums.StatusCodeEnum.kRootCertificateNotFound) + + self.step(20) + await cr2_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[0], caid=my_caid[1], ccdid=my_ccdid[0], expected_status=Clusters.TlsClientManagement.Enums.StatusCodeEnum.kClientCertificateNotFound) + + self.step(21) + res = await cr1_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[0], caid=my_caid[0], ccdid=my_ccdid[0]) + asserts.assert_is_not_none(res.endpointID) + my_endpoint_id = res.endpointID + + self.step(22) + await cr1_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[0], caid=my_caid[0], ccdid=my_ccdid[0], expected_status=Clusters.TlsClientManagement.Enums.StatusCodeEnum.kEndpointAlreadyInstalled) + + self.step(23) + await cr2_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[0], caid=my_caid[1], ccdid=my_ccdid[1]) + + self.step(24) + await cr1_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[1], caid=my_caid[0], ccdid=my_ccdid[0], endpoint_id=my_endpoint_id + 1, expected_status=Status.NotFound) + + self.step(25) + await cr2_cmd.send_provision_tls_endpoint_command(hostname=my_hostname, port=my_port[1], caid=my_caid[1], ccdid=my_ccdid[1], endpoint_id=my_endpoint_id, expected_status=Status.NotFound) + + self.step(26) + await cr1_cmd.send_remove_fabric_command(cr2_cmd.fabric_index) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TLSCLIENT_Base.py b/src/python_testing/TC_TLSCLIENT_Base.py new file mode 100644 index 00000000000..d188662cbbb --- /dev/null +++ b/src/python_testing/TC_TLSCLIENT_Base.py @@ -0,0 +1,72 @@ +# +# Copyright (c) 2025 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. +# + +from datetime import timedelta + +import test_plan_support +from TC_TLS_Utils import TLSUtils + +from matter.testing.matter_testing import MatterBaseTest +from matter.testing.runner import TestStep +from matter.utils import CommissioningBuildingBlocks + + +class TC_TLSCLIENT_Base(MatterBaseTest): + """Base class for TC_TLSCLIENT test cases with common setup methods.""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + class TwoFabricData: + def __init__(self, cr1_cmd: TLSUtils, cr2_cmd: TLSUtils): + self.cr1_cmd = cr1_cmd + self.cr2_cmd = cr2_cmd + + # This test creates the maximum number of endpoints, which can take some time + @property + def default_timeout(self) -> int: + return timedelta(minutes=5).total_seconds() + + async def common_setup(self): + self.step(1) + endpoint = self.get_endpoint() + cr1_cmd = TLSUtils(self, endpoint=endpoint) + cr1 = self.default_controller + + self.step(2) + # Establishing CR2 controller + cr2_certificate_authority = self.certificate_authority_manager.NewCertificateAuthority() + cr2_fabric_admin = cr2_certificate_authority.NewFabricAdmin(vendorId=0xFFF1, fabricId=cr1.fabricId + 1) + cr2 = cr2_fabric_admin.NewController(nodeId=cr1.nodeId + 1) + cr2_dut_node_id = self.dut_node_id+1 + + self.step(3) + _, noc_resp, _ = await CommissioningBuildingBlocks.AddNOCForNewFabricFromExisting( + commissionerDevCtrl=cr1, newFabricDevCtrl=cr2, + existingNodeId=self.dut_node_id, newNodeId=cr2_dut_node_id + ) + fabric_index_cr2 = noc_resp.fabricIndex + + cr2_cmd = TLSUtils(self, endpoint=endpoint, dev_ctrl=cr2, node_id=cr2_dut_node_id, fabric_index=fabric_index_cr2) + return self.TwoFabricData(cr1_cmd=cr1_cmd, cr2_cmd=cr2_cmd) + + def get_common_steps(self) -> list[TestStep]: + return [ + TestStep(1, test_plan_support.commission_if_required('CR1'), is_commissioning=True), + TestStep(2, test_plan_support.open_commissioning_window()), + TestStep(3, test_plan_support.commission_from_existing('CR1', 'CR2')), + ] diff --git a/src/python_testing/TC_WEBRTC_1_6.py b/src/python_testing/TC_WEBRTC_1_6.py index 697e27f83cc..0e22a5e6c1d 100644 --- a/src/python_testing/TC_WEBRTC_1_6.py +++ b/src/python_testing/TC_WEBRTC_1_6.py @@ -23,7 +23,10 @@ from matter.ChipDeviceCtrl import TransportPayloadCapability from matter.clusters import CameraAvStreamManagement, Objects, WebRTCTransportProvider from matter.clusters.Types import NullValue -from matter.testing.matter_testing import MatterBaseTest, TestStep, default_matter_test_main, has_feature, run_if_endpoint_matches +from matter.interaction_model import InteractionModelError, Status +from matter.testing.decorators import has_feature, run_if_endpoint_matches +from matter.testing.matter_testing import MatterBaseTest +from matter.testing.runner import TestStep, default_matter_test_main from matter.webrtc import BrowserPeerConnection, WebRTCManager @@ -213,13 +216,20 @@ async def _run_test_steps(self, webrtc_manager: WebRTCManager, webrtc_peer: Brow self.user_verify_two_way_talk("Verify if two way talk back is working") self.step(9) - await self.send_single_cmd( - cmd=WebRTCTransportProvider.Commands.EndSession( - webRTCSessionID=session_id, reason=Objects.Globals.Enums.WebRTCEndReasonEnum.kUserHangup - ), - endpoint=endpoint, - payloadCapability=TransportPayloadCapability.LARGE_PAYLOAD, - ) + try: + await self.send_single_cmd( + cmd=WebRTCTransportProvider.Commands.EndSession( + webRTCSessionID=session_id, reason=Objects.Globals.Enums.WebRTCEndReasonEnum.kUserHangup + ), + endpoint=endpoint, + payloadCapability=TransportPayloadCapability.LARGE_PAYLOAD, + ) + except InteractionModelError as e: + # Since on closing the browser popup, the PC state changes to Disconnected/Closed. + # Some implementations can remove session from CurrentSessions on connection state + # switching to Disconnected/Closed. Hence ignore NotFound status response. + if (e.status != Status.NotFound): + raise if dut_has_vdo_feature: self.step(10) diff --git a/src/python_testing/matter_testing_infrastructure/BUILD.gn b/src/python_testing/matter_testing_infrastructure/BUILD.gn index fa43fc5cf4e..5a80d666b4b 100644 --- a/src/python_testing/matter_testing_infrastructure/BUILD.gn +++ b/src/python_testing/matter_testing_infrastructure/BUILD.gn @@ -15,6 +15,8 @@ import("//build_overrides/build.gni") import("//build_overrides/chip.gni") import("//build_overrides/pigweed.gni") +import( + "//src/python_testing/matter_testing_infrastructure/credential_files.gni") import("//src/python_testing/matter_testing_infrastructure/data_model_xmls.gni") import("$dir_pw_build/python.gni") import("$dir_pw_build/python_dist.gni") @@ -45,6 +47,7 @@ pw_python_package("matter-testing-module") { "matter/testing/commissioning.py", "matter/testing/conformance.py", "matter/testing/conversions.py", + "matter/testing/credentials.py", "matter/testing/decorators.py", "matter/testing/defaults.py", "matter/testing/event_attribute_reporting.py", @@ -126,6 +129,33 @@ pw_zip("data_model_zip_1_5") { output = "${root_out_dir}/data_model/zip_1_5.zip" } +pw_zip("data_model_zip_1_5_1") { + inputs = [] + foreach(file, data_model_XMLS_1_5_1) { + zip_path = rebase_path(file, "${chip_root}/data_model/1.5.1/", "/") + inputs += [ "${file} > /${zip_path}" ] + } + output = "${root_out_dir}/data_model/zip_1_5_1.zip" +} + +pw_zip("credential_zip_development") { + inputs = [] + foreach(file, credentials_development) { + zip_path = rebase_path(file, "${chip_root}/credentials/development/", "/") + inputs += [ "${file} > /${zip_path}" ] + } + output = "${root_out_dir}/credentials/zip_development.zip" +} + +pw_zip("credential_zip_production") { + inputs = [] + foreach(file, credentials_production) { + zip_path = rebase_path(file, "${chip_root}/credentials/production/", "/") + inputs += [ "${file} > /${zip_path}" ] + } + output = "${root_out_dir}/credentials/zip_production.zip" +} + pw_python_distribution("matter-testing") { packages = [ ":matter-testing-module" ] @@ -137,12 +167,15 @@ pw_python_distribution("matter-testing") { } public_deps = [ + ":credential_zip_development", + ":credential_zip_production", ":data_model_zip_1_2", ":data_model_zip_1_3", ":data_model_zip_1_4", ":data_model_zip_1_4_1", ":data_model_zip_1_4_2", ":data_model_zip_1_5", + ":data_model_zip_1_5_1", ] extra_files = [ @@ -152,5 +185,8 @@ pw_python_distribution("matter-testing") { "${root_out_dir}/data_model/zip_1_4_1.zip > matter/testing/data_model/1.4.1/allfiles.zip", "${root_out_dir}/data_model/zip_1_4_2.zip > matter/testing/data_model/1.4.2/allfiles.zip", "${root_out_dir}/data_model/zip_1_5.zip > matter/testing/data_model/1.5/allfiles.zip", + "${root_out_dir}/data_model/zip_1_5_1.zip > matter/testing/data_model/1.5.1/allfiles.zip", + "${root_out_dir}/credentials/zip_development.zip > matter/testing/credentials/development/allfiles.zip", + "${root_out_dir}/credentials/zip_production.zip > matter/testing/credentials/production/allfiles.zip", ] } diff --git a/src/python_testing/matter_testing_infrastructure/credential_files.gni b/src/python_testing/matter_testing_infrastructure/credential_files.gni new file mode 100644 index 00000000000..9a321b39531 --- /dev/null +++ b/src/python_testing/matter_testing_infrastructure/credential_files.gni @@ -0,0 +1,358 @@ +# Copyright (c) 2024-2025 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This file is generated by +# src/python_testing/matter_testing_infrastructure/generate_data_model_xmls_gni.py +# +# Manually re-generate this file on any changes to the files in this directory. + +import("//build_overrides/chip.gni") + +credentials_development = [ + "${chip_root}/credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_001.cert.der", + "${chip_root}/credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_001.cert.pem", + "${chip_root}/credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_002.cert.der", + "${chip_root}/credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_002.cert.pem", + "${chip_root}/credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_003.cert.der", + "${chip_root}/credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_003.cert.pem", + "${chip_root}/credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_004.cert.der", + "${chip_root}/credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_004.cert.pem", + "${chip_root}/credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_005.cert.der", + "${chip_root}/credentials/development/cd-certs/CSA_Matter_CD_Signing_Key_005.cert.pem", + "${chip_root}/credentials/development/cd-certs/CSA_Matter_Certificate_and_Testing_Root.cert.der", + "${chip_root}/credentials/development/cd-certs/CSA_Matter_Certificate_and_Testing_Root.cert.pem", + "${chip_root}/credentials/development/cd-certs/Chip-Test-CD-Cert.der", + "${chip_root}/credentials/development/cd-certs/Chip-Test-CD-Cert.pem", + "${chip_root}/credentials/development/paa-root-certs/Chip-Test-PAA-FFF1-Cert.der", + "${chip_root}/credentials/development/paa-root-certs/Chip-Test-PAA-FFF1-Cert.pem", + "${chip_root}/credentials/development/paa-root-certs/Chip-Test-PAA-NoVID-Cert.der", + "${chip_root}/credentials/development/paa-root-certs/Chip-Test-PAA-NoVID-Cert.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_70mai_Matter_PAA_vid_0x140B.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_70mai_Matter_PAA_vid_0x140B.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_AB_Test_PAA_vid_0x137B.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_AB_Test_PAA_vid_0x137B.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_ACK_PAA_vid_0x137A.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_ACK_PAA_vid_0x137A.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_ACK_Test_PAA_vid_0x137A.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_ACK_Test_PAA_vid_0x137A.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Anker_Innovations_Matter_PAA_vid_0x1533.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Anker_Innovations_Matter_PAA_vid_0x1533.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Aqara_Matter_PAA_01_O_Lumi_United_Technology_Co__Ltd.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Aqara_Matter_PAA_01_O_Lumi_United_Technology_Co__Ltd.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Basics_PAA_vid_0x137B.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Basics_PAA_vid_0x137B.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Beken_Development_PAA_01_vid_0x1342.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Beken_Development_PAA_01_vid_0x1342.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Beken_PAA_01_O_BEKEN_CORPORATION_C_CN_vid_0x1342.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Beken_PAA_01_O_BEKEN_CORPORATION_C_CN_vid_0x1342.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_BouffaloLab_Matter_PAA_vid_0x130D.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_BouffaloLab_Matter_PAA_vid_0x130D.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_BouffaloLab_Matter_Test_PAA_vid_0x130D.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_BouffaloLab_Matter_Test_PAA_vid_0x130D.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_CommScope_Technologies_LLC_Matter_PAA.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_CommScope_Technologies_LLC_Matter_PAA.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_CoolKit_Matter_PAA_test_vid_0x1286.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_CoolKit_Matter_PAA_test_vid_0x1286.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Coolkit_Matter_PAA_vid_0x1286.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Coolkit_Matter_PAA_vid_0x1286.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_DSC_Matter_PAA_O_Dream_Security_Co__Ltd_C_KR.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_DSC_Matter_PAA_O_Dream_Security_Co__Ltd_C_KR.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_DUC_Matter_Test_PAA_CN_vid_0x141F.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_DUC_Matter_Test_PAA_CN_vid_0x141F.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_DigiCert_Root_CA_for_MATTER_PKI_G1_O_DigiCert__Inc_C_US.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_DigiCert_Root_CA_for_MATTER_PKI_G1_O_DigiCert__Inc_C_US.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_DigiCert_TEST_Root_CA_for_MATTER_PKI_O_DigiCert__Inc_C_US.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_DigiCert_TEST_Root_CA_for_MATTER_PKI_O_DigiCert__Inc_C_US.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Dooya_Matter_PAA_vid_0x1365.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Dooya_Matter_PAA_vid_0x1365.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_ELiteu_Matter_Development_PAA_01_vid_0x131F.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_ELiteu_Matter_Development_PAA_01_vid_0x131F.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_ESP_Matter_PAA_test_vid_0x131B.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_ESP_Matter_PAA_test_vid_0x131B.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_EZVIZ_Matter_test_PAA_01_vid_0x1434.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_EZVIZ_Matter_test_PAA_01_vid_0x1434.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Ecovacs_Matter_PAA_O_ECOVACS_IOT_vid_0x1405.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Ecovacs_Matter_PAA_O_ECOVACS_IOT_vid_0x1405.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Energy_Magic_Cube_Matter_PAA_001_vid_0x1462.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Energy_Magic_Cube_Matter_PAA_001_vid_0x1462.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Espressif_Matter_Open_PAA_O_Espressif_Systems.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Espressif_Matter_Open_PAA_O_Espressif_Systems.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Espressif_Matter_PAA_O_Espressif_Systems_vid_0x131B.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Espressif_Matter_PAA_O_Espressif_Systems_vid_0x131B.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Feit_Electric_PAA_vid_0x1423.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Feit_Electric_PAA_vid_0x1423.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Freedompro_vid_0x1411_vid_0x1411.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Freedompro_vid_0x1411_vid_0x1411.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Govee_Test_PAA_vid_0x1387.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Govee_Test_PAA_vid_0x1387.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_HOPERF_Matter_PAA_01_vid_0x1470.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_HOPERF_Matter_PAA_01_vid_0x1470.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Haier-Matter-PAA-01_vid_0x1348.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Haier-Matter-PAA-01_vid_0x1348.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Heiman_Matter_Test_PAA_vid_0x120B.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Heiman_Matter_Test_PAA_vid_0x120B.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Hisense_Matter_Test_PAA_vid_0x138C.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Hisense_Matter_Test_PAA_vid_0x138C.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_HooRii_Matter_Development_PAA_With_VID_0x1351_vid_0x1351.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_HooRii_Matter_Development_PAA_With_VID_0x1351_vid_0x1351.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_HooRii_Matter_PAA_G1_vid_0x1351.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_HooRii_Matter_PAA_G1_vid_0x1351.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_HuaCheng_vid_0x1517.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_HuaCheng_vid_0x1517.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_IKEA_of_Sweden_Matter_PAA_G1_vid_0x117C.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_IKEA_of_Sweden_Matter_PAA_G1_vid_0x117C.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_IKEA_of_Sweden_Matter_Test_PAA_vid_0x117C.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_IKEA_of_Sweden_Matter_Test_PAA_vid_0x117C.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Kasa_Matter_PAA_vid_0x1391.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Kasa_Matter_PAA_vid_0x1391.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Kasa_Matter_Test_PAA_vid_0x1391.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Kasa_Matter_Test_PAA_vid_0x1391.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Kudelski_Matter_PAA_01.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Kudelski_Matter_PAA_01.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Kudelski_Matter_Test_PAA_01.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Kudelski_Matter_Test_PAA_01.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Kwikset_Matter_Test_PAA_vid_0x1421.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Kwikset_Matter_Test_PAA_vid_0x1421.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_LEEDARSON-MATTER-PAA_vid_0x1168.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_LEEDARSON-MATTER-PAA_vid_0x1168.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_LGE_Matter_Test_PAA__vid_0x102E_vid_0x102E.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_LGE_Matter_Test_PAA__vid_0x102E_vid_0x102E.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Legrand_Group_Matter_PAA_vid_0x1021.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Legrand_Group_Matter_PAA_vid_0x1021.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Leviton_PAA_vid_0x109B.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Leviton_PAA_vid_0x109B.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Longanlink_Matter_PAA_01_vid_0x131F.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Longanlink_Matter_PAA_01_vid_0x131F.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Lorex_PAA_CN_vid_0x1419.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Lorex_PAA_CN_vid_0x1419.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_ASR_PAA_C_CN_vid_0x133F.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_ASR_PAA_C_CN_vid_0x133F.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_Certification_and_Testing_CA_O_CSA_vid_0xC5A0.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_Certification_and_Testing_CA_O_CSA_vid_0xC5A0.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_Development_PAA.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_Development_PAA.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_PAA_1_O_Google_C_US_vid_0x6006.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_PAA_1_O_Google_C_US_vid_0x6006.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_PAA_1_O_ubisys_technologies_GmbH_vid_0x10F2.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_PAA_1_O_ubisys_technologies_GmbH_vid_0x10F2.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_PAA_2_O_Google_C_US_vid_0x6006.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_PAA_2_O_Google_C_US_vid_0x6006.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_Signify_PAA_1_vid_0x100B.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_Signify_PAA_1_vid_0x100B.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_Test_PAA_O_Samsung_vid_0x10E1.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_Test_PAA_O_Samsung_vid_0x10E1.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_Test_PAA_vid_0x125D.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_Test_PAA_vid_0x125D.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_Uascent_PAA_0x1400_vid_0x1400.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Matter_Uascent_PAA_0x1400_vid_0x1400.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Meizu_PAA_vid_0x1398.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Meizu_PAA_vid_0x1398.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Meross_Development_PAA_vid_0x1345.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Meross_Development_PAA_vid_0x1345.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Meross_Matter_PAA_vid_0x1345.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Meross_Matter_PAA_vid_0x1345.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Midea_Group_Matter_PAA_G1_Prod_vid_0x118C.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Midea_Group_Matter_PAA_G1_Prod_vid_0x118C.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Midea_PAA_vid_0x118C.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Midea_PAA_vid_0x118C.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Nexus_Matter_PAA_G1_O_Technology_Nexus_SBS_AB_C_SE.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Nexus_Matter_PAA_G1_O_Technology_Nexus_SBS_AB_C_SE.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Non_Production_ONLY_-_XFN_PAA_Class_3.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Non_Production_ONLY_-_XFN_PAA_Class_3.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_OPPO_Test_PAA_vid_0x1341.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_OPPO_Test_PAA_vid_0x1341.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_ORVIBO_Matter_Test_PAA_vid_0x1219.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_ORVIBO_Matter_Test_PAA_vid_0x1219.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_PV_Test_PAA_vid_0x1381.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_PV_Test_PAA_vid_0x1381.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_PanKorePAA_O_PanKore_vid_0x1316.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_PanKorePAA_O_PanKore_vid_0x1316.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Pankore_Matter_Test_PAA.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Pankore_Matter_Test_PAA.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Phaten_Matter_PAA_vid_0x1404.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Phaten_Matter_PAA_vid_0x1404.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Prime_PAA_vid_0x1381.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Prime_PAA_vid_0x1381.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_QDhisense_Test_PAA_vid_0x138C.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_QDhisense_Test_PAA_vid_0x138C.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Qianyan_Matter_PAA_vid_0x1387.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Qianyan_Matter_PAA_vid_0x1387.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Quectel_Matter_CA_PAA_vid_0x1410.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Quectel_Matter_CA_PAA_vid_0x1410.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Quectel_Matter_PAA_vid_0x1410.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Quectel_Matter_PAA_vid_0x1410.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Rafael_Matter_PAA_vid_0x1346.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Rafael_Matter_PAA_vid_0x1346.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Rafael_Test_PAA_vid_0x1346.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Rafael_Test_PAA_vid_0x1346.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_SAVANT_Matter_PAA_vid_0x1339.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_SAVANT_Matter_PAA_vid_0x1339.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_SIEGENIA_Testnet_PAA_vid_0x135A.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_SIEGENIA_Testnet_PAA_vid_0x135A.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Safemo_Matter_PAA_vid_0x1506.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Safemo_Matter_PAA_vid_0x1506.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Schneider_Electric_Matter_PAA_01_vid_0x105E.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Schneider_Electric_Matter_PAA_01_vid_0x105E.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Schneider_Matter_Test_PAA_vid_0x105E.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Schneider_Matter_Test_PAA_vid_0x105E.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Sengled_Matter_PAA_vid_0x1160.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Sengled_Matter_PAA_vid_0x1160.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Siterwell_Matter_PAA_vid_0x1280.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Siterwell_Matter_PAA_vid_0x1280.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Snowball_Matter_PAA_01.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Snowball_Matter_PAA_01.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_StrongKey_G1_Development_PAA_O_StrongKey.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_StrongKey_G1_Development_PAA_O_StrongKey.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_StrongKey_Matter_G1_PAA_O_StrongKey.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_StrongKey_Matter_G1_PAA_O_StrongKey.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Sunricher_PAA_CN_vid_0x1224.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Sunricher_PAA_CN_vid_0x1224.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_SwitchBot_Matter_PAA_vid_0x1397.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_SwitchBot_Matter_PAA_vid_0x1397.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_SwitchBot_Test_PAA_01_vid_0x1397.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_SwitchBot_Test_PAA_01_vid_0x1397.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_TP-Link_Matter_PAA_vid_0x1188.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_TP-Link_Matter_PAA_vid_0x1188.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_TP-Link_Matter_Test_PAA_vid_0x1188.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_TP-Link_Matter_Test_PAA_vid_0x1188.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Tapo_Matter_PAA_vid_0x1392.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Tapo_Matter_PAA_vid_0x1392.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Tapo_Matter_Test_PAA_vid_0x1392.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Tapo_Matter_Test_PAA_vid_0x1392.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Telink_Matter_Development_PAA_01_vid_0x1141.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Telink_Matter_Development_PAA_01_vid_0x1141.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_TrustAsia_Matter_PAA_O_TrustAsia_Technologies__Inc.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_TrustAsia_Matter_PAA_O_TrustAsia_Technologies__Inc.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_TrustAsia_Matter_Test_PAA_O_TrustAsia_Technologies__Inc.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_TrustAsia_Matter_Test_PAA_O_TrustAsia_Technologies__Inc.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Tuya_Global_Matter_PAA.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Tuya_Global_Matter_PAA.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Tuya_Matter_PAA_vid_0x125D.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Tuya_Matter_PAA_vid_0x125D.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_U-tec_Group_Matter_PAA_vid_0x147F.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_U-tec_Group_Matter_PAA_vid_0x147F.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Uascent_Matter_Development_PAA_01_vid_0x1400.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Uascent_Matter_Development_PAA_01_vid_0x1400.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_WISeKey_OISTE_Matter_PAA_GA.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_WISeKey_OISTE_Matter_PAA_GA.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_XFN_Matter_PAA_VID_vid_0x111D.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_XFN_Matter_PAA_VID_vid_0x111D.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Xiaomi_Mijia_Matter_PAA_vid_0x126E.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Xiaomi_Mijia_Matter_PAA_vid_0x126E.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Yeelight_Matter_PAA_vid_0x1312.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_Yeelight_Matter_PAA_vid_0x1312.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_deveritec_GmbH_Test_PAA_vid_0x1362.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_deveritec_GmbH_Test_PAA_vid_0x1362.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_heiman_Matter_Protocol_PAA_vid_0x120B.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_CN_heiman_Matter_Protocol_PAA_vid_0x120B.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_SERIALNUMBER_63709330400001_CN_NXP_Matter_PAA_O_NXP_Semiconductors_NV_C_NL.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_SERIALNUMBER_63709330400001_CN_NXP_Matter_PAA_O_NXP_Semiconductors_NV_C_NL.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_SERIALNUMBER_63709330400004_CN_NXP_Matter_PAA_G2.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_SERIALNUMBER_63709330400004_CN_NXP_Matter_PAA_G2.pem", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_SERIALNUMBER_63709380400001_CN_NXP_Matter_Test_PAA_O_NXP_Semiconductors_NV_C_NL.der", + "${chip_root}/credentials/development/paa-root-certs/dcld_mirror_SERIALNUMBER_63709380400001_CN_NXP_Matter_Test_PAA_O_NXP_Semiconductors_NV_C_NL.pem", +] + +credentials_production = [ + "${chip_root}/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_001_O_CSA_vid_0xC5A0.der", + "${chip_root}/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_001_O_CSA_vid_0xC5A0.pem", + "${chip_root}/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_002_O_CSA_vid_0xC5A0.der", + "${chip_root}/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_002_O_CSA_vid_0xC5A0.pem", + "${chip_root}/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_003_O_CSA_vid_0xC5A0.der", + "${chip_root}/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_003_O_CSA_vid_0xC5A0.pem", + "${chip_root}/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_004_O_CSA_vid_0xC5A0.der", + "${chip_root}/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_004_O_CSA_vid_0xC5A0.pem", + "${chip_root}/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_005_O_CSA_vid_0xC5A0.der", + "${chip_root}/credentials/production/cd-certs/dcld_mirror_CN_Certification_Declaration_Signing_Key_005_O_CSA_vid_0xC5A0.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_ACK_PAA_vid_0x137A.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_ACK_PAA_vid_0x137A.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Basics_PAA_vid_0x137B.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Basics_PAA_vid_0x137B.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Beken_PAA_01_O_BEKEN_CORPORATION_C_CN_vid_0x1342.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Beken_PAA_01_O_BEKEN_CORPORATION_C_CN_vid_0x1342.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_CommScope_Technologies_LLC_Matter_PAA.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_CommScope_Technologies_LLC_Matter_PAA.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Coolkit_Matter_PAA_vid_0x1286.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Coolkit_Matter_PAA_vid_0x1286.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_DigiCert_Root_CA_for_MATTER_PKI_G1_O_DigiCert__Inc_C_US.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_DigiCert_Root_CA_for_MATTER_PKI_G1_O_DigiCert__Inc_C_US.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Dooya_Matter_PAA_vid_0x1365.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Dooya_Matter_PAA_vid_0x1365.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Espressif_Matter_PAA_O_Espressif_Systems_vid_0x131B.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Espressif_Matter_PAA_O_Espressif_Systems_vid_0x131B.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_HooRii_Matter_PAA_G1_vid_0x1351.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_HooRii_Matter_PAA_G1_vid_0x1351.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Kasa_Matter_PAA_vid_0x1391.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Kasa_Matter_PAA_vid_0x1391.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Kudelski_Matter_PAA_01.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Kudelski_Matter_PAA_01.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_LEEDARSON-MATTER-PAA_vid_0x1168.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_LEEDARSON-MATTER-PAA_vid_0x1168.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Legrand_Group_Matter_PAA_vid_0x1021.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Legrand_Group_Matter_PAA_vid_0x1021.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Leviton_PAA_vid_0x109B.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Leviton_PAA_vid_0x109B.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Longanlink_Matter_PAA_01_vid_0x131F.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Longanlink_Matter_PAA_01_vid_0x131F.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Matter_ASR_PAA_C_CN_vid_0x133F.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Matter_ASR_PAA_C_CN_vid_0x133F.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Matter_Certification_and_Testing_CA_O_CSA_vid_0xC5A0.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Matter_Certification_and_Testing_CA_O_CSA_vid_0xC5A0.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Matter_PAA_1_O_ubisys_technologies_GmbH_vid_0x10F2.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Matter_PAA_1_O_ubisys_technologies_GmbH_vid_0x10F2.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Matter_PAA_2_O_Google_C_US_vid_0x6006.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Matter_PAA_2_O_Google_C_US_vid_0x6006.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Matter_Signify_PAA_1_vid_0x100B.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Matter_Signify_PAA_1_vid_0x100B.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Matter_Uascent_PAA_0x1400_vid_0x1400.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Matter_Uascent_PAA_0x1400_vid_0x1400.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Meross_Matter_PAA_vid_0x1345.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Meross_Matter_PAA_vid_0x1345.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Midea_Group_Matter_PAA_G1_Prod_vid_0x118C.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Midea_Group_Matter_PAA_G1_Prod_vid_0x118C.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_PanKorePAA_O_PanKore_vid_0x1316.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_PanKorePAA_O_PanKore_vid_0x1316.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Phaten_Matter_PAA_vid_0x1404.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Phaten_Matter_PAA_vid_0x1404.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Prime_PAA_vid_0x1381.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Prime_PAA_vid_0x1381.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Qianyan_Matter_PAA_vid_0x1387.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Qianyan_Matter_PAA_vid_0x1387.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Quectel_Matter_PAA_vid_0x1410.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Quectel_Matter_PAA_vid_0x1410.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Rafael_Matter_PAA_vid_0x1346.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Rafael_Matter_PAA_vid_0x1346.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Sengled_Matter_PAA_vid_0x1160.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Sengled_Matter_PAA_vid_0x1160.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_StrongKey_Matter_G1_PAA_O_StrongKey.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_StrongKey_Matter_G1_PAA_O_StrongKey.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_TP-Link_Matter_PAA_vid_0x1188.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_TP-Link_Matter_PAA_vid_0x1188.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Tapo_Matter_PAA_vid_0x1392.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Tapo_Matter_PAA_vid_0x1392.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_TrustAsia_Matter_PAA_O_TrustAsia_Technologies__Inc.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_TrustAsia_Matter_PAA_O_TrustAsia_Technologies__Inc.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Tuya_Matter_PAA_vid_0x125D.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Tuya_Matter_PAA_vid_0x125D.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_WISeKey_OISTE_Matter_PAA_GA.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_WISeKey_OISTE_Matter_PAA_GA.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_XFN_Matter_PAA_VID_vid_0x111D.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_XFN_Matter_PAA_VID_vid_0x111D.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Xiaomi_Mijia_Matter_PAA_vid_0x126E.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Xiaomi_Mijia_Matter_PAA_vid_0x126E.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Yeelight_Matter_PAA_vid_0x1312.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_CN_Yeelight_Matter_PAA_vid_0x1312.pem", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_SERIALNUMBER_63709330400001_CN_NXP_Matter_PAA_O_NXP_Semiconductors_NV_C_NL.der", + "${chip_root}/credentials/production/paa-root-certs/dcld_mirror_SERIALNUMBER_63709330400001_CN_NXP_Matter_PAA_O_NXP_Semiconductors_NV_C_NL.pem", +] diff --git a/src/python_testing/matter_testing_infrastructure/data_model_xmls.gni b/src/python_testing/matter_testing_infrastructure/data_model_xmls.gni index 4bf3c0da1a6..e3102d73146 100644 --- a/src/python_testing/matter_testing_infrastructure/data_model_xmls.gni +++ b/src/python_testing/matter_testing_infrastructure/data_model_xmls.gni @@ -1,4 +1,4 @@ -# Copyright (c) 2024 Project CHIP Authors +# Copyright (c) 2024-2025 Project CHIP Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ # This file is generated by # src/python_testing/matter_testing_infrastructure/generate_data_model_xmls_gni.py # -# Manually re-generate this file on any changes to the data_model directory. +# Manually re-generate this file on any changes to the files in this directory. import("//build_overrides/chip.gni") @@ -1204,268 +1204,251 @@ data_model_XMLS_1_5 = [ "${chip_root}/data_model/1.5/namespaces/Namespace-Switches.xml", ] -data_model_XMLS_master = [ - "${chip_root}/data_model/master/clusters/ACL-Cluster.xml", - "${chip_root}/data_model/master/clusters/AccountLogin.xml", - "${chip_root}/data_model/master/clusters/ActionsCluster.xml", - "${chip_root}/data_model/master/clusters/AdminCommissioningCluster.xml", - "${chip_root}/data_model/master/clusters/AirQuality.xml", - "${chip_root}/data_model/master/clusters/AlarmBase.xml", - "${chip_root}/data_model/master/clusters/AmbientContextSensing.xml", - "${chip_root}/data_model/master/clusters/ApplicationBasic.xml", - "${chip_root}/data_model/master/clusters/ApplicationLauncher.xml", - "${chip_root}/data_model/master/clusters/AudioOutput.xml", - "${chip_root}/data_model/master/clusters/BasicInformationCluster.xml", - "${chip_root}/data_model/master/clusters/Binding-Cluster.xml", - "${chip_root}/data_model/master/clusters/BooleanState.xml", - "${chip_root}/data_model/master/clusters/BooleanStateConfiguration.xml", - "${chip_root}/data_model/master/clusters/BridgedDeviceBasicInformationCluster.xml", - "${chip_root}/data_model/master/clusters/CameraAVSettingsUserLevelManagement.xml", - "${chip_root}/data_model/master/clusters/CameraAVStreamManagement.xml", - "${chip_root}/data_model/master/clusters/Channel.xml", - "${chip_root}/data_model/master/clusters/Chime.xml", - "${chip_root}/data_model/master/clusters/ClosureControl.xml", - "${chip_root}/data_model/master/clusters/ClosureDimension.xml", - "${chip_root}/data_model/master/clusters/ColorControl.xml", - "${chip_root}/data_model/master/clusters/CommissionerControlCluster.xml", - "${chip_root}/data_model/master/clusters/CommodityMetering.xml", - "${chip_root}/data_model/master/clusters/CommodityPrice.xml", - "${chip_root}/data_model/master/clusters/CommodityTariff.xml", - "${chip_root}/data_model/master/clusters/ConcentrationMeasurement.xml", - "${chip_root}/data_model/master/clusters/ContentAppObserver.xml", - "${chip_root}/data_model/master/clusters/ContentControl.xml", - "${chip_root}/data_model/master/clusters/ContentLauncher.xml", - "${chip_root}/data_model/master/clusters/DemandResponseLoadControl.xml", - "${chip_root}/data_model/master/clusters/Descriptor-Cluster.xml", - "${chip_root}/data_model/master/clusters/DeviceEnergyManagement.xml", - "${chip_root}/data_model/master/clusters/DiagnosticLogsCluster.xml", - "${chip_root}/data_model/master/clusters/DiagnosticsEthernet.xml", - "${chip_root}/data_model/master/clusters/DiagnosticsGeneral.xml", - "${chip_root}/data_model/master/clusters/DiagnosticsSoftware.xml", - "${chip_root}/data_model/master/clusters/DiagnosticsThread.xml", - "${chip_root}/data_model/master/clusters/DiagnosticsWiFi.xml", - "${chip_root}/data_model/master/clusters/DishwasherAlarm.xml", - "${chip_root}/data_model/master/clusters/DoorLock.xml", - "${chip_root}/data_model/master/clusters/EcosystemInformationCluster.xml", - "${chip_root}/data_model/master/clusters/ElectricalEnergyMeasurement.xml", - "${chip_root}/data_model/master/clusters/ElectricalPowerMeasurement.xml", - "${chip_root}/data_model/master/clusters/EnergyEVSE.xml", - "${chip_root}/data_model/master/clusters/EnergyPreference.xml", - "${chip_root}/data_model/master/clusters/FanControl.xml", - "${chip_root}/data_model/master/clusters/FixedLabel-Cluster.xml", - "${chip_root}/data_model/master/clusters/FlowMeasurement.xml", - "${chip_root}/data_model/master/clusters/GeneralCommissioningCluster.xml", - "${chip_root}/data_model/master/clusters/Group-Key-Management-Cluster.xml", - "${chip_root}/data_model/master/clusters/Groups.xml", - "${chip_root}/data_model/master/clusters/Humidistat.xml", - "${chip_root}/data_model/master/clusters/ICDManagement.xml", - "${chip_root}/data_model/master/clusters/Identify.xml", - "${chip_root}/data_model/master/clusters/IlluminanceMeasurement.xml", - "${chip_root}/data_model/master/clusters/JointFabricDatastoreCluster.xml", - "${chip_root}/data_model/master/clusters/JointFabricPKICluster.xml", - "${chip_root}/data_model/master/clusters/KeypadInput.xml", - "${chip_root}/data_model/master/clusters/Label-Cluster-FixedLabelCluster.xml", - "${chip_root}/data_model/master/clusters/Label-Cluster-LabelCluster.xml", - "${chip_root}/data_model/master/clusters/Label-Cluster-UserLabelCluster.xml", - "${chip_root}/data_model/master/clusters/Label-Cluster.xml", - "${chip_root}/data_model/master/clusters/LaundryDryerControls.xml", - "${chip_root}/data_model/master/clusters/LaundryWasherControls.xml", - "${chip_root}/data_model/master/clusters/LevelControl.xml", - "${chip_root}/data_model/master/clusters/LocalizationConfiguration.xml", - "${chip_root}/data_model/master/clusters/LocalizationTimeFormat.xml", - "${chip_root}/data_model/master/clusters/LocalizationUnit.xml", - "${chip_root}/data_model/master/clusters/LowPower.xml", - "${chip_root}/data_model/master/clusters/MediaInput.xml", - "${chip_root}/data_model/master/clusters/MediaPlayback.xml", - "${chip_root}/data_model/master/clusters/Messages.xml", - "${chip_root}/data_model/master/clusters/MeterIdentification.xml", - "${chip_root}/data_model/master/clusters/MicrowaveOvenControl.xml", - "${chip_root}/data_model/master/clusters/ModeBase.xml", - "${chip_root}/data_model/master/clusters/ModeSelect.xml", - "${chip_root}/data_model/master/clusters/Mode_DeviceEnergyManagement.xml", - "${chip_root}/data_model/master/clusters/Mode_Dishwasher.xml", - "${chip_root}/data_model/master/clusters/Mode_EVSE.xml", - "${chip_root}/data_model/master/clusters/Mode_LaundryWasher.xml", - "${chip_root}/data_model/master/clusters/Mode_MicrowaveOven.xml", - "${chip_root}/data_model/master/clusters/Mode_Oven.xml", - "${chip_root}/data_model/master/clusters/Mode_RVCClean.xml", - "${chip_root}/data_model/master/clusters/Mode_RVCRun.xml", - "${chip_root}/data_model/master/clusters/Mode_Refrigerator.xml", - "${chip_root}/data_model/master/clusters/Mode_WaterHeater.xml", - "${chip_root}/data_model/master/clusters/NetworkCommissioningCluster.xml", - "${chip_root}/data_model/master/clusters/NetworkIdentityManagement.xml", - "${chip_root}/data_model/master/clusters/OTAProvider.xml", - "${chip_root}/data_model/master/clusters/OTARequestor.xml", - "${chip_root}/data_model/master/clusters/OccupancySensing.xml", - "${chip_root}/data_model/master/clusters/OnOff.xml", - "${chip_root}/data_model/master/clusters/OperationalCredentialCluster.xml", - "${chip_root}/data_model/master/clusters/OperationalState.xml", - "${chip_root}/data_model/master/clusters/OperationalState_Oven.xml", - "${chip_root}/data_model/master/clusters/OperationalState_RVC.xml", - "${chip_root}/data_model/master/clusters/PowerSourceCluster.xml", - "${chip_root}/data_model/master/clusters/PowerSourceConfigurationCluster.xml", - "${chip_root}/data_model/master/clusters/PowerTopology.xml", - "${chip_root}/data_model/master/clusters/PressureMeasurement.xml", - "${chip_root}/data_model/master/clusters/PumpConfigurationControl.xml", - "${chip_root}/data_model/master/clusters/PushAVStreamTransport.xml", - "${chip_root}/data_model/master/clusters/RefrigeratorAlarm.xml", - "${chip_root}/data_model/master/clusters/ResourceMonitoring.xml", - "${chip_root}/data_model/master/clusters/Scenes.xml", - "${chip_root}/data_model/master/clusters/ServiceArea.xml", - "${chip_root}/data_model/master/clusters/SmokeCOAlarm.xml", - "${chip_root}/data_model/master/clusters/SoilMeasurement.xml", - "${chip_root}/data_model/master/clusters/Switch.xml", - "${chip_root}/data_model/master/clusters/TLSCertificateManagement.xml", - "${chip_root}/data_model/master/clusters/TLSClientManagement.xml", - "${chip_root}/data_model/master/clusters/TargetNavigator.xml", - "${chip_root}/data_model/master/clusters/TemperatureControl.xml", - "${chip_root}/data_model/master/clusters/TemperatureMeasurement.xml", - "${chip_root}/data_model/master/clusters/Thermostat.xml", - "${chip_root}/data_model/master/clusters/ThermostatUserInterfaceConfiguration.xml", - "${chip_root}/data_model/master/clusters/ThreadBorderRouterDiagnostics.xml", - "${chip_root}/data_model/master/clusters/ThreadBorderRouterManagement.xml", - "${chip_root}/data_model/master/clusters/ThreadNetworkDirectory.xml", - "${chip_root}/data_model/master/clusters/TimeSync.xml", - "${chip_root}/data_model/master/clusters/UserLabel-Cluster.xml", - "${chip_root}/data_model/master/clusters/ValveConfigurationControl.xml", - "${chip_root}/data_model/master/clusters/WakeOnLAN.xml", - "${chip_root}/data_model/master/clusters/WaterContentMeasurement.xml", - "${chip_root}/data_model/master/clusters/WaterHeaterManagement.xml", - "${chip_root}/data_model/master/clusters/WebRTC_Provider.xml", - "${chip_root}/data_model/master/clusters/WebRTC_Requestor.xml", - "${chip_root}/data_model/master/clusters/WiFiNetworkManagement.xml", - "${chip_root}/data_model/master/clusters/WindowCovering.xml", - "${chip_root}/data_model/master/clusters/ZoneManagement.xml", - "${chip_root}/data_model/master/clusters/bridge-clusters-ActionsCluster.xml", - "${chip_root}/data_model/master/clusters/bridge-clusters-BridgedDeviceBasicInformationCluster.xml", - "${chip_root}/data_model/master/device_types/Aggregator.xml", - "${chip_root}/data_model/master/device_types/AirPurifier.xml", - "${chip_root}/data_model/master/device_types/AirQualitySensor.xml", - "${chip_root}/data_model/master/device_types/AudioDoorbell.xml", - "${chip_root}/data_model/master/device_types/BaseDeviceType.xml", - "${chip_root}/data_model/master/device_types/BasicVideoPlayer.xml", - "${chip_root}/data_model/master/device_types/BatteryStorage.xml", - "${chip_root}/data_model/master/device_types/BridgedNode.xml", - "${chip_root}/data_model/master/device_types/Camera.xml", - "${chip_root}/data_model/master/device_types/CameraController.xml", - "${chip_root}/data_model/master/device_types/CastingVideoClient.xml", - "${chip_root}/data_model/master/device_types/CastingVideoPlayer.xml", - "${chip_root}/data_model/master/device_types/Chime.xml", - "${chip_root}/data_model/master/device_types/Closure.xml", - "${chip_root}/data_model/master/device_types/ClosureBaseDeviceTypes-Awning.xml", - "${chip_root}/data_model/master/device_types/ClosureBaseDeviceTypes-Barrier.xml", - "${chip_root}/data_model/master/device_types/ClosureBaseDeviceTypes-Blind.xml", - "${chip_root}/data_model/master/device_types/ClosureBaseDeviceTypes-Cabinet.xml", - "${chip_root}/data_model/master/device_types/ClosureBaseDeviceTypes-ClosureBase.xml", - "${chip_root}/data_model/master/device_types/ClosureBaseDeviceTypes-Curtain.xml", - "${chip_root}/data_model/master/device_types/ClosureBaseDeviceTypes-Door.xml", - "${chip_root}/data_model/master/device_types/ClosureBaseDeviceTypes-GarageDoor.xml", - "${chip_root}/data_model/master/device_types/ClosureBaseDeviceTypes-Gate.xml", - "${chip_root}/data_model/master/device_types/ClosureBaseDeviceTypes-Pergola.xml", - "${chip_root}/data_model/master/device_types/ClosureBaseDeviceTypes-Screen.xml", - "${chip_root}/data_model/master/device_types/ClosureBaseDeviceTypes-Shade.xml", - "${chip_root}/data_model/master/device_types/ClosureBaseDeviceTypes-Shutter.xml", - "${chip_root}/data_model/master/device_types/ClosureBaseDeviceTypes-Window.xml", - "${chip_root}/data_model/master/device_types/ClosureController.xml", - "${chip_root}/data_model/master/device_types/ClosurePanel.xml", - "${chip_root}/data_model/master/device_types/ColorDimmerSwitch.xml", - "${chip_root}/data_model/master/device_types/ColorTemperatureLight.xml", - "${chip_root}/data_model/master/device_types/ContactSensor.xml", - "${chip_root}/data_model/master/device_types/ContentApp.xml", - "${chip_root}/data_model/master/device_types/ControlBridge.xml", - "${chip_root}/data_model/master/device_types/CookSurface.xml", - "${chip_root}/data_model/master/device_types/Cooktop.xml", - "${chip_root}/data_model/master/device_types/DeviceEnergyManagement.xml", - "${chip_root}/data_model/master/device_types/DimmableLight.xml", - "${chip_root}/data_model/master/device_types/DimmablePlug-InUnit.xml", - "${chip_root}/data_model/master/device_types/DimmerSwitch.xml", - "${chip_root}/data_model/master/device_types/Dishwasher.xml", - "${chip_root}/data_model/master/device_types/DoorLock.xml", - "${chip_root}/data_model/master/device_types/DoorLockController.xml", - "${chip_root}/data_model/master/device_types/EVSE.xml", - "${chip_root}/data_model/master/device_types/ElectricalEnergyTariff.xml", - "${chip_root}/data_model/master/device_types/ElectricalMeter.xml", - "${chip_root}/data_model/master/device_types/ElectricalSensor.xml", - "${chip_root}/data_model/master/device_types/ElectricalUtilityMeter.xml", - "${chip_root}/data_model/master/device_types/ExtendedColorLight.xml", - "${chip_root}/data_model/master/device_types/ExtractorHood.xml", - "${chip_root}/data_model/master/device_types/Fan.xml", - "${chip_root}/data_model/master/device_types/FloodlightCamera.xml", - "${chip_root}/data_model/master/device_types/FlowSensor.xml", - "${chip_root}/data_model/master/device_types/GenericSwitch.xml", - "${chip_root}/data_model/master/device_types/HeatPump.xml", - "${chip_root}/data_model/master/device_types/HumidifierDehumidifier.xml", - "${chip_root}/data_model/master/device_types/HumiditySensor.xml", - "${chip_root}/data_model/master/device_types/Intercom.xml", - "${chip_root}/data_model/master/device_types/IrrigationSystem.xml", - "${chip_root}/data_model/master/device_types/JointFabricAdmin.xml", - "${chip_root}/data_model/master/device_types/LaundryDryer.xml", - "${chip_root}/data_model/master/device_types/LaundryWasher.xml", - "${chip_root}/data_model/master/device_types/LightSensor.xml", - "${chip_root}/data_model/master/device_types/MeterReferencePoint.xml", - "${chip_root}/data_model/master/device_types/MicrowaveOven.xml", - "${chip_root}/data_model/master/device_types/ModeSelectDeviceType.xml", - "${chip_root}/data_model/master/device_types/MountedDimmableLoadControl.xml", - "${chip_root}/data_model/master/device_types/MountedOnOffControl.xml", - "${chip_root}/data_model/master/device_types/NetworkInfraManager.xml", - "${chip_root}/data_model/master/device_types/OccupancySensor.xml", - "${chip_root}/data_model/master/device_types/OnOffLight.xml", - "${chip_root}/data_model/master/device_types/OnOffLightSwitch.xml", - "${chip_root}/data_model/master/device_types/OnOffPlug-inUnit.xml", - "${chip_root}/data_model/master/device_types/OnOffSensor.xml", - "${chip_root}/data_model/master/device_types/OtaProvider.xml", - "${chip_root}/data_model/master/device_types/OtaRequestor.xml", - "${chip_root}/data_model/master/device_types/Oven.xml", - "${chip_root}/data_model/master/device_types/PowerSource.xml", - "${chip_root}/data_model/master/device_types/PressureSensor.xml", - "${chip_root}/data_model/master/device_types/Pump.xml", - "${chip_root}/data_model/master/device_types/PumpController.xml", - "${chip_root}/data_model/master/device_types/RainSensor.xml", - "${chip_root}/data_model/master/device_types/Refrigerator.xml", - "${chip_root}/data_model/master/device_types/RoboticVacuumCleaner.xml", - "${chip_root}/data_model/master/device_types/RoomAirConditioner.xml", - "${chip_root}/data_model/master/device_types/RootNodeDeviceType.xml", - "${chip_root}/data_model/master/device_types/SecondaryNetworkInterface.xml", - "${chip_root}/data_model/master/device_types/SmokeCOAlarm.xml", - "${chip_root}/data_model/master/device_types/SnapshotCamera.xml", - "${chip_root}/data_model/master/device_types/SoilSensor.xml", - "${chip_root}/data_model/master/device_types/SolarPower.xml", - "${chip_root}/data_model/master/device_types/Speaker.xml", - "${chip_root}/data_model/master/device_types/TemperatureControlledCabinet.xml", - "${chip_root}/data_model/master/device_types/TemperatureSensor.xml", - "${chip_root}/data_model/master/device_types/Thermostat.xml", - "${chip_root}/data_model/master/device_types/ThermostatController.xml", - "${chip_root}/data_model/master/device_types/ThreadBorderRouter.xml", - "${chip_root}/data_model/master/device_types/VideoDoorbell.xml", - "${chip_root}/data_model/master/device_types/VideoRemoteControl.xml", - "${chip_root}/data_model/master/device_types/WaterFreezeDetector.xml", - "${chip_root}/data_model/master/device_types/WaterHeater.xml", - "${chip_root}/data_model/master/device_types/WaterLeakDetector.xml", - "${chip_root}/data_model/master/device_types/WaterValve.xml", - "${chip_root}/data_model/master/device_types/WindowCovering.xml", - "${chip_root}/data_model/master/device_types/WindowCoveringController.xml", - "${chip_root}/data_model/master/namespaces/Namespace-Closure-Cabinet.xml", - "${chip_root}/data_model/master/namespaces/Namespace-Closure-Covering.xml", - "${chip_root}/data_model/master/namespaces/Namespace-Closure-Window.xml", - "${chip_root}/data_model/master/namespaces/Namespace-Closure.xml", - "${chip_root}/data_model/master/namespaces/Namespace-ClosurePanel.xml", - "${chip_root}/data_model/master/namespaces/Namespace-CommodityTariff-Chronology.xml", - "${chip_root}/data_model/master/namespaces/Namespace-CommodityTariff-Commodity.xml", - "${chip_root}/data_model/master/namespaces/Namespace-CommodityTariff-Flow.xml", - "${chip_root}/data_model/master/namespaces/Namespace-Common-Area.xml", - "${chip_root}/data_model/master/namespaces/Namespace-Common-CompassDirection.xml", - "${chip_root}/data_model/master/namespaces/Namespace-Common-CompassLocation.xml", - "${chip_root}/data_model/master/namespaces/Namespace-Common-Direction.xml", - "${chip_root}/data_model/master/namespaces/Namespace-Common-Landmark.xml", - "${chip_root}/data_model/master/namespaces/Namespace-Common-Level.xml", - "${chip_root}/data_model/master/namespaces/Namespace-Common-Location.xml", - "${chip_root}/data_model/master/namespaces/Namespace-Common-Number.xml", - "${chip_root}/data_model/master/namespaces/Namespace-Common-Position.xml", - "${chip_root}/data_model/master/namespaces/Namespace-Common-RelativePosition.xml", - "${chip_root}/data_model/master/namespaces/Namespace-ElectricalMeasurement.xml", - "${chip_root}/data_model/master/namespaces/Namespace-Laundry.xml", - "${chip_root}/data_model/master/namespaces/Namespace-PowerSource.xml", - "${chip_root}/data_model/master/namespaces/Namespace-Refrigerator.xml", - "${chip_root}/data_model/master/namespaces/Namespace-RoomAirConditioner.xml", - "${chip_root}/data_model/master/namespaces/Namespace-Switches.xml", +data_model_XMLS_1_5_1 = [ + "${chip_root}/data_model/1.5.1/clusters/ACL-Cluster.xml", + "${chip_root}/data_model/1.5.1/clusters/AccountLogin.xml", + "${chip_root}/data_model/1.5.1/clusters/ActionsCluster.xml", + "${chip_root}/data_model/1.5.1/clusters/AdminCommissioningCluster.xml", + "${chip_root}/data_model/1.5.1/clusters/AirQuality.xml", + "${chip_root}/data_model/1.5.1/clusters/AlarmBase.xml", + "${chip_root}/data_model/1.5.1/clusters/ApplicationBasic.xml", + "${chip_root}/data_model/1.5.1/clusters/ApplicationLauncher.xml", + "${chip_root}/data_model/1.5.1/clusters/AudioOutput.xml", + "${chip_root}/data_model/1.5.1/clusters/BasicInformationCluster.xml", + "${chip_root}/data_model/1.5.1/clusters/Binding-Cluster.xml", + "${chip_root}/data_model/1.5.1/clusters/BooleanState.xml", + "${chip_root}/data_model/1.5.1/clusters/BooleanStateConfiguration.xml", + "${chip_root}/data_model/1.5.1/clusters/BridgedDeviceBasicInformationCluster.xml", + "${chip_root}/data_model/1.5.1/clusters/CameraAVSettingsUserLevelManagement.xml", + "${chip_root}/data_model/1.5.1/clusters/CameraAVStreamManagement.xml", + "${chip_root}/data_model/1.5.1/clusters/Channel.xml", + "${chip_root}/data_model/1.5.1/clusters/Chime.xml", + "${chip_root}/data_model/1.5.1/clusters/ClosureControl.xml", + "${chip_root}/data_model/1.5.1/clusters/ClosureDimension.xml", + "${chip_root}/data_model/1.5.1/clusters/ColorControl.xml", + "${chip_root}/data_model/1.5.1/clusters/CommissionerControlCluster.xml", + "${chip_root}/data_model/1.5.1/clusters/CommodityMetering.xml", + "${chip_root}/data_model/1.5.1/clusters/CommodityPrice.xml", + "${chip_root}/data_model/1.5.1/clusters/CommodityTariff.xml", + "${chip_root}/data_model/1.5.1/clusters/ConcentrationMeasurement.xml", + "${chip_root}/data_model/1.5.1/clusters/ContentAppObserver.xml", + "${chip_root}/data_model/1.5.1/clusters/ContentControl.xml", + "${chip_root}/data_model/1.5.1/clusters/ContentLauncher.xml", + "${chip_root}/data_model/1.5.1/clusters/Descriptor-Cluster.xml", + "${chip_root}/data_model/1.5.1/clusters/DeviceEnergyManagement.xml", + "${chip_root}/data_model/1.5.1/clusters/DiagnosticLogsCluster.xml", + "${chip_root}/data_model/1.5.1/clusters/DiagnosticsEthernet.xml", + "${chip_root}/data_model/1.5.1/clusters/DiagnosticsGeneral.xml", + "${chip_root}/data_model/1.5.1/clusters/DiagnosticsSoftware.xml", + "${chip_root}/data_model/1.5.1/clusters/DiagnosticsThread.xml", + "${chip_root}/data_model/1.5.1/clusters/DiagnosticsWiFi.xml", + "${chip_root}/data_model/1.5.1/clusters/DishwasherAlarm.xml", + "${chip_root}/data_model/1.5.1/clusters/DoorLock.xml", + "${chip_root}/data_model/1.5.1/clusters/EcosystemInformationCluster.xml", + "${chip_root}/data_model/1.5.1/clusters/ElectricalEnergyMeasurement.xml", + "${chip_root}/data_model/1.5.1/clusters/ElectricalGridConditions.xml", + "${chip_root}/data_model/1.5.1/clusters/ElectricalPowerMeasurement.xml", + "${chip_root}/data_model/1.5.1/clusters/EnergyEVSE.xml", + "${chip_root}/data_model/1.5.1/clusters/EnergyPreference.xml", + "${chip_root}/data_model/1.5.1/clusters/FanControl.xml", + "${chip_root}/data_model/1.5.1/clusters/FixedLabel-Cluster.xml", + "${chip_root}/data_model/1.5.1/clusters/FlowMeasurement.xml", + "${chip_root}/data_model/1.5.1/clusters/GeneralCommissioningCluster.xml", + "${chip_root}/data_model/1.5.1/clusters/Group-Key-Management-Cluster.xml", + "${chip_root}/data_model/1.5.1/clusters/Groups.xml", + "${chip_root}/data_model/1.5.1/clusters/ICDManagement.xml", + "${chip_root}/data_model/1.5.1/clusters/Identify.xml", + "${chip_root}/data_model/1.5.1/clusters/IlluminanceMeasurement.xml", + "${chip_root}/data_model/1.5.1/clusters/JointFabricAdministratorCluster.xml", + "${chip_root}/data_model/1.5.1/clusters/JointFabricDatastoreCluster.xml", + "${chip_root}/data_model/1.5.1/clusters/KeypadInput.xml", + "${chip_root}/data_model/1.5.1/clusters/Label-Cluster.xml", + "${chip_root}/data_model/1.5.1/clusters/LaundryDryerControls.xml", + "${chip_root}/data_model/1.5.1/clusters/LaundryWasherControls.xml", + "${chip_root}/data_model/1.5.1/clusters/LevelControl.xml", + "${chip_root}/data_model/1.5.1/clusters/LocalizationConfiguration.xml", + "${chip_root}/data_model/1.5.1/clusters/LocalizationTimeFormat.xml", + "${chip_root}/data_model/1.5.1/clusters/LocalizationUnit.xml", + "${chip_root}/data_model/1.5.1/clusters/LowPower.xml", + "${chip_root}/data_model/1.5.1/clusters/MediaInput.xml", + "${chip_root}/data_model/1.5.1/clusters/MediaPlayback.xml", + "${chip_root}/data_model/1.5.1/clusters/Messages.xml", + "${chip_root}/data_model/1.5.1/clusters/MeterIdentification.xml", + "${chip_root}/data_model/1.5.1/clusters/MicrowaveOvenControl.xml", + "${chip_root}/data_model/1.5.1/clusters/ModeBase.xml", + "${chip_root}/data_model/1.5.1/clusters/ModeSelect.xml", + "${chip_root}/data_model/1.5.1/clusters/Mode_DeviceEnergyManagement.xml", + "${chip_root}/data_model/1.5.1/clusters/Mode_Dishwasher.xml", + "${chip_root}/data_model/1.5.1/clusters/Mode_EVSE.xml", + "${chip_root}/data_model/1.5.1/clusters/Mode_LaundryWasher.xml", + "${chip_root}/data_model/1.5.1/clusters/Mode_MicrowaveOven.xml", + "${chip_root}/data_model/1.5.1/clusters/Mode_Oven.xml", + "${chip_root}/data_model/1.5.1/clusters/Mode_RVCClean.xml", + "${chip_root}/data_model/1.5.1/clusters/Mode_RVCRun.xml", + "${chip_root}/data_model/1.5.1/clusters/Mode_Refrigerator.xml", + "${chip_root}/data_model/1.5.1/clusters/Mode_WaterHeater.xml", + "${chip_root}/data_model/1.5.1/clusters/NetworkCommissioningCluster.xml", + "${chip_root}/data_model/1.5.1/clusters/OTAProvider.xml", + "${chip_root}/data_model/1.5.1/clusters/OTARequestor.xml", + "${chip_root}/data_model/1.5.1/clusters/OccupancySensing.xml", + "${chip_root}/data_model/1.5.1/clusters/OnOff.xml", + "${chip_root}/data_model/1.5.1/clusters/OperationalCredentialCluster.xml", + "${chip_root}/data_model/1.5.1/clusters/OperationalState.xml", + "${chip_root}/data_model/1.5.1/clusters/OperationalState_Oven.xml", + "${chip_root}/data_model/1.5.1/clusters/OperationalState_RVC.xml", + "${chip_root}/data_model/1.5.1/clusters/PowerSourceCluster.xml", + "${chip_root}/data_model/1.5.1/clusters/PowerSourceConfigurationCluster.xml", + "${chip_root}/data_model/1.5.1/clusters/PowerTopology.xml", + "${chip_root}/data_model/1.5.1/clusters/PressureMeasurement.xml", + "${chip_root}/data_model/1.5.1/clusters/PumpConfigurationControl.xml", + "${chip_root}/data_model/1.5.1/clusters/PushAVStreamTransport.xml", + "${chip_root}/data_model/1.5.1/clusters/RefrigeratorAlarm.xml", + "${chip_root}/data_model/1.5.1/clusters/ResourceMonitoring.xml", + "${chip_root}/data_model/1.5.1/clusters/Scenes.xml", + "${chip_root}/data_model/1.5.1/clusters/ServiceArea.xml", + "${chip_root}/data_model/1.5.1/clusters/SmokeCOAlarm.xml", + "${chip_root}/data_model/1.5.1/clusters/SoilMeasurement.xml", + "${chip_root}/data_model/1.5.1/clusters/Switch.xml", + "${chip_root}/data_model/1.5.1/clusters/TLSCertificateManagement.xml", + "${chip_root}/data_model/1.5.1/clusters/TLSClientManagement.xml", + "${chip_root}/data_model/1.5.1/clusters/TargetNavigator.xml", + "${chip_root}/data_model/1.5.1/clusters/TemperatureControl.xml", + "${chip_root}/data_model/1.5.1/clusters/TemperatureMeasurement.xml", + "${chip_root}/data_model/1.5.1/clusters/Thermostat.xml", + "${chip_root}/data_model/1.5.1/clusters/ThermostatUserInterfaceConfiguration.xml", + "${chip_root}/data_model/1.5.1/clusters/ThreadBorderRouterManagement.xml", + "${chip_root}/data_model/1.5.1/clusters/ThreadNetworkDirectory.xml", + "${chip_root}/data_model/1.5.1/clusters/TimeSync.xml", + "${chip_root}/data_model/1.5.1/clusters/UserLabel-Cluster.xml", + "${chip_root}/data_model/1.5.1/clusters/ValveConfigurationControl.xml", + "${chip_root}/data_model/1.5.1/clusters/WakeOnLAN.xml", + "${chip_root}/data_model/1.5.1/clusters/WaterContentMeasurement.xml", + "${chip_root}/data_model/1.5.1/clusters/WaterHeaterManagement.xml", + "${chip_root}/data_model/1.5.1/clusters/WebRTC_Provider.xml", + "${chip_root}/data_model/1.5.1/clusters/WebRTC_Requestor.xml", + "${chip_root}/data_model/1.5.1/clusters/WiFiNetworkManagement.xml", + "${chip_root}/data_model/1.5.1/clusters/WindowCovering.xml", + "${chip_root}/data_model/1.5.1/clusters/ZoneManagement.xml", + "${chip_root}/data_model/1.5.1/device_types/Aggregator.xml", + "${chip_root}/data_model/1.5.1/device_types/AirPurifier.xml", + "${chip_root}/data_model/1.5.1/device_types/AirQualitySensor.xml", + "${chip_root}/data_model/1.5.1/device_types/AudioDoorbell.xml", + "${chip_root}/data_model/1.5.1/device_types/BaseDeviceType.xml", + "${chip_root}/data_model/1.5.1/device_types/BasicVideoPlayer.xml", + "${chip_root}/data_model/1.5.1/device_types/BatteryStorage.xml", + "${chip_root}/data_model/1.5.1/device_types/BridgedNode.xml", + "${chip_root}/data_model/1.5.1/device_types/Camera.xml", + "${chip_root}/data_model/1.5.1/device_types/CameraController.xml", + "${chip_root}/data_model/1.5.1/device_types/CastingVideoClient.xml", + "${chip_root}/data_model/1.5.1/device_types/CastingVideoPlayer.xml", + "${chip_root}/data_model/1.5.1/device_types/Chime.xml", + "${chip_root}/data_model/1.5.1/device_types/Closure.xml", + "${chip_root}/data_model/1.5.1/device_types/ClosureController.xml", + "${chip_root}/data_model/1.5.1/device_types/ClosurePanel.xml", + "${chip_root}/data_model/1.5.1/device_types/ColorDimmerSwitch.xml", + "${chip_root}/data_model/1.5.1/device_types/ColorTemperatureLight.xml", + "${chip_root}/data_model/1.5.1/device_types/ContactSensor.xml", + "${chip_root}/data_model/1.5.1/device_types/ContentApp.xml", + "${chip_root}/data_model/1.5.1/device_types/ControlBridge.xml", + "${chip_root}/data_model/1.5.1/device_types/CookSurface.xml", + "${chip_root}/data_model/1.5.1/device_types/Cooktop.xml", + "${chip_root}/data_model/1.5.1/device_types/DeviceEnergyManagement.xml", + "${chip_root}/data_model/1.5.1/device_types/DimmableLight.xml", + "${chip_root}/data_model/1.5.1/device_types/DimmablePlug-InUnit.xml", + "${chip_root}/data_model/1.5.1/device_types/DimmerSwitch.xml", + "${chip_root}/data_model/1.5.1/device_types/Dishwasher.xml", + "${chip_root}/data_model/1.5.1/device_types/DoorLock.xml", + "${chip_root}/data_model/1.5.1/device_types/DoorLockController.xml", + "${chip_root}/data_model/1.5.1/device_types/Doorbell.xml", + "${chip_root}/data_model/1.5.1/device_types/EVSE.xml", + "${chip_root}/data_model/1.5.1/device_types/ElectricalEnergyTariff.xml", + "${chip_root}/data_model/1.5.1/device_types/ElectricalMeter.xml", + "${chip_root}/data_model/1.5.1/device_types/ElectricalSensor.xml", + "${chip_root}/data_model/1.5.1/device_types/ElectricalUtilityMeter.xml", + "${chip_root}/data_model/1.5.1/device_types/ExtendedColorLight.xml", + "${chip_root}/data_model/1.5.1/device_types/ExtractorHood.xml", + "${chip_root}/data_model/1.5.1/device_types/Fan.xml", + "${chip_root}/data_model/1.5.1/device_types/FloodlightCamera.xml", + "${chip_root}/data_model/1.5.1/device_types/FlowSensor.xml", + "${chip_root}/data_model/1.5.1/device_types/GenericSwitch.xml", + "${chip_root}/data_model/1.5.1/device_types/HeatPump.xml", + "${chip_root}/data_model/1.5.1/device_types/HumiditySensor.xml", + "${chip_root}/data_model/1.5.1/device_types/Intercom.xml", + "${chip_root}/data_model/1.5.1/device_types/IrrigationSystem.xml", + "${chip_root}/data_model/1.5.1/device_types/JointFabricAdmin.xml", + "${chip_root}/data_model/1.5.1/device_types/LaundryDryer.xml", + "${chip_root}/data_model/1.5.1/device_types/LaundryWasher.xml", + "${chip_root}/data_model/1.5.1/device_types/LightSensor.xml", + "${chip_root}/data_model/1.5.1/device_types/MeterReferencePoint.xml", + "${chip_root}/data_model/1.5.1/device_types/MicrowaveOven.xml", + "${chip_root}/data_model/1.5.1/device_types/ModeSelectDeviceType.xml", + "${chip_root}/data_model/1.5.1/device_types/MountedDimmableLoadControl.xml", + "${chip_root}/data_model/1.5.1/device_types/MountedOnOffControl.xml", + "${chip_root}/data_model/1.5.1/device_types/NetworkInfraManager.xml", + "${chip_root}/data_model/1.5.1/device_types/OccupancySensor.xml", + "${chip_root}/data_model/1.5.1/device_types/OnOffLight.xml", + "${chip_root}/data_model/1.5.1/device_types/OnOffLightSwitch.xml", + "${chip_root}/data_model/1.5.1/device_types/OnOffPlug-inUnit.xml", + "${chip_root}/data_model/1.5.1/device_types/OnOffSensor.xml", + "${chip_root}/data_model/1.5.1/device_types/OtaProvider.xml", + "${chip_root}/data_model/1.5.1/device_types/OtaRequestor.xml", + "${chip_root}/data_model/1.5.1/device_types/Oven.xml", + "${chip_root}/data_model/1.5.1/device_types/PowerSource.xml", + "${chip_root}/data_model/1.5.1/device_types/PressureSensor.xml", + "${chip_root}/data_model/1.5.1/device_types/Pump.xml", + "${chip_root}/data_model/1.5.1/device_types/PumpController.xml", + "${chip_root}/data_model/1.5.1/device_types/RainSensor.xml", + "${chip_root}/data_model/1.5.1/device_types/Refrigerator.xml", + "${chip_root}/data_model/1.5.1/device_types/RoboticVacuumCleaner.xml", + "${chip_root}/data_model/1.5.1/device_types/RoomAirConditioner.xml", + "${chip_root}/data_model/1.5.1/device_types/RootNodeDeviceType.xml", + "${chip_root}/data_model/1.5.1/device_types/SecondaryNetworkInterface.xml", + "${chip_root}/data_model/1.5.1/device_types/SmokeCOAlarm.xml", + "${chip_root}/data_model/1.5.1/device_types/SnapshotCamera.xml", + "${chip_root}/data_model/1.5.1/device_types/SoilSensor.xml", + "${chip_root}/data_model/1.5.1/device_types/SolarPower.xml", + "${chip_root}/data_model/1.5.1/device_types/Speaker.xml", + "${chip_root}/data_model/1.5.1/device_types/TemperatureControlledCabinet.xml", + "${chip_root}/data_model/1.5.1/device_types/TemperatureSensor.xml", + "${chip_root}/data_model/1.5.1/device_types/Thermostat.xml", + "${chip_root}/data_model/1.5.1/device_types/ThermostatController.xml", + "${chip_root}/data_model/1.5.1/device_types/ThreadBorderRouter.xml", + "${chip_root}/data_model/1.5.1/device_types/VideoDoorbell.xml", + "${chip_root}/data_model/1.5.1/device_types/VideoRemoteControl.xml", + "${chip_root}/data_model/1.5.1/device_types/WaterFreezeDetector.xml", + "${chip_root}/data_model/1.5.1/device_types/WaterHeater.xml", + "${chip_root}/data_model/1.5.1/device_types/WaterLeakDetector.xml", + "${chip_root}/data_model/1.5.1/device_types/WaterValve.xml", + "${chip_root}/data_model/1.5.1/device_types/WindowCovering.xml", + "${chip_root}/data_model/1.5.1/device_types/WindowCoveringController.xml", + "${chip_root}/data_model/1.5.1/globals/Bitmaps.xml", + "${chip_root}/data_model/1.5.1/globals/Commands.xml", + "${chip_root}/data_model/1.5.1/globals/Enums.xml", + "${chip_root}/data_model/1.5.1/globals/Structs.xml", + "${chip_root}/data_model/1.5.1/globals/TypeDefs.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Closure-Cabinet.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Closure-Covering.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Closure-Window.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Closure.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-ClosurePanel.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-CommodityTariff-Chronology.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-CommodityTariff-Commodity.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-CommodityTariff-Flow.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Common-Area.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Common-Closure.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Common-CompassDirection.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Common-CompassLocation.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Common-Direction.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Common-Landmark.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Common-Level.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Common-Location.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Common-Number.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Common-Position.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Common-RelativePosition.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-ElectricalMeasurement.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Laundry.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-PowerSource.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Refrigerator.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-RoomAirConditioner.xml", + "${chip_root}/data_model/1.5.1/namespaces/Namespace-Switches.xml", ] diff --git a/src/python_testing/matter_testing_infrastructure/generate_data_model_xmls_gni.py b/src/python_testing/matter_testing_infrastructure/generate_data_model_xmls_gni.py index 470913b33af..43dbde527a1 100644 --- a/src/python_testing/matter_testing_infrastructure/generate_data_model_xmls_gni.py +++ b/src/python_testing/matter_testing_infrastructure/generate_data_model_xmls_gni.py @@ -21,16 +21,18 @@ package without requiring a full chip SDK checkout. """ import os +from pathlib import Path import jinja2 # Set chip_root to be dynamically based on the script's location chip_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../..")) data_model_dir = os.path.join(chip_root, "data_model") +credentials_dir = os.path.join(chip_root, "credentials") # Template for generating the GNI file content with proper indentation GNI_HEADER = """\ -# Copyright (c) 2024 Project CHIP Authors +# Copyright (c) 2024-2025 Project CHIP Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -47,14 +49,16 @@ # This file is generated by # src/python_testing/matter_testing_infrastructure/generate_data_model_xmls_gni.py # -# Manually re-generate this file on any changes to the data_model directory. +# Manually re-generate this file on any changes to the files in this directory. import("//build_overrides/chip.gni") """ +DM_PREFIX = "data_model_XMLS" +CREDENTIALS_PREFIX = "credentials" GNI_TEMPLATE = """\ -data_model_XMLS_{{ dir }} = [ +{{ prefix }}_{{ dir }} = [ {% for name in file_list %} "{{ name }}", {% endfor %} @@ -63,32 +67,37 @@ """ -def get_data_model_file_names(directory: str): - ''' Function to find and collect all .xml files''' +def get_file_names(directory: str, file_globs: list[str]): + ''' Function to find and collect all files matching glob patterns''' file_list = [] - for root, _, files in os.walk(directory): - for file in files: - if file.endswith(".xml"): - # Replace absolute path with `${chip_root}` for GNI compatibility - relative_path = os.path.join("${chip_root}", os.path.relpath(root, chip_root), file) - file_list.append(relative_path) + globs = [] + for g in file_globs: + globs += Path(directory).rglob(g) + for file in globs: + # Replace absolute path with `${chip_root}` for GNI compatibility + relative_path = os.path.join("${chip_root}", os.path.relpath(file, chip_root)) + file_list.append(relative_path) # Sort files alphabetically file_list.sort() return file_list -def generate_gni_file(): +def _generate_gni_file(zip_dir: str, prefix: str, file_extensions: tuple[str], output_filename: str): '''Main function to generate the data_model_xmls.gni file''' environment = jinja2.Environment(trim_blocks=True, lstrip_blocks=True) template = environment.from_string(GNI_TEMPLATE) output_content_per_dir = [] # Step 1: Find all files and create the sorted file list - dirs = sorted([d for d in os.listdir(data_model_dir) if os.path.isdir(os.path.join(data_model_dir, d))]) + if zip_dir == credentials_dir: + dirs = ["development", "production"] + else: + dirs = sorted([d for d in os.listdir(zip_dir) if os.path.isdir(os.path.join(zip_dir, d))]) + for directory in dirs: - file_list = get_data_model_file_names(os.path.join(data_model_dir, directory)) + file_list = get_file_names(os.path.join(zip_dir, directory), file_extensions) # Step 2: Render the template with the file list - output_content_per_dir.append(template.render(dir=directory.replace('.', '_'), file_list=file_list)) + output_content_per_dir.append(template.render(prefix=prefix, dir=directory.replace('.', '_'), file_list=file_list)) output_content = GNI_HEADER + "".join(output_content_per_dir) @@ -100,7 +109,7 @@ def generate_gni_file(): base_dir = os.path.abspath(os.path.join(script_dir, "../..")) # Go up two levels to src/python_testing/ # Now append `matter_testing_infrastructure` output_dir = os.path.join(base_dir, "python_testing", "matter_testing_infrastructure") - output_file = os.path.join(output_dir, "data_model_xmls.gni") + output_file = os.path.join(output_dir, output_filename) # Step 5: Write the rendered content to the output file os.makedirs(output_dir, exist_ok=True) # Ensure the output directory exists @@ -109,6 +118,16 @@ def generate_gni_file(): print(f"{output_file} has been generated successfully.") +def generate_dm_gni_file(): + _generate_gni_file(data_model_dir, DM_PREFIX, ["*.xml"], "data_model_xmls.gni") + + +def generate_credential_gni_file(): + _generate_gni_file(credentials_dir, CREDENTIALS_PREFIX, [ + "paa-root-certs/**/*.der", "paa-root-certs/**/*.pem", "cd-certs/**/*.der", "cd-certs/**/*.pem"], "credential_files.gni") + + # Run the function to generate the .gni file if __name__ == "__main__": - generate_gni_file() + generate_dm_gni_file() + generate_credential_gni_file() diff --git a/src/python_testing/matter_testing_infrastructure/matter/testing/choice_conformance.py b/src/python_testing/matter_testing_infrastructure/matter/testing/choice_conformance.py index 68d3a14a277..dd4e32858d5 100644 --- a/src/python_testing/matter_testing_infrastructure/matter/testing/choice_conformance.py +++ b/src/python_testing/matter_testing_infrastructure/matter/testing/choice_conformance.py @@ -15,7 +15,7 @@ # limitations under the License. # -from matter.testing.conformance import Choice, ConformanceDecisionWithChoice +from matter.testing.conformance import Choice, ConformanceAssessmentData, ConformanceDecisionWithChoice from matter.testing.global_attribute_ids import GlobalAttributeIds from matter.testing.problem_notices import AttributePathLocation, ProblemNotice, ProblemSeverity from matter.testing.spec_parsing import XmlCluster @@ -47,7 +47,7 @@ def _evaluate_choices(location: AttributePathLocation, counts: dict[Choice, int] return problems -def evaluate_feature_choice_conformance(endpoint_id: int, cluster_id: int, xml_clusters: dict[int, XmlCluster], feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> list[ChoiceConformanceProblemNotice]: +def evaluate_feature_choice_conformance(endpoint_id: int, cluster_id: int, xml_clusters: dict[int, XmlCluster], conformance_assessment_data: ConformanceAssessmentData) -> list[ChoiceConformanceProblemNotice]: all_features = [uint(1 << i) for i in range(32)] all_features = [f for f in all_features if f in xml_clusters[cluster_id].features.keys()] @@ -55,36 +55,38 @@ def evaluate_feature_choice_conformance(endpoint_id: int, cluster_id: int, xml_c counts: dict[Choice, int] = {} for f in all_features: xml_feature = xml_clusters[cluster_id].features[f] - conformance_decision_with_choice = xml_feature.conformance(feature_map, attribute_list, all_command_list) - _add_to_counts_if_required(conformance_decision_with_choice, (feature_map & f) != 0, counts) + conformance_decision_with_choice = xml_feature.conformance(conformance_assessment_data) + _add_to_counts_if_required(conformance_decision_with_choice, (conformance_assessment_data.feature_map & f) != 0, counts) location = AttributePathLocation(endpoint_id=endpoint_id, cluster_id=cluster_id, attribute_id=GlobalAttributeIds.FEATURE_MAP_ID) return _evaluate_choices(location, counts) -def evaluate_attribute_choice_conformance(endpoint_id: int, cluster_id: int, xml_clusters: dict[int, XmlCluster], feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> list[ChoiceConformanceProblemNotice]: +def evaluate_attribute_choice_conformance(endpoint_id: int, cluster_id: int, xml_clusters: dict[int, XmlCluster], conformance_assessment_data: ConformanceAssessmentData) -> list[ChoiceConformanceProblemNotice]: all_attributes = xml_clusters[cluster_id].attributes.keys() counts: dict[Choice, int] = {} for attribute_id in all_attributes: conformance_decision_with_choice = xml_clusters[cluster_id].attributes[attribute_id].conformance( - feature_map, attribute_list, all_command_list) - _add_to_counts_if_required(conformance_decision_with_choice, attribute_id in attribute_list, counts) + conformance_assessment_data) + _add_to_counts_if_required(conformance_decision_with_choice, + attribute_id in conformance_assessment_data.attribute_list, counts) location = AttributePathLocation(endpoint_id=endpoint_id, cluster_id=cluster_id, attribute_id=GlobalAttributeIds.ATTRIBUTE_LIST_ID) return _evaluate_choices(location, counts) -def evaluate_command_choice_conformance(endpoint_id: int, cluster_id: int, xml_clusters: dict[int, XmlCluster], feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> list[ChoiceConformanceProblemNotice]: +def evaluate_command_choice_conformance(endpoint_id: int, cluster_id: int, xml_clusters: dict[int, XmlCluster], conformance_assessment_data: ConformanceAssessmentData) -> list[ChoiceConformanceProblemNotice]: all_commands = xml_clusters[cluster_id].accepted_commands.keys() counts: dict[Choice, int] = {} for command_id in all_commands: conformance_decision_with_choice = xml_clusters[cluster_id].accepted_commands[command_id].conformance( - feature_map, attribute_list, all_command_list) - _add_to_counts_if_required(conformance_decision_with_choice, command_id in all_command_list, counts) + conformance_assessment_data) + _add_to_counts_if_required(conformance_decision_with_choice, + command_id in conformance_assessment_data.all_command_list, counts) location = AttributePathLocation(endpoint_id=endpoint_id, cluster_id=cluster_id, attribute_id=GlobalAttributeIds.ACCEPTED_COMMAND_LIST_ID) diff --git a/src/python_testing/matter_testing_infrastructure/matter/testing/conformance.py b/src/python_testing/matter_testing_infrastructure/matter/testing/conformance.py index c7a11bf5afa..9981211804f 100644 --- a/src/python_testing/matter_testing_infrastructure/matter/testing/conformance.py +++ b/src/python_testing/matter_testing_infrastructure/matter/testing/conformance.py @@ -33,6 +33,7 @@ commands. """ +import operator import xml.etree.ElementTree as ElementTree from dataclasses import dataclass from enum import Enum, auto @@ -52,11 +53,13 @@ OR_TERM = 'orTerm' NOT_TERM = 'notTerm' GREATER_TERM = 'greaterTerm' +GREATER_EQUAL_TERM = 'greaterOrEqualTerm' FEATURE_TAG = 'feature' ATTRIBUTE_TAG = 'attribute' COMMAND_TAG = 'command' CONDITION_TAG = 'condition' LITERAL_TAG = 'literal' +REVISION_TAG = 'revision' ZIGBEE_CONDITION = 'zigbee' @@ -121,6 +124,26 @@ class ConformanceParseParameters: command_map: dict[str, uint] +@dataclass +class ConformanceAssessmentData: + feature_map: uint + attribute_list: list[uint] + all_command_list: list[uint] + cluster_revision: uint + + +@dataclass +class EmptyClusterGlobalAttributes(ConformanceAssessmentData): + def __init__(self): + self.feature_map = uint(0) + self.attribute_list = [] + self.all_command_list = [] + self.cluster_revision = uint(1) + + +EMPTY_CLUSTER_GLOBAL_ATTRIBUTES = EmptyClusterGlobalAttributes() + + def conformance_allowed(conformance_decision: ConformanceDecisionWithChoice, allow_provisional: bool): if conformance_decision.decision in [ConformanceDecision.NOT_APPLICABLE, ConformanceDecision.DISALLOWED]: return False @@ -131,16 +154,16 @@ def conformance_allowed(conformance_decision: ConformanceDecisionWithChoice, all def is_disallowed(conformance: Callable): # Deprecated and disallowed conformances will come back as disallowed regardless of the implemented features / attributes / etc. - return conformance(0, [], []).decision == ConformanceDecision.DISALLOWED + return conformance(EMPTY_CLUSTER_GLOBAL_ATTRIBUTES).decision == ConformanceDecision.DISALLOWED def is_provisional(conformance: Callable): - return conformance(0, [], []).decision == ConformanceDecision.PROVISIONAL + return conformance(EMPTY_CLUSTER_GLOBAL_ATTRIBUTES).decision == ConformanceDecision.PROVISIONAL @dataclass class Conformance: - def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> ConformanceDecisionWithChoice: + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: ''' Evaluates the conformance of a specific cluster or device type element. feature_map: The feature_map for the given cluster for which this conformance applies. Used to evaluate feature conformances @@ -155,7 +178,7 @@ def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_li class zigbee(Conformance): - def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> ConformanceDecisionWithChoice: + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: return ConformanceDecisionWithChoice(ConformanceDecision.NOT_APPLICABLE) def __str__(self): @@ -163,7 +186,7 @@ def __str__(self): class mandatory(Conformance): - def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> ConformanceDecisionWithChoice: + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: return ConformanceDecisionWithChoice(ConformanceDecision.MANDATORY) def __str__(self): @@ -174,7 +197,7 @@ class optional(Conformance): def __init__(self, choice: Optional[Choice] = None): self.choice = choice - def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> ConformanceDecisionWithChoice: + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: return ConformanceDecisionWithChoice(ConformanceDecision.OPTIONAL, self.choice) def __str__(self): @@ -182,7 +205,7 @@ def __str__(self): class deprecated(Conformance): - def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> ConformanceDecisionWithChoice: + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: return ConformanceDecisionWithChoice(ConformanceDecision.DISALLOWED) def __str__(self): @@ -190,7 +213,7 @@ def __str__(self): class disallowed(Conformance): - def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> ConformanceDecisionWithChoice: + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: return ConformanceDecisionWithChoice(ConformanceDecision.DISALLOWED) def __str__(self): @@ -198,27 +221,54 @@ def __str__(self): class provisional(Conformance): - def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> ConformanceDecisionWithChoice: + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: return ConformanceDecisionWithChoice(ConformanceDecision.PROVISIONAL) def __str__(self): return 'P' -class literal(Conformance): +class ValueConformance(Conformance): + def __call__(self, conformance_assessment_data: ConformanceAssessmentData): + # This should never be called + raise ConformanceException('Value conformance function should not be called - this is simply a value holder') + + def get_value(self, conformance_assessment_data: ConformanceAssessmentData) -> int: + raise ConformanceException('Base get_value function should not be called directly') + + +class literal(ValueConformance): def __init__(self, value: str): # base=0 allows automatic detection of number format from string prefix: # "10" -> 10 (decimal), "0x10" -> 16 (hex), "0o10" -> 8 (octal), "0b10" -> 2 (binary) # This is needed because XML literal values can be in different formats self.value = int(value, 0) - def __call__(self): - # This should never be called - raise ConformanceException('Literal conformance function should not be called - this is simply a value holder') - def __str__(self): return str(self.value) + def get_value(self, conformance_assessment_data: ConformanceAssessmentData) -> int: + return self.value + + +class revision(ValueConformance): + def __init__(self, value: str): + self.value: Optional[int] + if value.lower() == 'current': + self.value = None + else: + self.value = int(value, 0) + + def __str__(self): + if self.value is None: + return "Rev" + return f'v{str(self.value)}' + + def get_value(self, conformance_assessment_data: ConformanceAssessmentData) -> int: + if self.value is None: + return conformance_assessment_data.cluster_revision + return self.value + # Conformance options that apply regardless of the element set of the cluster or device BASIC_CONFORMANCE: dict[str, Conformance] = { @@ -235,8 +285,8 @@ def __init__(self, requiredFeature: uint, code: str): self.requiredFeature = requiredFeature self.code = code - def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> ConformanceDecisionWithChoice: - if self.requiredFeature & feature_map != 0: + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: + if self.requiredFeature & conformance_assessment_data.feature_map != 0: return ConformanceDecisionWithChoice(ConformanceDecision.MANDATORY) return ConformanceDecisionWithChoice(ConformanceDecision.NOT_APPLICABLE) @@ -250,7 +300,7 @@ class device_feature(Conformance): def __init__(self, feature: str): self.feature = feature - def __call__(self, feature_map: uint = uint(0), attribute_list: list[uint] = [], all_command_list: list[uint] = []) -> ConformanceDecisionWithChoice: + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: if (self.feature.lower() == "matter"): return ConformanceDecisionWithChoice(ConformanceDecision.MANDATORY) elif (self.feature.lower() == 'zigbee'): @@ -267,8 +317,8 @@ def __init__(self, requiredAttribute: uint, name: str): self.requiredAttribute = requiredAttribute self.name = name - def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> ConformanceDecisionWithChoice: - if self.requiredAttribute in attribute_list: + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: + if self.requiredAttribute in conformance_assessment_data.attribute_list: return ConformanceDecisionWithChoice(ConformanceDecision.MANDATORY) return ConformanceDecisionWithChoice(ConformanceDecision.NOT_APPLICABLE) @@ -281,8 +331,8 @@ def __init__(self, requiredCommand: uint, name: str): self.requiredCommand = requiredCommand self.name = name - def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> ConformanceDecisionWithChoice: - if self.requiredCommand in all_command_list: + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: + if self.requiredCommand in conformance_assessment_data.all_command_list: return ConformanceDecisionWithChoice(ConformanceDecision.MANDATORY) return ConformanceDecisionWithChoice(ConformanceDecision.NOT_APPLICABLE) @@ -301,8 +351,8 @@ def __init__(self, op: Conformance, choice: Optional[Choice] = None): self.op = op self.choice = choice - def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> ConformanceDecisionWithChoice: - decision_with_choice = self.op(feature_map, attribute_list, all_command_list) + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: + decision_with_choice = self.op(conformance_assessment_data) if decision_with_choice.decision in [ConformanceDecision.MANDATORY, ConformanceDecision.OPTIONAL]: return ConformanceDecisionWithChoice(ConformanceDecision.OPTIONAL, self.choice) @@ -319,8 +369,8 @@ class mandatory_wrapper(Conformance): def __init__(self, op: Conformance): self.op = op - def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> ConformanceDecisionWithChoice: - return self.op(feature_map, attribute_list, all_command_list) + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: + return self.op(conformance_assessment_data) def __str__(self): return strip_outer_parentheses(str(self.op)) @@ -332,11 +382,11 @@ def __init__(self, op: Conformance): raise ChoiceConformanceException('NOT operation called on choice conformance') self.op = op - def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> ConformanceDecisionWithChoice: + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: # not operations can't be used with anything that returns DISALLOWED # not operations also can't be used with things that are optional # ie, ![AB] doesn't make sense, nor does !O - decision_with_choice = self.op(feature_map, attribute_list, all_command_list) + decision_with_choice = self.op(conformance_assessment_data) if decision_with_choice.decision in [ConformanceDecision.DISALLOWED, ConformanceDecision.PROVISIONAL]: raise ConformanceException('NOT operation on optional or disallowed item') # Features in device types degrade to optional so a not operation here is still optional because we don't have any way to verify the features since they're not exposed anywhere @@ -360,9 +410,9 @@ def __init__(self, op_list: list[Conformance]): raise ChoiceConformanceException('AND operation with internal choice conformance') self.op_list = op_list - def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> ConformanceDecisionWithChoice: + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: for op in self.op_list: - decision_with_choice = op(feature_map, attribute_list, all_command_list) + decision_with_choice = op(conformance_assessment_data) # and operations can't happen on optional or disallowed if decision_with_choice.decision == ConformanceDecision.OPTIONAL and all(type(op) == device_feature for op in self.op_list): return decision_with_choice @@ -388,9 +438,9 @@ def __init__(self, op_list: list[Conformance]): raise ChoiceConformanceException('OR operation with internal choice conformance') self.op_list = op_list - def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> ConformanceDecisionWithChoice: + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: for op in self.op_list: - decision_with_choice = op(feature_map, attribute_list, all_command_list) + decision_with_choice = op(conformance_assessment_data) if decision_with_choice.decision in [ConformanceDecision.DISALLOWED, ConformanceDecision.PROVISIONAL]: raise ConformanceException('OR operation on optional or disallowed item') elif decision_with_choice.decision == ConformanceDecision.NOT_APPLICABLE: @@ -406,31 +456,57 @@ def __str__(self): return f'({" | ".join(op_strs)})' -class greater_operation(Conformance): - def _type_ok(self, op: Conformance): - return type(op) == attribute or type(op) == literal +class ArithmeticConformance(Conformance): + ''' Base class for arithmetic operations - do not use directly.''' + + def _type_ok(self, op1: Conformance, op2: Conformance): + def _is_valid_operand(op: Conformance) -> bool: + return issubclass(type(op), ValueConformance) or type(op) == attribute + return _is_valid_operand(op1) and _is_valid_operand(op2) def __init__(self, op1: Conformance, op2: Conformance): - if not self._type_ok(op1) or not self._type_ok(op2): - raise ConformanceException('Arithmetic operations can only have attribute or literal value children') + if not self._type_ok(op1, op2): + raise ConformanceException('Arithmetic operations can only have attribute + literal or revision children') self.op1 = op1 self.op2 = op2 + self.operator = operator.gt + self.opstr = "???" - def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> ConformanceDecisionWithChoice: + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: + # If there are any non-value ops, return optional, as it represents an attribute comparison and we don't have the data + # for that currently. # For now, this is fully optional, need to implement this properly later, but it requires access to the actual attribute values # We need to reach into the attribute, but can't use it directly because the attribute callable is an EXISTENCE check and # the arithmetic functions require a value. + if hasattr(self.op1, 'get_value') and hasattr(self.op2, 'get_value'): + if self.operator(self.op1.get_value(conformance_assessment_data), self.op2.get_value(conformance_assessment_data)): + return ConformanceDecisionWithChoice(ConformanceDecision.MANDATORY) + return ConformanceDecisionWithChoice(ConformanceDecision.NOT_APPLICABLE) return ConformanceDecisionWithChoice(ConformanceDecision.OPTIONAL) def __str__(self): - return f'{str(self.op1)} > {str(self.op2)}' + return f'{str(self.op1)} {self.opstr} {str(self.op2)}' + + +class greater_operation(ArithmeticConformance): + def __init__(self, op1: Conformance, op2: Conformance): + super().__init__(op1, op2) + self.operator = operator.gt + self.opstr = '>' + + +class greater_equal_operation(ArithmeticConformance): + def __init__(self, op1: Conformance, op2: Conformance): + super().__init__(op1, op2) + self.operator = operator.ge + self.opstr = '>=' class otherwise(Conformance): def __init__(self, op_list: list[Conformance]): self.op_list = op_list - def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> ConformanceDecisionWithChoice: + def __call__(self, conformance_assessment_data: ConformanceAssessmentData) -> ConformanceDecisionWithChoice: # Otherwise operations apply from left to right. If any of them # has a definite decision (optional, mandatory or disallowed), that is the one that applies # Provisional items are meant to be marked as the first item in the list @@ -438,7 +514,7 @@ def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_li # For O,D, optional applies (leftmost), but we should consider some way to warn here as well, # possibly in another function for op in self.op_list: - decision_with_choice = op(feature_map, attribute_list, all_command_list) + decision_with_choice = op(conformance_assessment_data) if decision_with_choice.decision == ConformanceDecision.NOT_APPLICABLE: continue return decision_with_choice @@ -494,9 +570,14 @@ def parse_basic_callable_from_xml(element: ElementTree.Element) -> Conformance: raise ConformanceException( f"Literal tag missing 'value' attribute: {ElementTree.tostring(element, encoding='unicode').strip()}") return literal(literal_value) - else: - raise BasicConformanceException( - f'parse_basic_callable_from_xml called for unknown element {str(element.tag)} {str(element.attrib)}') + if element.tag == REVISION_TAG: + value = element.get('value') + if value is None: + raise ConformanceException( + f"Revision tag missing 'value' attribute: {ElementTree.tostring(element, encoding='unicode').strip()}") + return revision(value) + raise BasicConformanceException( + f'parse_basic_callable_from_xml called for unknown element {str(element.tag)} {str(element.attrib)}') def parse_wrapper_callable_from_xml(element: ElementTree.Element, ops: list[Conformance]) -> Conformance: @@ -549,8 +630,11 @@ def parse_wrapper_callable_from_xml(element: ElementTree.Element, ops: list[Conf if len(ops) != 2: raise ConformanceException(f'Greater than term found with more than two subelements {list(element)}') return greater_operation(ops[0], ops[1]) - else: - raise ConformanceException(f'Unexpected conformance tag with children {element}') + if element.tag == GREATER_EQUAL_TERM: + if len(ops) != 2: + raise ConformanceException(f'Greater than term found with more than two subelements {list(element)}') + return greater_equal_operation(ops[0], ops[1]) + raise ConformanceException(f'Unexpected conformance tag with children {element}') def parse_device_type_callable_from_xml(element: ElementTree.Element) -> Conformance: diff --git a/src/python_testing/matter_testing_infrastructure/matter/testing/credentials.py b/src/python_testing/matter_testing_infrastructure/matter/testing/credentials.py new file mode 100644 index 00000000000..870c54d8439 --- /dev/null +++ b/src/python_testing/matter_testing_infrastructure/matter/testing/credentials.py @@ -0,0 +1,87 @@ +# +# Copyright (c) 2025 Project CHIP Authors +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import importlib +import importlib.resources as pkg_resources +import os +import zipfile +from enum import Enum, auto +from importlib.abc import Traversable +from typing import Union + + +class CredentialSource(Enum): + kDevelopment = auto() + kProduction = auto() + + @property + def dirname(self): + if self == CredentialSource.kDevelopment: + return "development" + if self == CredentialSource.kProduction: + return "production" + raise KeyError("Invalid enum: %r" % self) + + +class CertificatePurpose(Enum): + kPAA = auto() + kCD = auto() + + @property + def dirname(self): + if self == CertificatePurpose.kPAA: + return "paa-root-certs" + if self == CertificatePurpose.kCD: + return "cd-certs" + raise KeyError("Invalid enum: %r" % self) + + +def _get_credentials(credential_source: Union[CredentialSource, Traversable], certificate_purpose: CertificatePurpose) -> Traversable: + # Early return if data_model_directory is already a Traversable type + if not isinstance(credential_source, CredentialSource): + # data_model_directory is a Traversable (e.g. pathlib.Path to an extracted root) + # Return directly as per the docstring - it should already contain the correct directory structure + return credential_source + + # If it's a prebuilt directory, build the path based on the requested certificates + zip_file_traversable = pkg_resources.files(importlib.import_module('matter.testing')).joinpath( + 'credentials').joinpath(credential_source.dirname).joinpath('allfiles.zip') + + # Avoid returning a zipfile.Path backed by a closed file handle. Build Path from the filesystem path + # so the ZipFile lifecycle is managed by zipfile.Path itself. + # mypy: Traversable does not declare __fspath__, but runtime object from importlib.resources + # is a FileSystem resource that implements it. Safe to coerce for zipfile.Path usage. + zip_path = os.fspath(zip_file_traversable) # type: ignore[call-overload] + zip_root = zipfile.Path(zip_path) + return zip_root / certificate_purpose.dirname + + +def get_paa_root_certs(credential_source: Union[CredentialSource, Traversable]) -> Traversable: + """ + Get the directory of the PAA root certs of a specific source from either a directory or stored zip. + + `credential_source` given as a path MUST be of type Traversable (often `pathlib.Path(somepathstring)`). + """ + return _get_credentials(credential_source, CertificatePurpose.kPAA) + + +def get_cd_certs(credential_source: Union[CredentialSource, Traversable]) -> Traversable: + """ + Get the directory of the CD certs of a specific source from either a directory or stored zip. + + `credential_source` given as a path MUST be of type Traversable (often `pathlib.Path(somepathstring)`). + """ + return _get_credentials(credential_source, CertificatePurpose.kCD) diff --git a/src/python_testing/matter_testing_infrastructure/matter/testing/matter_testing.py b/src/python_testing/matter_testing_infrastructure/matter/testing/matter_testing.py index 639c51f7079..6de9b3292b2 100644 --- a/src/python_testing/matter_testing_infrastructure/matter/testing/matter_testing.py +++ b/src/python_testing/matter_testing_infrastructure/matter/testing/matter_testing.py @@ -52,6 +52,7 @@ import matter.native import matter.testing.global_stash as global_stash from matter.clusters import Attribute, ClusterObjects +from matter.exceptions import ChipStackError from matter.interaction_model import InteractionModelError, Status from matter.setup_payload import SetupPayload from matter.testing.commissioning import (CommissioningInfo, CustomCommissioningParameters, SetupPayloadInfo, commission_devices, @@ -1315,6 +1316,97 @@ def user_verify_push_av_stream(self, prompt_msg: str) -> bool: ) return skipped + def _expire_sessions_on_all_controllers(self): + """Helper method to expire sessions on all active controllers via the fabric admin interface. + + This method iterates through all certificate authorities and their fabric admins to expire + sessions on all active controllers. This ensures all controllers can reconnect after a device + reboot or factory reset. + """ + LOGGER.info("Expiring sessions on all active controllers") + for ca in self.matter_stack.certificate_authorities: + for fabric_admin in ca.adminList: + for controller in fabric_admin._activeControllers: + if controller.isActive: + try: + controller.ExpireSessions(self.dut_node_id) + LOGGER.info(f"Expired sessions on controller with nodeId {controller.nodeId}") + except ChipStackError as e: # chipstack-ok + LOGGER.warning(f"Failed to expire sessions on controller {controller.nodeId}: {e}") + + async def request_device_reboot(self): + """Request a reboot of the Device Under Test (DUT). + + This method handles device reboots in both CI and development environments (via run_python_test.py test runner script) + and also manual testing scenarios (via user input). It expires existing sessions to allow for controllers to reconnect + to the DUT after the reboot. + + Returns: + None + """ + # Check if restart flag file is available (indicates test runner supports app restart) + restart_flag_file = self.get_restart_flag_file() + + if not restart_flag_file: + # No restart flag file: ask user to manually reboot + self.wait_for_user_input(prompt_msg="Reboot the DUT. Press Enter when ready.\n") + + # After manual reboot, expire previous sessions so that we can re-establish connections + self._expire_sessions_on_all_controllers() + LOGGER.info("Manual device reboot completed") + + else: + try: + # Create the restart flag file to signal the test runner + with open(restart_flag_file, "w") as f: + f.write("restart") + LOGGER.info("Created restart flag file to signal app reboot") + + # The test runner will automatically wait for the app-ready-pattern before continuing + + # Expire sessions and re-establish connections + self._expire_sessions_on_all_controllers() + LOGGER.info("App restart completed successfully") + + except Exception as e: + LOGGER.error(f"Failed to reboot app: {e}") + asserts.fail(f"App reboot failed: {e}") + + async def request_device_factory_reset(self): + """Request a factory reset of the Device Under Test (DUT). + + This method handles factory resets in both CI and development environments (via run_python_test.py test runner script) + and also manual testing scenarios (via user input). + It will expire existing sessions to allow for controllers to reconnect to the DUT after the factory reset. + """ + # Check if restart flag file is available (indicates test runner supports app reboot) + restart_flag_file = self.get_restart_flag_file() + + if not restart_flag_file: + # No restart flag file: ask user to manually factory reset + self.wait_for_user_input(prompt_msg="Factory reset the DUT. Press Enter when ready.\n") + + # After manual factory reset, expire previous sessions so that we can re-establish connections + self._expire_sessions_on_all_controllers() + LOGGER.info("Manual device factory reset completed") + + else: + try: + # Create the restart flag file to signal the test runner + with open(restart_flag_file, "w") as f: + f.write("reset") + LOGGER.info("Created restart flag file to signal app factory reset") + + # The test runner will automatically wait for the app-ready-pattern before continuing + + # Expire sessions and re-establish connections + self._expire_sessions_on_all_controllers() + LOGGER.info("App factory reset completed successfully") + + except Exception as e: + LOGGER.error(f"Failed to factory reset app: {e}") + asserts.fail(f"App factory reset failed: {e}") + def _async_runner(body, self: MatterBaseTest, *args, **kwargs): """Runs an async function within the test's event loop with a timeout. diff --git a/src/python_testing/matter_testing_infrastructure/matter/testing/spec_parsing.py b/src/python_testing/matter_testing_infrastructure/matter/testing/spec_parsing.py index b53d7cba2a4..96ea8df4ea8 100644 --- a/src/python_testing/matter_testing_infrastructure/matter/testing/spec_parsing.py +++ b/src/python_testing/matter_testing_infrastructure/matter/testing/spec_parsing.py @@ -895,6 +895,7 @@ class PrebuiltDataModelDirectory(Enum): k1_4_1 = auto() k1_4_2 = auto() k1_5 = auto() + k1_5_1 = auto() @property def dirname(self): @@ -910,6 +911,8 @@ def dirname(self): return "1.4.2" if self == PrebuiltDataModelDirectory.k1_5: return "1.5" + if self == PrebuiltDataModelDirectory.k1_5_1: + return "1.5.1" raise KeyError("Invalid enum: %r" % self) @@ -1626,6 +1629,7 @@ def dm_from_spec_version(specification_version: uint) -> PrebuiltDataModelDirect 0x01040100: PrebuiltDataModelDirectory.k1_4_1, 0x01040200: PrebuiltDataModelDirectory.k1_4_2, 0x01050000: PrebuiltDataModelDirectory.k1_5, + 0x01050100: PrebuiltDataModelDirectory.k1_5_1, } if specification_version not in version_to_dm.keys(): diff --git a/src/python_testing/mdns_discovery/README.md b/src/python_testing/mdns_discovery/README.md index 0e422716593..52d0851a357 100644 --- a/src/python_testing/mdns_discovery/README.md +++ b/src/python_testing/mdns_discovery/README.md @@ -239,7 +239,7 @@ exact failing constraint obvious. You can import them from the following file: `mdns_discovery/utils/asserts.py` -``` +```python from mdns_discovery.utils.asserts import assert_valid_dn_key assert_valid_dn_key("Kitchen") @@ -264,6 +264,29 @@ assert_valid_dn_key("Kitchen") | `assert_valid_t_key` | `assert_valid_vendor_id` | | `assert_valid_icd_key` | `assert_valid_hostname` | +## 🛜 Network Utilities + +This module contains network utility functions to support mDNS-related test +cases. + +You can import them from the following file: `mdns_discovery/utils/network.py` + +```python +from mdns_discovery.utils.network import get_host_ipv6_addresses + +addr_list = get_host_ipv6_addresses() + +for addr in addr_list: + print(addr) +``` + +### ✅ Available network utility functions + +| | +| ------------------------- | +| `get_host_ipv6_addresses` | +| `is_dut_tcp_supported` | + ## 📌 General Information > For a complete overview of available methods, their functionality, and diff --git a/src/python_testing/mdns_discovery/tests/test_asserts.py b/src/python_testing/mdns_discovery/tests/test_asserts.py index 2064ecba65d..b231e22243f 100644 --- a/src/python_testing/mdns_discovery/tests/test_asserts.py +++ b/src/python_testing/mdns_discovery/tests/test_asserts.py @@ -23,8 +23,9 @@ assert_valid_devtype_subtype, assert_valid_dn_key, assert_valid_dt_key, assert_valid_hostname, assert_valid_icd_key, assert_valid_ipv6_addresses, assert_valid_jf_key, assert_valid_long_discriminator_subtype, - assert_valid_operational_instance_name, assert_valid_ph_key, assert_valid_pi_key, - assert_valid_product_id, assert_valid_ri_key, assert_valid_sai_key, assert_valid_sat_key, + assert_valid_operational_instance_name, assert_valid_ph_key, + assert_valid_ph_pi_relationship, assert_valid_pi_key, assert_valid_product_id, + assert_valid_ri_key, assert_valid_sai_key, assert_valid_sat_key, assert_valid_short_discriminator_subtype, assert_valid_sii_key, assert_valid_t_key, assert_valid_vendor_id, assert_valid_vendor_subtype, assert_valid_vp_key) from mobly import signals @@ -1018,14 +1019,14 @@ def test_multiple_failures_not_possible_with_hyphen_error(self): class TestAssertValidPhKey(unittest.TestCase): INT_MSG = "Must be a decimal integer without leading zeroes" GT0_MSG = "Value must be greater than 0" - BIT_MSG = "Only bits 0-19 may be set (value must fit in 20 bits)" + BIT_MSG = "Only bits 0-22 may be set" # Valid values VALID_VALUES = [ "1", # minimum allowed "33", # typical example - "1048575", # max 20-bit value (2^20 - 1) - "524288", # power of two within 20 bits + "8388607", # all 22-bits enabled (1<<23 - 1) + "524288", # power of two within 23 bits "999999", # large but still valid under mask ] @@ -1051,8 +1052,8 @@ def test_invalid_due_to_zero_value(self): self.assertIn(self.GT0_MSG, msg) def test_invalid_due_to_out_of_range(self): - # Exceeds 20-bit mask - msg = fail_msg(assert_valid_ph_key, str((1 << 20))) + # Only bits 1 through 22 are defined. + msg = fail_msg(assert_valid_ph_key, str((1 << 23))) self.assertIn(self.BIT_MSG, msg) def test_invalid_due_to_empty_string(self): @@ -1068,8 +1069,8 @@ def test_invalid_due_to_leading_zero_and_zero_value(self): self.assertNotIn(self.BIT_MSG, msg) def test_invalid_due_to_leading_zero_and_out_of_range(self): - # Leading zero present and numeric value beyond 20-bit mask → INT + BIT - msg = fail_msg(assert_valid_ph_key, "01048576") # 1_048_576 == 1 << 20 + # Leading zero present and numeric value beyond range + msg = fail_msg(assert_valid_ph_key, "08388608") # 8,388,608 == 1 << 23 self.assertIn(self.INT_MSG, msg) self.assertIn(self.BIT_MSG, msg) self.assertNotIn(self.GT0_MSG, msg) @@ -1090,8 +1091,8 @@ def test_invalid_due_to_many_leading_zeros_and_zero_value(self): self.assertNotIn(self.BIT_MSG, msg) def test_invalid_due_to_leading_zero_and_out_of_range_variant(self): - # Leading zero plus value beyond 20-bit mask -> INT + BIT, no GT0 - msg = fail_msg(assert_valid_ph_key, "0001048577") # 1_048_577 > (1<<20) - 1 + # Leading zero plus value beyond 22-bit mask -> INT + BIT, no GT0 + msg = fail_msg(assert_valid_ph_key, "0008388608") # 1_048_577 > (1<<20) - 1 self.assertIn(self.INT_MSG, msg) self.assertIn(self.BIT_MSG, msg) self.assertNotIn(self.GT0_MSG, msg) @@ -1174,6 +1175,38 @@ def test_non_utf8_even_when_long_source_string_reports_only_utf8_error(self): self.assertNotIn(self.LEN_MSG, msg) +class TestAssertValidPhPiRelationship(unittest.TestCase): + def test_valid_ph_no_pi_needed(self): + # PH has no mandatory PI bits set (e.g., bit 0, 1, 2, 3) + # 7 = 0b0111 + assert_valid_ph_pi_relationship({'PH': '7'}) + + def test_valid_ph_with_mandatory_pi_bits(self): + # PH bit 4 is set, PI is present + # 16 = 0b10000 + assert_valid_ph_pi_relationship({'PH': '16', 'PI': 'some instruction'}) + + def test_invalid_ph_mandatory_pi_bit_set_no_pi(self): + # PH bit 4 is set, but PI is missing + msg = fail_msg(assert_valid_ph_pi_relationship, {'PH': '16'}) + self.assertIn("'PI' key must be present", msg) + + def test_invalid_pi_no_ph(self): + # PI is present, but PH is missing + msg = fail_msg(assert_valid_ph_pi_relationship, {'PI': 'some instruction'}) + self.assertIn("'PH' key must be present", msg) + + def test_invalid_pi_with_ph_missing_related_bits(self): + # PI is present, PH is present but has none of bits 4, 8-12, 15-22 set + # 7 = 0b0111 + msg = fail_msg(assert_valid_ph_pi_relationship, {'PH': '7', 'PI': 'some instruction'}) + self.assertIn("'PH' key must have at least one of bits", msg) + + def test_empty_txt(self): + # No PH or PI, should pass + assert_valid_ph_pi_relationship({}) + + class TestAssertValidProductId(unittest.TestCase): INT_MSG = "Must be a decimal integer without leading zeroes" RNG_MSG = "Value must be within 0-65535 (16-bit range)" @@ -1551,124 +1584,187 @@ class TestAssertValidTKey(unittest.TestCase): RANGE_MSG = "Only bits 0-2 may be present (value must fit in 3 bits)" BIT0_MSG = "Bit 0 is reserved and must be 0" PROV_MSG = "Bits 1 and 2 are provisional and must not be set (strict mode)" + TCP_CAP_MSG = "Value must match TCP capability: {4, 6} if TCP supported, {0} if not" + MISMATCH_MSG = "TCP support in the PICS" - # Valid values (strict mode) - VALID_VALUES = [ - "0", # allowed, all bits clear - ] - - def _fail_msg(self, value: str, enforce_provisional: bool = True) -> str: - # Helper: run expecting failure and return assertion message (catch both types) + def _fail_msg(self, t_key: str, t_key_present: bool, supports_tcp_dut: bool, supports_tcp_pics: bool, enforce_provisional: bool = True) -> str: + """Helper: run expecting failure and return assertion message""" try: - assert_valid_t_key(value, enforce_provisional=enforce_provisional) + assert_valid_t_key(t_key, t_key_present, supports_tcp_dut, supports_tcp_pics, enforce_provisional) except (AssertionError, signals.TestFailure) as e: return str(e) self.fail("Expected failure but assertion passed") - def test_valid_values_strict(self): - # In strict mode, only "0" should pass - for value in self.VALID_VALUES: - with self.subTest(value=value): - assert_valid_t_key(value) - + # ========== T Key Not Present ========== + def test_t_key_not_present_returns_early(self): + """When t_key_present is False, function should return early without validation""" + # Should not raise regardless of other parameters + assert_valid_t_key(None, t_key_present=False, supports_tcp_dut=False, supports_tcp_pics=True) + assert_valid_t_key("invalid", t_key_present=False, supports_tcp_dut=True, supports_tcp_pics=False) + assert_valid_t_key("999", t_key_present=False, supports_tcp_dut=False, supports_tcp_pics=False) + + # ========== DUT/PICS TCP Support Mismatch ========== + def test_dut_tcp_supported_but_pics_unsupported(self): + """DUT supports TCP but PICS says unsupported -> should fail""" + msg = self._fail_msg("4", t_key_present=True, supports_tcp_dut=True, supports_tcp_pics=False, enforce_provisional=False) + self.assertIn(self.MISMATCH_MSG, msg) + + def test_dut_tcp_unsupported_but_pics_supported(self): + """DUT doesn't support TCP but PICS says supported -> should fail""" + msg = self._fail_msg("0", t_key_present=True, supports_tcp_dut=False, supports_tcp_pics=True, enforce_provisional=False) + self.assertIn(self.MISMATCH_MSG, msg) + + # ========== Valid TCP Capability Values ========== + def test_valid_value_4_tcp_supported(self): + """T=4 valid when TCP supported""" + assert_valid_t_key("4", t_key_present=True, supports_tcp_dut=True, supports_tcp_pics=True, enforce_provisional=False) + + def test_valid_value_6_tcp_supported(self): + """T=6 valid when TCP supported""" + assert_valid_t_key("6", t_key_present=True, supports_tcp_dut=True, supports_tcp_pics=True, enforce_provisional=False) + + def test_valid_value_0_mrp_only(self): + """T=0 valid when MRP-only (TCP unsupported)""" + assert_valid_t_key("0", t_key_present=True, supports_tcp_dut=False, supports_tcp_pics=False) + + # ========== Invalid TCP Capability Values ========== + def test_invalid_tcp_value_when_mrp_only(self): + """T=4 invalid when MRP-only""" + msg = self._fail_msg("4", t_key_present=True, supports_tcp_dut=False, supports_tcp_pics=False, enforce_provisional=False) + self.assertIn(self.TCP_CAP_MSG, msg) + + def test_invalid_mrp_value_when_tcp_supported(self): + """T=0 invalid when TCP supported""" + msg = self._fail_msg("0", t_key_present=True, supports_tcp_dut=True, supports_tcp_pics=True, enforce_provisional=False) + self.assertIn(self.TCP_CAP_MSG, msg) + + def test_invalid_value_2_for_tcp(self): + """T=2 is not a valid TCP value (even though it's bit 1)""" + msg = self._fail_msg("2", t_key_present=True, supports_tcp_dut=True, supports_tcp_pics=True, enforce_provisional=False) + self.assertIn(self.TCP_CAP_MSG, msg) + + # ========== Format Validation ========== def test_invalid_due_to_non_decimal(self): - msg = self._fail_msg("A") + """Non-decimal string should fail""" + msg = self._fail_msg("A", t_key_present=True, supports_tcp_dut=True, supports_tcp_pics=True, enforce_provisional=False) self.assertIn(self.INT_MSG, msg) self.assertNotIn(self.RANGE_MSG, msg) - self.assertNotIn(self.BIT0_MSG, msg) - self.assertNotIn(self.PROV_MSG, msg) def test_invalid_due_to_leading_zero(self): - msg = self._fail_msg("01") + """Leading zero should fail""" + msg = self._fail_msg("04", t_key_present=True, supports_tcp_dut=True, supports_tcp_pics=True, enforce_provisional=False) self.assertIn(self.INT_MSG, msg) + # ========== Bit Range Validation ========== def test_invalid_due_to_out_of_range_bit3(self): - msg = self._fail_msg("8") + """Value with bit 3 set (>= 8) should fail range check""" + msg = self._fail_msg("8", t_key_present=True, supports_tcp_dut=False, supports_tcp_pics=False, enforce_provisional=False) + self.assertIn(self.RANGE_MSG, msg) + self.assertNotIn(self.INT_MSG, msg) + + def test_invalid_due_to_out_of_range_large_value(self): + """Large value should fail range check""" + msg = self._fail_msg("99", t_key_present=True, supports_tcp_dut=False, supports_tcp_pics=False, enforce_provisional=False) self.assertIn(self.RANGE_MSG, msg) - self.assertNotIn(self.INT_MSG, msg) # format is fine + # ========== Bit 0 Validation ========== def test_invalid_due_to_bit0_set(self): - msg = self._fail_msg("1") + """Bit 0 must always be 0""" + msg = self._fail_msg("1", t_key_present=True, supports_tcp_dut=False, supports_tcp_pics=False, enforce_provisional=False) self.assertIn(self.BIT0_MSG, msg) self.assertNotIn(self.INT_MSG, msg) + def test_invalid_due_to_bit0_set_with_tcp(self): + """T=5 has bit 0 set, invalid even if bits 2 allowed""" + msg = self._fail_msg("5", t_key_present=True, supports_tcp_dut=True, supports_tcp_pics=True, enforce_provisional=False) + self.assertIn(self.BIT0_MSG, msg) + + # ========== Provisional Bits Validation (Strict Mode) ========== def test_invalid_due_to_provisional_bits_in_strict_mode(self): + """Provisional bits (1,2) should fail in strict mode""" for val in ["2", "4", "6"]: with self.subTest(val=val): - msg = self._fail_msg(val) + msg = self._fail_msg(val, t_key_present=True, supports_tcp_dut=False, supports_tcp_pics=False) self.assertIn(self.PROV_MSG, msg) - def test_valid_with_provisional_bits_when_relaxed(self): - assert_valid_t_key("2", enforce_provisional=False) - assert_valid_t_key("4", enforce_provisional=False) - assert_valid_t_key("6", enforce_provisional=False) - - def test_invalid_due_to_bit0_even_if_relaxed(self): - msg = self._fail_msg("1", enforce_provisional=False) - self.assertIn(self.BIT0_MSG, msg) - self.assertNotIn(self.PROV_MSG, msg) - - def test_invalid_due_to_out_of_range_even_if_relaxed(self): - msg = self._fail_msg("9", enforce_provisional=False) - self.assertIn(self.RANGE_MSG, msg) - self.assertNotIn(self.PROV_MSG, msg) - - def test_invalid_due_to_int_and_bit0_strict(self): - # Leading zero breaks INT; numeric value 1 sets bit0 - msg = self._fail_msg("01") + # ========== Provisional Bits Validation (Relaxed Mode) ========== + def test_valid_with_provisional_bits_when_relaxed_and_tcp_supported(self): + """Provisional bits allowed in relaxed mode with proper TCP capability""" + assert_valid_t_key("4", t_key_present=True, supports_tcp_dut=True, supports_tcp_pics=True, enforce_provisional=False) + assert_valid_t_key("6", t_key_present=True, supports_tcp_dut=True, supports_tcp_pics=True, enforce_provisional=False) + + def test_invalid_provisional_bit_wrong_tcp_capability(self): + """Even in relaxed mode, TCP capability must match""" + msg = self._fail_msg("2", t_key_present=True, supports_tcp_dut=False, supports_tcp_pics=False, enforce_provisional=False) + self.assertIn(self.TCP_CAP_MSG, msg) + self.assertNotIn(self.PROV_MSG, msg) # Relaxed mode + + # ========== Multiple Failures ========== + def test_invalid_due_to_int_and_bit0(self): + """Leading zero breaks INT; numeric value 1 sets bit0""" + msg = self._fail_msg("01", t_key_present=True, supports_tcp_dut=False, supports_tcp_pics=False) self.assertIn(self.INT_MSG, msg) self.assertIn(self.BIT0_MSG, msg) - self.assertNotIn(self.RANGE_MSG, msg) - self.assertNotIn(self.PROV_MSG, msg) def test_invalid_due_to_int_and_provisional_strict(self): - # Leading zero + value 2 sets provisional bit1 - msg = self._fail_msg("02") + """Leading zero + value 2 sets provisional bit1""" + msg = self._fail_msg("02", t_key_present=True, supports_tcp_dut=False, supports_tcp_pics=False) self.assertIn(self.INT_MSG, msg) self.assertIn(self.PROV_MSG, msg) - self.assertNotIn(self.RANGE_MSG, msg) - self.assertNotIn(self.BIT0_MSG, msg) def test_invalid_due_to_int_range_and_provisional_strict(self): - # "010" -> integer rule fails; 10 (0b1010) sets bit3 (range) and bit1 (provisional) - msg = self._fail_msg("010") + """010 -> integer rule fails; 10 sets bit3 (range) and bit1 (provisional)""" + msg = self._fail_msg("010", t_key_present=True, supports_tcp_dut=False, supports_tcp_pics=False) self.assertIn(self.INT_MSG, msg) self.assertIn(self.RANGE_MSG, msg) self.assertIn(self.PROV_MSG, msg) self.assertNotIn(self.BIT0_MSG, msg) def test_invalid_due_to_range_bit0_and_provisional_strict(self): - # 11 (0b1011): bit3 -> range, bit0 set, bit1 -> provisional - msg = self._fail_msg("11") + """11 (0b1011): bit3 -> range, bit0 set, bit1 -> provisional""" + msg = self._fail_msg("11", t_key_present=True, supports_tcp_dut=False, supports_tcp_pics=False) self.assertIn(self.RANGE_MSG, msg) self.assertIn(self.BIT0_MSG, msg) self.assertIn(self.PROV_MSG, msg) self.assertNotIn(self.INT_MSG, msg) def test_invalid_due_to_bit0_and_provisional_strict(self): - # 3 (0b0011): within 3-bit range; bit0 set & bit1 (provisional) set - msg = self._fail_msg("3") + """3 (0b0011): within 3-bit range; bit0 set & bit1 (provisional) set""" + msg = self._fail_msg("3", t_key_present=True, supports_tcp_dut=False, supports_tcp_pics=False) self.assertIn(self.BIT0_MSG, msg) self.assertIn(self.PROV_MSG, msg) self.assertNotIn(self.RANGE_MSG, msg) self.assertNotIn(self.INT_MSG, msg) def test_invalid_due_to_range_and_bit0_relaxed(self): - # Relaxed: provisional ignored; 9 (0b1001) -> range + bit0 - msg = self._fail_msg("9", enforce_provisional=False) + """Relaxed: provisional ignored; 9 (0b1001) -> range + bit0""" + msg = self._fail_msg("9", t_key_present=True, supports_tcp_dut=False, supports_tcp_pics=False, enforce_provisional=False) self.assertIn(self.RANGE_MSG, msg) self.assertIn(self.BIT0_MSG, msg) self.assertNotIn(self.PROV_MSG, msg) self.assertNotIn(self.INT_MSG, msg) def test_invalid_due_to_int_range_and_bit0_relaxed(self): - # Leading zero + 9 -> INT + RANGE + BIT0 (relaxed ignores provisional) - msg = self._fail_msg("09", enforce_provisional=False) + """Leading zero + 9 -> INT + RANGE + BIT0 (relaxed ignores provisional)""" + msg = self._fail_msg("09", t_key_present=True, supports_tcp_dut=False, supports_tcp_pics=False, enforce_provisional=False) self.assertIn(self.INT_MSG, msg) self.assertIn(self.RANGE_MSG, msg) self.assertIn(self.BIT0_MSG, msg) self.assertNotIn(self.PROV_MSG, msg) + def test_invalid_tcp_capability_plus_bit_violations(self): + """T=5 when TCP supported: wrong value + bit0 + provisional (strict)""" + msg = self._fail_msg("5", t_key_present=True, supports_tcp_dut=True, supports_tcp_pics=True) + self.assertIn(self.TCP_CAP_MSG, msg) # 5 not in {4, 6} + self.assertIn(self.BIT0_MSG, msg) + self.assertIn(self.PROV_MSG, msg) + + def test_mismatch_plus_bit_violations(self): + """DUT/PICS mismatch should fail before other validations""" + msg = self._fail_msg("1", t_key_present=True, supports_tcp_dut=True, supports_tcp_pics=False) + self.assertIn(self.MISMATCH_MSG, msg) + # Other validations may or may not run after mismatch, just check mismatch occurs + class TestAssertValidVendorId(unittest.TestCase): INT_MSG = "Must be a decimal integer without leading zeroes" diff --git a/src/python_testing/mdns_discovery/utils/asserts.py b/src/python_testing/mdns_discovery/utils/asserts.py index 7eb88d419a0..1ad91129da3 100644 --- a/src/python_testing/mdns_discovery/utils/asserts.py +++ b/src/python_testing/mdns_discovery/utils/asserts.py @@ -746,7 +746,7 @@ def assert_valid_ph_key(ph_key: str) -> None: - Encoded as a variable-length decimal number in ASCII text - Omitting any leading zeroes - Must be greater than 0 - - Only bits 0-19 are valid + - Only bits 0-22 are valid Example: "33" @@ -760,7 +760,7 @@ def assert_valid_ph_key(ph_key: str) -> None: constraints = [ "Must be a decimal integer without leading zeroes", "Value must be greater than 0", - "Only bits 0-19 may be set (value must fit in 20 bits)", + "Only bits 0-22 may be set (value must fit in 23 bits)", ] failed: list[str] = [] @@ -777,7 +777,7 @@ def assert_valid_ph_key(ph_key: str) -> None: if v <= 0: failed.append(constraints[1]) # Bit-mask validity only meaningful for positive integers - allowed_mask = (1 << 20) - 1 + allowed_mask = (1 << 23) - 1 if v > 0 and (v & ~allowed_mask): failed.append(constraints[2]) except ValueError: @@ -829,6 +829,41 @@ def assert_valid_pi_key(pi_key: str) -> None: ) +@not_none_args +def assert_valid_ph_pi_relationship(txt: dict[str, str]) -> None: + """ + Verify the relationship between Pairing Hint (PH) and Pairing Instruction (PI) keys. + + Constraints: + - If any of bits 4, 8, 10, 12, 15, 17, 19, 20, 21, or 22 are set in PH, then PI MUST be present. + - If PI is present, PH MUST be present and have at least one of the bits 4, 8, 9, 10, 11, 12, 15, 16, 17, 18, 19, 20, 21, or 22 set. + + Raises: + TestFailure: If the relationship constraints are violated. + """ + ph_key = txt.get('PH') + pi_key = txt.get('PI') + + if ph_key: + try: + ph_val = int(ph_key) + mandatory_pi_bits = [4, 8, 10, 12, 15, 17, 19, 20, 21, 22] + if any((ph_val & (1 << bit)) for bit in mandatory_pi_bits): + asserts.assert_in('PI', txt, f"'PI' key must be present if any of bits {mandatory_pi_bits} are set in 'PH' key.") + except (ValueError, TypeError): + pass + + if pi_key is not None: + asserts.assert_in('PH', txt, "'PH' key must be present if 'PI' key is present.") + try: + ph_val = int(ph_key) + pi_related_bits = [4, 8, 9, 10, 11, 12, 15, 16, 17, 18, 19, 20, 21, 22] + asserts.assert_true(any((ph_val & (1 << bit)) for bit in pi_related_bits), + f"'PH' key must have at least one of bits {pi_related_bits} set if 'PI' key is present.") + except (ValueError, TypeError): + pass + + @not_none_args def assert_valid_jf_key(jf_key: str) -> None: """ @@ -1038,13 +1073,17 @@ def assert_valid_sat_key(sat_key: str) -> None: ) -@not_none_args -def assert_valid_t_key(t_key: str, enforce_provisional: bool = True) -> None: +def assert_valid_t_key(t_key: str, t_key_present: bool, supports_tcp_dut: bool, supports_tcp_pics: bool, enforce_provisional: bool = True) -> None: """ **Transport Protocol Modes** Verify that the TXT record T key is valid. + This function validates the T key format, bit constraints, and TCP capability + alignment. If the T key is not present in the TXT record, the function returns + early without performing any validation. When the T key is present, it ensures + that DUT and PICS TCP support are consistent and validates the key value. + Constraints: - Encoded as a decimal number in ASCII text - Omitting any leading zeros @@ -1053,17 +1092,26 @@ def assert_valid_t_key(t_key: str, enforce_provisional: bool = True) -> None: - Bits 1 and 2 are provisional: * If enforce_provisional=True → must not be set * If enforce_provisional=False → allowed, only bit 0 must be clear + - TCP capability must match: + * If TCP supported: allowed values are {4, 6} + * If TCP not supported (MRP-only support): allowed value is {0} - Example: - "0" + Examples: + "4" # TCP supported (IPv4) + "6" # TCP supported (IPv6) Args: - t_key (str): The value to validate + t_key (str): The T key value to validate (may be None if not present) + t_key_present (bool): Whether the T key is present in the TXT record + supports_tcp_dut (bool): Whether TCP is supported by the DUT + supports_tcp_pics (bool): Whether TCP is supported by PICS enforce_provisional (bool): Whether to enforce strict prohibition of provisional bits 1 and 2 (default: True) Raises: - TestFailure: If `t_key` does not conform to the constraints. + TestFailure: + - If DUT and PICS TCP support do not match. + - If `t_key` does not conform to the constraints. Spec: https://github.com/CHIP-Specifications/connectedhomeip-spec/blob/master/src/secure_channel/Discovery.adoc#4-common-txt-keyvalue-pairs @@ -1073,10 +1121,19 @@ def assert_valid_t_key(t_key: str, enforce_provisional: bool = True) -> None: "Only bits 0-2 may be present (value must fit in 3 bits)", "Bit 0 is reserved and must be 0", "Bits 1 and 2 are provisional and must not be set (strict mode)", + "Value must match TCP capability: {4, 6} if TCP supported, {0} if not", ] failed: list[str] = [] + # If T key is not present, there's nothing to verify + if not t_key_present: + return + + # Verify that DUT and PICS TCP support matches (both unsupported or both supported) + asserts.assert_true(supports_tcp_dut == supports_tcp_pics, + f"TCP support in the PICS ({supports_tcp_pics}) must match TCP support in the DUT ({supports_tcp_dut}).") + # Integer format (no leading zeroes except "0") — independent of bit checks if not re.fullmatch(r'(0|[1-9]\d*)', t_key): failed.append(constraints[0]) @@ -1085,13 +1142,15 @@ def assert_valid_t_key(t_key: str, enforce_provisional: bool = True) -> None: if re.fullmatch(r'\d+', t_key): try: v = int(t_key) - # Evaluate all conditions independently (no elif gating) if v & ~0x7: failed.append(constraints[1]) # bits above 2 present if v & 0x1: failed.append(constraints[2]) # bit 0 must be 0 if enforce_provisional and (v & 0x6): failed.append(constraints[3]) # bits 1 or 2 set (strict mode) + allowed = {4, 6} if supports_tcp_dut else {0} + if v not in allowed: + failed.append(constraints[4]) # value must match TCP capability except ValueError: # Defensive: if parsing somehow fails, treat as integer-format error failed.append(constraints[0]) diff --git a/src/python_testing/mdns_discovery/utils/network.py b/src/python_testing/mdns_discovery/utils/network.py index 56863feab61..c6e574c7621 100644 --- a/src/python_testing/mdns_discovery/utils/network.py +++ b/src/python_testing/mdns_discovery/utils/network.py @@ -73,3 +73,42 @@ def get_host_ipv6_addresses(): logger.info(f"Discovered IPv6 addresses: {results}") return results + + +async def is_dut_tcp_supported(instance_qname: str): + """ + Determines whether the DUT supports TCP by inspecting its operational service TXT record. + + This function queries the DUT's operational mDNS service and examines the T key in the + TXT record. MRP-only support (TCP unsupported) is indicated when the T key is absent, + empty, or has a value of "0". Any other value indicates TCP support. + + Args: + instance_qname (str): The fully qualified instance name of the DUT. + + Returns: + bool: + - True if the DUT supports TCP (T key present and not "0") + - False if the DUT supports MRP-only (T key absent, empty, or "0") + + Raises: + Exception: If the TXT record cannot be retrieved from the DUT. + """ + # Import here to avoid circular dependency + from mdns_discovery.mdns_discovery import MdnsDiscovery, MdnsServiceType + + try: + # Get the operational service TXT record + txt_record = await MdnsDiscovery().get_txt_record( + service_name=instance_qname, service_type=MdnsServiceType.OPERATIONAL.value + ) + except Exception as e: + raise Exception( + f"Unable to determine TCP support for '{instance_qname}'. " + f"Failure during TXT record retrieval: {e}" + ) from e + + # Returns True when TCP is supported (T key present and not "0") + # Returns False when MRP-only (T key absent, empty, or "0") + t_key = txt_record.txt.get('T', None) + return not (t_key is None or not str(t_key).strip() or str(t_key).strip() == "0") diff --git a/src/python_testing/test_metadata.yaml b/src/python_testing/test_metadata.yaml index 8e2b222a225..cdf944e5d86 100644 --- a/src/python_testing/test_metadata.yaml +++ b/src/python_testing/test_metadata.yaml @@ -150,6 +150,10 @@ not_automated: reason: Helper methods for Push AV Integration TCs - name: TC_TLS_Utils.py reason: Helper methods for TC tests dependent on TLS clusters + - name: TC_TLSCERT_Base.py + reason: Shared code for TC_TLSCERT, not a standalone test + - name: TC_TLSCLIENT_Base.py + reason: Shared code for TC_TLSCLIENT, not a standalone test - name: TC_BINFO_3_2.py reason: V1.5 BRANCH FIX - Configuration version is still provisional @@ -158,7 +162,7 @@ not_automated: # to consider improving. May not be exhaustive slow_tests: - { name: mobile-device-test.py, duration: 3 minutes } - - { name: TC_AccessChecker.py, duration: 1.5 minutes } + - { name: TC_AccessChecker.py, duration: 25 minutes } - { name: TC_BRBINFO_4_1.py, duration: 2 minutes } - { name: TC_CADMIN_1_3_4.py, duration: 4 minutes } - { name: TC_CADMIN_1_19.py, duration: 30 seconds } diff --git a/src/python_testing/test_testing/DeviceConformanceTests.py b/src/python_testing/test_testing/DeviceConformanceTests.py index 419410a2892..ecb77dd256b 100644 --- a/src/python_testing/test_testing/DeviceConformanceTests.py +++ b/src/python_testing/test_testing/DeviceConformanceTests.py @@ -22,7 +22,7 @@ from matter.testing.basic_composition import BasicCompositionTests from matter.testing.choice_conformance import (evaluate_attribute_choice_conformance, evaluate_command_choice_conformance, evaluate_feature_choice_conformance) -from matter.testing.conformance import conformance_allowed +from matter.testing.conformance import EMPTY_CLUSTER_GLOBAL_ATTRIBUTES, ConformanceAssessmentData, conformance_allowed from matter.testing.global_attribute_ids import (ClusterIdType, DeviceTypeIdType, GlobalAttributeIds, cluster_id_type, device_type_id_type, is_valid_device_type_id) from matter.testing.problem_notices import (AttributePathLocation, ClusterPathLocation, CommandPathLocation, DeviceTypePathLocation, @@ -161,6 +161,8 @@ def record_warning(location, problem): attribute_list = cluster[GlobalAttributeIds.ATTRIBUTE_LIST_ID] all_command_list = cluster[GlobalAttributeIds.ACCEPTED_COMMAND_LIST_ID] + \ cluster[GlobalAttributeIds.GENERATED_COMMAND_LIST_ID] + revision = cluster[GlobalAttributeIds.CLUSTER_REVISION_ID] + cluster_info = ConformanceAssessmentData(feature_map, attribute_list, all_command_list, revision) # Feature conformance checking location = AttributePathLocation(endpoint_id=endpoint_id, cluster_id=cluster_id, @@ -179,12 +181,12 @@ def record_warning(location, problem): problem=f'Unknown feature with mask 0x{f:02x} (feature bit {f.bit_length() - 1})') continue xml_feature = self.xml_clusters[cluster_id].features[f] - conformance_decision_with_choice = xml_feature.conformance(feature_map, attribute_list, all_command_list) + conformance_decision_with_choice = xml_feature.conformance(cluster_info) if not conformance_allowed(conformance_decision_with_choice, allow_provisional): record_error(location=location, problem=f'Disallowed feature with mask 0x{f:02x} (feature bit {f.bit_length() - 1})') for feature_mask, xml_feature in self.xml_clusters[cluster_id].features.items(): - conformance_decision_with_choice = xml_feature.conformance(feature_map, attribute_list, all_command_list) + conformance_decision_with_choice = xml_feature.conformance(cluster_info) if conformance_decision_with_choice.is_mandatory() and feature_mask not in feature_masks: record_error( location=location, problem=f'Required feature with mask 0x{feature_mask:02x} (feature bit {feature_mask.bit_length() - 1}) is not present in feature map. {conformance_str(xml_feature.conformance, feature_map, self.xml_clusters[cluster_id].features)}') @@ -200,7 +202,7 @@ def record_warning(location, problem): record_error(location=location, problem='Standard attribute found on device, but not in spec') continue xml_attribute = self.xml_clusters[cluster_id].attributes[attribute_id] - conformance_decision_with_choice = xml_attribute.conformance(feature_map, attribute_list, all_command_list) + conformance_decision_with_choice = xml_attribute.conformance(cluster_info) if not conformance_allowed(conformance_decision_with_choice, allow_provisional): location = AttributePathLocation(endpoint_id=endpoint_id, cluster_id=cluster_id, attribute_id=attribute_id) record_error( @@ -208,8 +210,8 @@ def record_warning(location, problem): for attribute_id, xml_attribute in self.xml_clusters[cluster_id].attributes.items(): if cluster_id in ignore_attributes and attribute_id in ignore_attributes[cluster_id]: continue - conformance_decision_with_choice = xml_attribute.conformance(feature_map, attribute_list, all_command_list) - if conformance_decision_with_choice.is_mandatory() and attribute_id not in cluster.keys(): + conformance_decision_with_choice = xml_attribute.conformance(cluster_info) + if conformance_decision_with_choice.is_mandatory() and attribute_id not in cluster: location = AttributePathLocation(endpoint_id=endpoint_id, cluster_id=cluster_id, attribute_id=attribute_id) record_error( location=location, problem=f'Attribute 0x{attribute_id:02x} is required, but is not present on the DUT. {conformance_str(xml_attribute.conformance, feature_map, self.xml_clusters[cluster_id].features)}') @@ -226,12 +228,12 @@ def check_spec_conformance_for_commands(command_type: CommandType): record_error(location=location, problem='Standard command found on device, but not in spec') continue xml_command = xml_commands_dict[command_id] - conformance_decision_with_choice = xml_command.conformance(feature_map, attribute_list, all_command_list) + conformance_decision_with_choice = xml_command.conformance(cluster_info) if not conformance_allowed(conformance_decision_with_choice, allow_provisional): record_error( location=location, problem=f'Command 0x{command_id:02x} is included, but disallowed by conformance. {conformance_str(xml_command.conformance, feature_map, self.xml_clusters[cluster_id].features)}') for command_id, xml_command in xml_commands_dict.items(): - conformance_decision_with_choice = xml_command.conformance(feature_map, attribute_list, all_command_list) + conformance_decision_with_choice = xml_command.conformance(cluster_info) if conformance_decision_with_choice.is_mandatory() and command_id not in command_list: location = CommandPathLocation(endpoint_id=endpoint_id, cluster_id=cluster_id, command_id=command_id) record_error( @@ -242,11 +244,11 @@ def check_spec_conformance_for_commands(command_type: CommandType): check_spec_conformance_for_commands(CommandType.GENERATED) feature_choice_problems = evaluate_feature_choice_conformance( - endpoint_id, cluster_id, self.xml_clusters, feature_map, attribute_list, all_command_list) + endpoint_id, cluster_id, self.xml_clusters, cluster_info) attribute_choice_problems = evaluate_attribute_choice_conformance( - endpoint_id, cluster_id, self.xml_clusters, feature_map, attribute_list, all_command_list) + endpoint_id, cluster_id, self.xml_clusters, cluster_info) command_choice_problem = evaluate_command_choice_conformance( - endpoint_id, cluster_id, self.xml_clusters, feature_map, attribute_list, all_command_list) + endpoint_id, cluster_id, self.xml_clusters, cluster_info) if feature_choice_problems or attribute_choice_problems or command_choice_problem: success = False @@ -380,7 +382,7 @@ def record_warning(location, problem): # TODO: check client clusters too? for cluster_id, cluster_requirement in xml_device.server_clusters.items(): # Device type cluster conformances do not include any conformances based on cluster elements - conformance_decision_with_choice = cluster_requirement.conformance(0, [], []) + conformance_decision_with_choice = cluster_requirement.conformance(EMPTY_CLUSTER_GLOBAL_ATTRIBUTES) location = DeviceTypePathLocation(device_type_id=device_type_id, cluster_id=cluster_id) if conformance_decision_with_choice.is_mandatory() and cluster_id not in server_clusters: record_error(location=location, @@ -396,9 +398,9 @@ def record_warning(location, problem): # Optional cluster not on this endpoint continue - def check_feature_overrides(cluster_requirement: XmlDeviceTypeClusterRequirements, feature_map, attribute_list, cmd_list): + def check_feature_overrides(cluster_requirement: XmlDeviceTypeClusterRequirements, cluster_info: ConformanceAssessmentData): for mask, conformance in cluster_requirement.feature_overrides.items(): - conformance_decision_with_choice = conformance(feature_map, attribute_list, cmd_list) + conformance_decision_with_choice = conformance(cluster_info) if conformance_decision_with_choice.is_mandatory() and ((feature_map & mask) == 0): record_error( location=location, problem=f"Feature bit {mask.bit_length() - 1} in cluster {cluster_requirement.name} is required by element override for device type {xml_device.name}, but is not present in the feature map") @@ -406,9 +408,9 @@ def check_feature_overrides(cluster_requirement: XmlDeviceTypeClusterRequirement record_error( location=location, problem=f"Feature bit {mask.bit_length() - 1} in cluster {cluster_requirement.name} is disallowed by element override for device type {xml_device.name}, but is present in the feature map") - def check_attribute_overrides(cluster_requirement: XmlDeviceTypeClusterRequirements, feature_map: int, attribute_list: list[int], cmd_list: list[int]) -> None: + def check_attribute_overrides(cluster_requirement: XmlDeviceTypeClusterRequirements, cluster_info: ConformanceAssessmentData) -> None: for id, conformance in cluster_requirement.attribute_overrides.items(): - conformance_decision_with_choice = conformance(feature_map, attribute_list, cmd_list) + conformance_decision_with_choice = conformance(cluster_info) if conformance_decision_with_choice.is_mandatory() and id not in attribute_list: record_error( location=location, problem=f"Attribute {id} in cluster {cluster_requirement.name} is required by element override for device type {xml_device.name}, but is not present in the attribute list") @@ -420,9 +422,9 @@ def check_attribute_overrides(cluster_requirement: XmlDeviceTypeClusterRequireme record_error( location=location, problem=f"Attribute {id} in cluster {cluster_requirement.name} is disallowed by element override for device type {xml_device.name}, but is present in the attribute list") - def check_command_overrides(cluster_requirement: XmlDeviceTypeClusterRequirements, feature_map: int, attribute_list: list[int], cmd_list: list[int]): + def check_command_overrides(cluster_requirement: XmlDeviceTypeClusterRequirements, cluster_info: ConformanceAssessmentData): for id, conformance in cluster_requirement.command_overrides.items(): - conformance_decision_with_choice = conformance(feature_map, attribute_list, cmd_list) + conformance_decision_with_choice = conformance(cluster_info) if conformance_decision_with_choice.is_mandatory() and id not in cmd_list: record_error( location=location, problem=f"Command {id} in cluster {cluster_requirement.name} is required by element override for device type {xml_device.name}, but is not present in the cmd list") @@ -434,10 +436,12 @@ def check_command_overrides(cluster_requirement: XmlDeviceTypeClusterRequirement feature_map = endpoint[cluster][cluster.Attributes.FeatureMap] attribute_list = endpoint[cluster][cluster.Attributes.AttributeList] cmd_list = endpoint[cluster][cluster.Attributes.AcceptedCommandList] + revision = endpoint[cluster][cluster.Attributes.ClusterRevision] + cluster_info = ConformanceAssessmentData(feature_map, attribute_list, cmd_list, revision) - check_feature_overrides(cluster_requirement, feature_map, attribute_list, cmd_list) - check_attribute_overrides(cluster_requirement, feature_map, attribute_list, cmd_list) - check_command_overrides(cluster_requirement, feature_map, attribute_list, cmd_list) + check_feature_overrides(cluster_requirement, cluster_info) + check_attribute_overrides(cluster_requirement, cluster_info) + check_command_overrides(cluster_requirement, cluster_info) # If we want to check for extra clusters on the endpoint, we need to know the entire set of clusters in all the device type # lists across all the device types on the endpoint. diff --git a/src/python_testing/test_testing/TestChoiceConformanceSupport.py b/src/python_testing/test_testing/TestChoiceConformanceSupport.py index cb902145ab2..bb626cda1da 100644 --- a/src/python_testing/test_testing/TestChoiceConformanceSupport.py +++ b/src/python_testing/test_testing/TestChoiceConformanceSupport.py @@ -23,6 +23,7 @@ from matter.testing.choice_conformance import (evaluate_attribute_choice_conformance, evaluate_command_choice_conformance, evaluate_feature_choice_conformance) +from matter.testing.conformance import ConformanceAssessmentData from matter.testing.matter_testing import MatterBaseTest, default_matter_test_main from matter.testing.problem_notices import ProblemNotice from matter.testing.spec_parsing import XmlCluster, add_cluster_data_from_xml @@ -195,17 +196,21 @@ def make_feature_map(combo: tuple[int]) -> int: return feature_map for combo, expected_failures in self.all_id_combos: - problems = evaluate_feature_choice_conformance(0, 1, self.clusters, make_feature_map(combo), [], []) + info = ConformanceAssessmentData(feature_map=make_feature_map( + combo), attribute_list=[], all_command_list=[], cluster_revision=1) + problems = evaluate_feature_choice_conformance(0, 1, self.clusters, info) self._evaluate_problems(problems, expected_failures) def test_attributes(self): for combo, expected_failures in self.all_id_combos: - problems = evaluate_attribute_choice_conformance(0, 1, self.clusters, 0, list(combo), []) + info = ConformanceAssessmentData(feature_map=0, attribute_list=list(combo), all_command_list=[], cluster_revision=1) + problems = evaluate_attribute_choice_conformance(0, 1, self.clusters, info) self._evaluate_problems(problems, expected_failures) def test_commands(self): for combo, expected_failures in self.all_id_combos: - problems = evaluate_command_choice_conformance(0, 1, self.clusters, 0, [], list(combo)) + info = ConformanceAssessmentData(feature_map=0, attribute_list=[], all_command_list=list(combo), cluster_revision=1) + problems = evaluate_command_choice_conformance(0, 1, self.clusters, info) self._evaluate_problems(problems, expected_failures) diff --git a/src/python_testing/test_testing/TestConformanceSupport.py b/src/python_testing/test_testing/TestConformanceSupport.py index bed18575ed8..541803372e1 100644 --- a/src/python_testing/test_testing/TestConformanceSupport.py +++ b/src/python_testing/test_testing/TestConformanceSupport.py @@ -20,9 +20,10 @@ from mobly import asserts -from matter.testing.conformance import (Choice, Conformance, ConformanceDecision, ConformanceException, ConformanceParseParameters, - deprecated, disallowed, mandatory, optional, parse_basic_callable_from_xml, - parse_callable_from_xml, provisional, zigbee) +from matter.testing.conformance import (EMPTY_CLUSTER_GLOBAL_ATTRIBUTES, Choice, Conformance, ConformanceAssessmentData, + ConformanceDecision, ConformanceException, ConformanceParseParameters, deprecated, + disallowed, mandatory, optional, parse_basic_callable_from_xml, parse_callable_from_xml, + provisional, zigbee) from matter.testing.matter_testing import MatterBaseTest, default_matter_test_main from matter.tlv import uint @@ -61,7 +62,8 @@ def test_conformance_mandatory(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for f in self.feature_maps: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.MANDATORY) + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) asserts.assert_equal(str(xml_callable), 'M') def test_conformance_optional(self): @@ -69,7 +71,8 @@ def test_conformance_optional(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for f in self.feature_maps: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.OPTIONAL) + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) asserts.assert_equal(str(xml_callable), 'O') def test_conformance_disallowed(self): @@ -77,14 +80,16 @@ def test_conformance_disallowed(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for f in self.feature_maps: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.DISALLOWED) + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.DISALLOWED) asserts.assert_equal(str(xml_callable), 'X') xml = '' et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for f in self.feature_maps: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.DISALLOWED) + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.DISALLOWED) asserts.assert_equal(str(xml_callable), 'D') def test_conformance_provisional(self): @@ -92,7 +97,8 @@ def test_conformance_provisional(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for f in self.feature_maps: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.PROVISIONAL) + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.PROVISIONAL) asserts.assert_equal(str(xml_callable), 'P') def test_conformance_zigbee(self): @@ -100,7 +106,8 @@ def test_conformance_zigbee(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for f in self.feature_maps: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), 'Zigbee') def test_conformance_mandatory_on_condition(self): @@ -110,10 +117,11 @@ def test_conformance_mandatory_on_condition(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) if self.has_ab[i]: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) else: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), 'AB') xml = ('' @@ -122,10 +130,11 @@ def test_conformance_mandatory_on_condition(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) if self.has_cd[i]: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) else: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), 'CD') # single attribute mandatory @@ -135,10 +144,11 @@ def test_conformance_mandatory_on_condition(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, a in enumerate(self.attribute_lists): + info = ConformanceAssessmentData(feature_map=0, attribute_list=a, all_command_list=[], cluster_revision=1) if self.has_attr1[i]: - asserts.assert_equal(xml_callable(0x00, a, []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) else: - asserts.assert_equal(xml_callable(0x00, a, []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), 'attr1') xml = ('' @@ -147,10 +157,11 @@ def test_conformance_mandatory_on_condition(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, a in enumerate(self.attribute_lists): + info = ConformanceAssessmentData(feature_map=0, attribute_list=a, all_command_list=[], cluster_revision=1) if self.has_attr2[i]: - asserts.assert_equal(xml_callable(0x00, a, []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) else: - asserts.assert_equal(xml_callable(0x00, a, []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), 'attr2') # test command in optional and in boolean - this is the same as attribute essentially, so testing every permutation is overkill @@ -163,10 +174,11 @@ def test_conformance_optional_on_condition(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) if self.has_ab[i]: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.OPTIONAL) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) else: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), '[AB]') xml = ('' @@ -175,10 +187,11 @@ def test_conformance_optional_on_condition(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) if self.has_cd[i]: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.OPTIONAL) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) else: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), '[CD]') # single attribute optional @@ -188,10 +201,11 @@ def test_conformance_optional_on_condition(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, a in enumerate(self.attribute_lists): + info = ConformanceAssessmentData(feature_map=0, attribute_list=a, all_command_list=[], cluster_revision=1) if self.has_attr1[i]: - asserts.assert_equal(xml_callable(0x00, a, []).decision, ConformanceDecision.OPTIONAL) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) else: - asserts.assert_equal(xml_callable(0x00, a, []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), '[attr1]') xml = ('' @@ -200,10 +214,11 @@ def test_conformance_optional_on_condition(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, a in enumerate(self.attribute_lists): + info = ConformanceAssessmentData(feature_map=0, attribute_list=a, all_command_list=[], cluster_revision=1) if self.has_attr2[i]: - asserts.assert_equal(xml_callable(0x00, a, []).decision, ConformanceDecision.OPTIONAL) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) else: - asserts.assert_equal(xml_callable(0x00, a, []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), '[attr2]') # single command optional @@ -213,10 +228,11 @@ def test_conformance_optional_on_condition(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, c in enumerate(self.cmd_lists): + info = ConformanceAssessmentData(feature_map=0, attribute_list=[], all_command_list=c, cluster_revision=1) if self.has_cmd1[i]: - asserts.assert_equal(xml_callable(0x00, [], c).decision, ConformanceDecision.OPTIONAL) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) else: - asserts.assert_equal(xml_callable(0x00, [], c).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), '[cmd1]') xml = ('' @@ -225,10 +241,11 @@ def test_conformance_optional_on_condition(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, c in enumerate(self.cmd_lists): + info = ConformanceAssessmentData(feature_map=0, attribute_list=[], all_command_list=c, cluster_revision=1) if self.has_cmd2[i]: - asserts.assert_equal(xml_callable(0x00, [], c).decision, ConformanceDecision.OPTIONAL) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) else: - asserts.assert_equal(xml_callable(0x00, [], c).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), '[cmd2]') def test_conformance_not_term_mandatory(self): @@ -241,10 +258,11 @@ def test_conformance_not_term_mandatory(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) if not self.has_ab[i]: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) else: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), '!AB') xml = ('' @@ -255,10 +273,11 @@ def test_conformance_not_term_mandatory(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) if not self.has_cd[i]: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) else: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), '!CD') # single attribute not mandatory @@ -270,10 +289,11 @@ def test_conformance_not_term_mandatory(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, a in enumerate(self.attribute_lists): + info = ConformanceAssessmentData(feature_map=0, attribute_list=a, all_command_list=[], cluster_revision=1) if not self.has_attr1[i]: - asserts.assert_equal(xml_callable(0x00, a, []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) else: - asserts.assert_equal(xml_callable(0x00, a, []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), '!attr1') xml = ('' @@ -284,10 +304,11 @@ def test_conformance_not_term_mandatory(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, a in enumerate(self.attribute_lists): + info = ConformanceAssessmentData(feature_map=0, attribute_list=a, all_command_list=[], cluster_revision=1) if not self.has_attr2[i]: - asserts.assert_equal(xml_callable(0x00, a, []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) else: - asserts.assert_equal(xml_callable(0x00, a, []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), '!attr2') def test_conformance_not_term_optional(self): @@ -300,10 +321,11 @@ def test_conformance_not_term_optional(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) if not self.has_ab[i]: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.OPTIONAL) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) else: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), '[!AB]') xml = ('' @@ -314,10 +336,11 @@ def test_conformance_not_term_optional(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) if not self.has_cd[i]: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.OPTIONAL) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) else: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), '[!CD]') def test_conformance_and_term(self): @@ -331,10 +354,11 @@ def test_conformance_and_term(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) if self.has_ab[i] and self.has_cd[i]: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) else: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), 'AB & CD') # and term for attributes only @@ -347,10 +371,11 @@ def test_conformance_and_term(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, a in enumerate(self.attribute_lists): + info = ConformanceAssessmentData(feature_map=0, attribute_list=a, all_command_list=[], cluster_revision=1) if self.has_attr1[i] and self.has_attr2[i]: - asserts.assert_equal(xml_callable(0x00, a, []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) else: - asserts.assert_equal(xml_callable(0x00, a, []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), 'attr1 & attr2') # and term for feature and attribute @@ -364,10 +389,11 @@ def test_conformance_and_term(self): xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): for j, a in enumerate(self.attribute_lists): + info = ConformanceAssessmentData(feature_map=f, attribute_list=a, all_command_list=[], cluster_revision=1) if self.has_ab[i] and self.has_attr2[j]: - asserts.assert_equal(xml_callable(f, a, []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) else: - asserts.assert_equal(xml_callable(f, a, []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), 'AB & attr2') def test_conformance_or_term(self): @@ -381,10 +407,11 @@ def test_conformance_or_term(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) if self.has_ab[i] or self.has_cd[i]: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) else: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), 'AB | CD') # or term attribute only @@ -397,10 +424,11 @@ def test_conformance_or_term(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, a in enumerate(self.attribute_lists): + info = ConformanceAssessmentData(feature_map=0, attribute_list=a, all_command_list=[], cluster_revision=1) if self.has_attr1[i] or self.has_attr2[i]: - asserts.assert_equal(xml_callable(0x00, a, []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) else: - asserts.assert_equal(xml_callable(0x00, a, []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), 'attr1 | attr2') # or term feature and attribute @@ -414,10 +442,11 @@ def test_conformance_or_term(self): xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): for j, a in enumerate(self.attribute_lists): + info = ConformanceAssessmentData(feature_map=f, attribute_list=a, all_command_list=[], cluster_revision=1) if self.has_ab[i] or self.has_attr2[j]: - asserts.assert_equal(xml_callable(f, a, []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) else: - asserts.assert_equal(xml_callable(f, a, []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), 'AB | attr2') def test_conformance_and_term_with_not(self): @@ -433,10 +462,11 @@ def test_conformance_and_term_with_not(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) if not self.has_ab[i] and self.has_cd[i]: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.OPTIONAL) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) else: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), '[!AB & CD]') def test_conformance_or_term_with_not(self): @@ -452,10 +482,11 @@ def test_conformance_or_term_with_not(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) if self.has_ab[i] or not self.has_cd[i]: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) else: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), 'AB | !CD') # not around or term with @@ -470,10 +501,11 @@ def test_conformance_or_term_with_not(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) if not (self.has_ab[i] or self.has_cd[i]): - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.OPTIONAL) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) else: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), '[!(AB | CD)]') def test_conformance_and_term_with_three_terms(self): @@ -489,11 +521,14 @@ def test_conformance_and_term_with_three_terms(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) # no features - asserts.assert_equal(xml_callable(0x00, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + info = ConformanceAssessmentData(feature_map=0, attribute_list=[], all_command_list=[], cluster_revision=1) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) # one feature - asserts.assert_equal(xml_callable(0x01, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + info = ConformanceAssessmentData(feature_map=0x01, attribute_list=[], all_command_list=[], cluster_revision=1) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) # all features - asserts.assert_equal(xml_callable(0x07, [], []).decision, ConformanceDecision.OPTIONAL) + info = ConformanceAssessmentData(feature_map=0x07, attribute_list=[], all_command_list=[], cluster_revision=1) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) asserts.assert_equal(str(xml_callable), '[AB & CD & EF]') # and term with one of each @@ -509,10 +544,11 @@ def test_conformance_and_term_with_three_terms(self): for i, f in enumerate(self.feature_maps): for j, a in enumerate(self.attribute_lists): for k, c in enumerate(self.cmd_lists): + info = ConformanceAssessmentData(feature_map=f, attribute_list=a, all_command_list=c, cluster_revision=1) if self.has_ab[i] and self.has_attr1[j] and self.has_cmd1[k]: - asserts.assert_equal(xml_callable(f, a, c).decision, ConformanceDecision.OPTIONAL) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) else: - asserts.assert_equal(xml_callable(f, a, c).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), '[AB & attr1 & cmd1]') def test_conformance_or_term_with_three_terms(self): @@ -527,11 +563,14 @@ def test_conformance_or_term_with_three_terms(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) # no features - asserts.assert_equal(xml_callable(0x00, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + info = ConformanceAssessmentData(feature_map=0x00, attribute_list=[], all_command_list=[], cluster_revision=1) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) # one feature - asserts.assert_equal(xml_callable(0x01, [], []).decision, ConformanceDecision.OPTIONAL) + info = ConformanceAssessmentData(feature_map=0x01, attribute_list=[], all_command_list=[], cluster_revision=1) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) # all features - asserts.assert_equal(xml_callable(0x07, [], []).decision, ConformanceDecision.OPTIONAL) + info = ConformanceAssessmentData(feature_map=0x07, attribute_list=[], all_command_list=[], cluster_revision=1) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) asserts.assert_equal(str(xml_callable), '[AB | CD | EF]') # or term with one of each @@ -547,10 +586,11 @@ def test_conformance_or_term_with_three_terms(self): for i, f in enumerate(self.feature_maps): for j, a in enumerate(self.attribute_lists): for k, c in enumerate(self.cmd_lists): + info = ConformanceAssessmentData(feature_map=f, attribute_list=a, all_command_list=c, cluster_revision=1) if self.has_ab[i] or self.has_attr1[j] or self.has_cmd1[k]: - asserts.assert_equal(xml_callable(f, a, c).decision, ConformanceDecision.OPTIONAL) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) else: - asserts.assert_equal(xml_callable(f, a, c).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), '[AB | attr1 | cmd1]') def test_conformance_otherwise(self): @@ -564,10 +604,11 @@ def test_conformance_otherwise(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) if self.has_ab[i]: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) else: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.OPTIONAL) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) asserts.assert_equal(str(xml_callable), 'AB, O') # AB, [CD] @@ -582,12 +623,13 @@ def test_conformance_otherwise(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) if self.has_ab[i]: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) elif self.has_cd[i]: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.OPTIONAL) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.OPTIONAL) else: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.NOT_APPLICABLE) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.NOT_APPLICABLE) asserts.assert_equal(str(xml_callable), 'AB, [CD]') # AB & !CD, P @@ -605,46 +647,40 @@ def test_conformance_otherwise(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) for i, f in enumerate(self.feature_maps): + info = ConformanceAssessmentData(feature_map=f, attribute_list=[], all_command_list=[], cluster_revision=1) if self.has_ab[i] and not self.has_cd[i]: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.MANDATORY) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.MANDATORY) else: - asserts.assert_equal(xml_callable(f, [], []).decision, ConformanceDecision.PROVISIONAL) + asserts.assert_equal(xml_callable(info).decision, ConformanceDecision.PROVISIONAL) asserts.assert_equal(str(xml_callable), 'AB & !CD, P') - def test_conformance_greater(self): - # AB, [CD] - xml = ('' - '' - '' - '' - '' - '') + def _test_conformance_arithmetic(self, term: str, symbol: str): + def create_xml(xml_mid: str) -> str: + return ('' + f'<{term}>' + f'{xml_mid}' + f'' + '') + xml = create_xml(('' + '')) et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) # TODO: switch this to check greater than once the update to the base is done (#33422) - asserts.assert_equal(xml_callable(0x00, [], []).decision, ConformanceDecision.OPTIONAL) - asserts.assert_equal(str(xml_callable), 'attr1 > 1') + asserts.assert_equal(xml_callable(EMPTY_CLUSTER_GLOBAL_ATTRIBUTES).decision, ConformanceDecision.OPTIONAL) + asserts.assert_equal(str(xml_callable), f'attr1 {symbol} 1') # Ensure that we can only have greater terms with exactly 2 value - xml = ('' - '' - '' - '' - '' - '' - '') + xml = create_xml(('' + '' + '')) et = ElementTree.fromstring(xml) try: xml_callable = parse_callable_from_xml(et, self.params) - asserts.fail("Incorrectly parsed bad greaterTerm XML with > 2 values") + asserts.fail(f"Incorrectly parsed bad {term} XML with > 2 values") except ConformanceException: pass - xml = ('' - '' - '' - '' - '') + xml = create_xml(('')) et = ElementTree.fromstring(xml) try: xml_callable = parse_callable_from_xml(et, self.params) @@ -653,19 +689,89 @@ def test_conformance_greater(self): pass # Only attributes and literals allowed because arithmetic operations require values - xml = ('' - '' - '' - '' - '' - '') + xml = create_xml(('' + '')) et = ElementTree.fromstring(xml) try: xml_callable = parse_callable_from_xml(et, self.params) - asserts.fail("Incorrectly parsed greater term with feature value") + asserts.fail(f"Incorrectly parsed {term} with feature value") except ConformanceException: pass + def test_conformance_greater(self): + self._test_conformance_arithmetic('greaterTerm', '>') + + def test_conformance_greater_or_equal(self): + self._test_conformance_arithmetic('greaterOrEqualTerm', '>=') + + def test_revision(self): + def create_xml(revision: int) -> str: + return ('' + '' + '' + f'' + '' + '') + + conformance_assessment_data = EMPTY_CLUSTER_GLOBAL_ATTRIBUTES + + xml = create_xml(2) + et = ElementTree.fromstring(xml) + xml_callable = parse_callable_from_xml(et, self.params) + asserts.assert_equal(str(xml_callable), 'Rev >= v2') + + conformance_assessment_data.cluster_revision = 1 + asserts.assert_equal(xml_callable(conformance_assessment_data).decision, ConformanceDecision.NOT_APPLICABLE) + conformance_assessment_data.cluster_revision = 2 + asserts.assert_equal(xml_callable(conformance_assessment_data).decision, ConformanceDecision.MANDATORY) + conformance_assessment_data.cluster_revision = 3 + asserts.assert_equal(xml_callable(conformance_assessment_data).decision, ConformanceDecision.MANDATORY) + + xml = create_xml(5) + et = ElementTree.fromstring(xml) + xml_callable = parse_callable_from_xml(et, self.params) + asserts.assert_equal(str(xml_callable), 'Rev >= v5') + + conformance_assessment_data.cluster_revision = 1 + asserts.assert_equal(xml_callable(conformance_assessment_data).decision, ConformanceDecision.NOT_APPLICABLE) + conformance_assessment_data.cluster_revision = 2 + asserts.assert_equal(xml_callable(conformance_assessment_data).decision, ConformanceDecision.NOT_APPLICABLE) + conformance_assessment_data.cluster_revision = 4 + asserts.assert_equal(xml_callable(conformance_assessment_data).decision, ConformanceDecision.NOT_APPLICABLE) + conformance_assessment_data.cluster_revision = 5 + asserts.assert_equal(xml_callable(conformance_assessment_data).decision, ConformanceDecision.MANDATORY) + conformance_assessment_data.cluster_revision = 6 + asserts.assert_equal(xml_callable(conformance_assessment_data).decision, ConformanceDecision.MANDATORY) + + too_many_terms = ('' + '' + '' + '' + '' + '' + '') + et = ElementTree.fromstring(too_many_terms) + with asserts.assert_raises(ConformanceException): + xml_callable = parse_callable_from_xml(et, self.params) + + too_few_terms_current = ('' + '' + '' + '' + '') + et = ElementTree.fromstring(too_few_terms_current) + with asserts.assert_raises(ConformanceException): + xml_callable = parse_callable_from_xml(et, self.params) + + too_few_terms_value = ('' + '' + '' + '' + '') + et = ElementTree.fromstring(too_few_terms_value) + with asserts.assert_raises(ConformanceException): + xml_callable = parse_callable_from_xml(et, self.params) + def test_basic_conformance(self): basic_test('', mandatory) basic_test('', optional) @@ -707,7 +813,7 @@ def test_device_type_conformance(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) asserts.assert_equal(str(xml_callable), 'Zigbee', msg) - asserts.assert_equal(xml_callable(0, [], []).decision, ConformanceDecision.NOT_APPLICABLE, msg) + asserts.assert_equal(xml_callable(EMPTY_CLUSTER_GLOBAL_ATTRIBUTES).decision, ConformanceDecision.NOT_APPLICABLE, msg) xml = ('' '' @@ -716,7 +822,7 @@ def test_device_type_conformance(self): xml_callable = parse_callable_from_xml(et, self.params) # expect no exception here asserts.assert_equal(str(xml_callable), '[Zigbee]', msg) - asserts.assert_equal(xml_callable(0, [], []).decision, ConformanceDecision.NOT_APPLICABLE, msg) + asserts.assert_equal(xml_callable(EMPTY_CLUSTER_GLOBAL_ATTRIBUTES).decision, ConformanceDecision.NOT_APPLICABLE, msg) # otherwise conforms are allowed xml = ('' @@ -727,7 +833,7 @@ def test_device_type_conformance(self): xml_callable = parse_callable_from_xml(et, self.params) # expect no exception here asserts.assert_equal(str(xml_callable), 'Zigbee, P', msg) - asserts.assert_equal(xml_callable(0, [], []).decision, ConformanceDecision.PROVISIONAL, msg) + asserts.assert_equal(xml_callable(EMPTY_CLUSTER_GLOBAL_ATTRIBUTES).decision, ConformanceDecision.PROVISIONAL, msg) # TODO: adjust conformance call function to accept a list of conditions and evaluate based on that xml = ('' @@ -738,7 +844,7 @@ def test_device_type_conformance(self): asserts.assert_equal(str(xml_callable), 'CD', msg) # Device conditions are always optional (at least for now), even though we didn't pass in anything # to indicate whether or not this conditions is enabled - asserts.assert_equal(xml_callable(0, [], []).decision, ConformanceDecision.OPTIONAL) + asserts.assert_equal(xml_callable(EMPTY_CLUSTER_GLOBAL_ATTRIBUTES).decision, ConformanceDecision.OPTIONAL) xml = ('' '' @@ -747,7 +853,7 @@ def test_device_type_conformance(self): et = ElementTree.fromstring(xml) xml_callable = parse_callable_from_xml(et, self.params) asserts.assert_equal(str(xml_callable), 'CD, testy', msg) - asserts.assert_equal(xml_callable(0, [], []).decision, ConformanceDecision.OPTIONAL) + asserts.assert_equal(xml_callable(EMPTY_CLUSTER_GLOBAL_ATTRIBUTES).decision, ConformanceDecision.OPTIONAL) def check_good_choice(self, xml: str, conformance_str: str) -> Conformance: et = ElementTree.fromstring(xml) @@ -756,7 +862,9 @@ def check_good_choice(self, xml: str, conformance_str: str) -> Conformance: return xml_callable def check_decision(self, more_expected: bool, conformance: Conformance, feature_map: uint, attr_list: list[uint], cmd_list: list[uint]): - decision = conformance(feature_map, attr_list, cmd_list) + info = ConformanceAssessmentData(feature_map=feature_map, attribute_list=attr_list, + all_command_list=cmd_list, cluster_revision=1) + decision = conformance(info) asserts.assert_true(decision.choice, 'Expected choice conformance on decision, but did not get one') asserts.assert_equal(decision.choice.marker, 'a', 'Unexpected conformance string returned') asserts.assert_equal(decision.choice.more, more_expected, "Unexpected more on choice") @@ -800,21 +908,24 @@ def test_choice_conformance(self): '' '') conformance = self.check_good_choice(xml, f'[AB].{suffix}') - asserts.assert_equal(conformance(0, [], []).decision, ConformanceDecision.NOT_APPLICABLE, msg_not_applicable) + asserts.assert_equal(conformance(EMPTY_CLUSTER_GLOBAL_ATTRIBUTES).decision, + ConformanceDecision.NOT_APPLICABLE, msg_not_applicable) self.check_decision(more, conformance, AB, [], []) xml = (f'' '' '') conformance = self.check_good_choice(xml, f'[attr1].{suffix}') - asserts.assert_equal(conformance(0, [], []).decision, ConformanceDecision.NOT_APPLICABLE, msg_not_applicable) + asserts.assert_equal(conformance(EMPTY_CLUSTER_GLOBAL_ATTRIBUTES).decision, + ConformanceDecision.NOT_APPLICABLE, msg_not_applicable) self.check_decision(more, conformance, 0, attr1, []) xml = (f'' '' '') conformance = self.check_good_choice(xml, f'[cmd1].{suffix}') - asserts.assert_equal(conformance(0, [], []).decision, ConformanceDecision.NOT_APPLICABLE, msg_not_applicable) + asserts.assert_equal(conformance(EMPTY_CLUSTER_GLOBAL_ATTRIBUTES).decision, + ConformanceDecision.NOT_APPLICABLE, msg_not_applicable) self.check_decision(more, conformance, 0, [], cmd1) xml = (f'' @@ -824,7 +935,8 @@ def test_choice_conformance(self): '' '') conformance = self.check_good_choice(xml, f'[AB | CD].{suffix}') - asserts.assert_equal(conformance(0, [], []).decision, ConformanceDecision.NOT_APPLICABLE, msg_not_applicable) + asserts.assert_equal(conformance(ConformanceAssessmentData(feature_map=0, attribute_list=[], all_command_list=[], cluster_revision=1)).decision, + ConformanceDecision.NOT_APPLICABLE, msg_not_applicable) self.check_decision(more, conformance, AB, [], []) xml = (f'' @@ -833,7 +945,8 @@ def test_choice_conformance(self): '' '') conformance = self.check_good_choice(xml, f'[!attr1].{suffix}') - asserts.assert_equal(conformance(0, attr1, []).decision, ConformanceDecision.NOT_APPLICABLE, msg_not_applicable) + asserts.assert_equal(conformance(ConformanceAssessmentData(feature_map=0, attribute_list=attr1, all_command_list=[], cluster_revision=1)).decision, + ConformanceDecision.NOT_APPLICABLE, msg_not_applicable) self.check_decision(more, conformance, 0, [], []) xml = ('' @@ -847,11 +960,13 @@ def test_choice_conformance(self): # with no features or attributes, this should end up as O.a, so there should be a choice self.check_decision(more, conformance, 0, [], []) # when we have this attribute, we should not have a choice - asserts.assert_equal(conformance(0, attr1, []).decision, ConformanceDecision.MANDATORY, 'Unexpected conformance') - asserts.assert_equal(conformance(0, attr1, []).choice, None, 'Unexpected choice in conformance') + info = ConformanceAssessmentData(feature_map=0, attribute_list=attr1, all_command_list=[], cluster_revision=1) + asserts.assert_equal(conformance(info).decision, ConformanceDecision.MANDATORY, 'Unexpected conformance') + asserts.assert_equal(conformance(info).choice, None, 'Unexpected choice in conformance') # when we have only this feature, we should not have a choice - asserts.assert_equal(conformance(AB, [], []).decision, ConformanceDecision.OPTIONAL, 'Unexpected conformance') - asserts.assert_equal(conformance(AB, [], []).choice, None, 'Unexpected choice in conformance') + info = ConformanceAssessmentData(feature_map=AB, attribute_list=[], all_command_list=[], cluster_revision=1) + asserts.assert_equal(conformance(info).decision, ConformanceDecision.OPTIONAL, 'Unexpected conformance') + asserts.assert_equal(conformance(info).choice, None, 'Unexpected choice in conformance') # - multiple in otherwise [AB].a, [CD].b xml = ('' @@ -864,22 +979,26 @@ def test_choice_conformance(self): '' '') conformance = self.check_good_choice(xml, f'attr1, [AB].{suffix}, [CD].b') - asserts.assert_equal(conformance(0, [], []).decision, ConformanceDecision.NOT_APPLICABLE, msg_not_applicable) + asserts.assert_equal(conformance(EMPTY_CLUSTER_GLOBAL_ATTRIBUTES).decision, + ConformanceDecision.NOT_APPLICABLE, msg_not_applicable) # when we have this attribute, we should not have a choice - asserts.assert_equal(conformance(0, attr1, []).decision, ConformanceDecision.MANDATORY, 'Unexpected conformance') - asserts.assert_equal(conformance(0, attr1, []).choice, None, 'Unexpected choice in conformance') + info = ConformanceAssessmentData(feature_map=0, attribute_list=attr1, all_command_list=[], cluster_revision=1) + asserts.assert_equal(conformance(info).decision, ConformanceDecision.MANDATORY, 'Unexpected conformance') + asserts.assert_equal(conformance(info).choice, None, 'Unexpected choice in conformance') # When it's just AB, we should have a choice self.check_decision(more, conformance, AB, [], []) # When we have both the attribute and AB, we should not have a choice - asserts.assert_equal(conformance(0, attr1, []).decision, ConformanceDecision.MANDATORY, 'Unexpected conformance') - asserts.assert_equal(conformance(0, attr1, []).choice, None, 'Unexpected choice in conformance') + info = ConformanceAssessmentData(feature_map=0, attribute_list=attr1, all_command_list=[], cluster_revision=1) + asserts.assert_equal(conformance(info).decision, ConformanceDecision.MANDATORY, 'Unexpected conformance') + asserts.assert_equal(conformance(info).choice, None, 'Unexpected choice in conformance') # When we have AB and CD, we should be using the AB choice CD = self.feature_names_to_bits['CD'] ABCD = AB | CD self.check_decision(more, conformance, ABCD, [], []) # When we just have CD, we still have a choice, but the string should be b - asserts.assert_equal(conformance(CD, [], []).decision, ConformanceDecision.OPTIONAL, 'Unexpected conformance') - asserts.assert_equal(conformance(CD, [], []).choice, Choice('b', False), 'Unexpected choice in conformance') + info = ConformanceAssessmentData(feature_map=CD, attribute_list=[], all_command_list=[], cluster_revision=1) + asserts.assert_equal(conformance(info).decision, ConformanceDecision.OPTIONAL, 'Unexpected conformance') + asserts.assert_equal(conformance(info).choice, Choice('b', False), 'Unexpected choice in conformance') # Ones that should throw exceptions diff --git a/src/python_testing/test_testing/TestSpecParsingDeviceType.py b/src/python_testing/test_testing/TestSpecParsingDeviceType.py index 018d4870bfd..7d8169c0b32 100644 --- a/src/python_testing/test_testing/TestSpecParsingDeviceType.py +++ b/src/python_testing/test_testing/TestSpecParsingDeviceType.py @@ -23,7 +23,7 @@ from mobly import asserts import matter.clusters as Clusters -from matter.testing.conformance import conformance_allowed +from matter.testing.conformance import EMPTY_CLUSTER_GLOBAL_ATTRIBUTES, conformance_allowed from matter.testing.matter_testing import MatterBaseTest, default_matter_test_main from matter.testing.spec_parsing import (PrebuiltDataModelDirectory, XmlDeviceType, build_xml_clusters, build_xml_device_types, parse_single_device_type) @@ -452,7 +452,7 @@ def test_disallowed_cluster(self): expected_problems = 0 self.create_good_device(id) for cluster_id, cluster in dt.server_clusters.items(): - if not conformance_allowed(cluster.conformance(0, [], []), False): + if not conformance_allowed(cluster.conformance(EMPTY_CLUSTER_GLOBAL_ATTRIBUTES), False): self.test.endpoints[1][Clusters.Descriptor][Clusters.Descriptor.Attributes.ServerList].append(cluster_id) expected_problems += 1 if expected_problems == 0: @@ -470,12 +470,14 @@ def test_spec_files(self): one_four_one, one_four_one_problems = build_xml_device_types(PrebuiltDataModelDirectory.k1_4_1) one_four_two, one_four_two_problems = build_xml_device_types(PrebuiltDataModelDirectory.k1_4_2) one_five, one_five_problems = build_xml_device_types(PrebuiltDataModelDirectory.k1_5) + one_five_one, one_five_one_problems = build_xml_device_types(PrebuiltDataModelDirectory.k1_5_1) self.problems.extend(one_two_problems) self.problems.extend(one_three_problems) self.problems.extend(one_four_problems) self.problems.extend(one_four_one_problems) self.problems.extend(one_four_two_problems) self.problems.extend(one_five_problems) + self.problems.extend(one_five_one_problems) asserts.assert_equal(len(one_two_problems), 0, "Problems found when parsing 1.2 spec") asserts.assert_equal(len(one_three_problems), 0, "Problems found when parsing 1.3 spec") @@ -483,6 +485,7 @@ def test_spec_files(self): asserts.assert_equal(len(one_four_one_problems), 0, "Problems found when parsing 1.4.1 spec") asserts.assert_equal(len(one_four_two_problems), 0, "Problems found when parsing 1.4.2 spec") asserts.assert_equal(len(one_five_problems), 0, "Problems found when parsing 1.5 spec") + asserts.assert_equal(len(one_five_one_problems), 0, "Problems found when parsing 1.5.1 spec") # Current ballot has a bunch of problems related to IDs being allocated for closures and TBR. These should all # mention ID-TBD as the id, so let's pull those out for now and make sure there are no UNKNOWN problems. @@ -514,6 +517,8 @@ def test_spec_files(self): set(), "There are some 1.3 device types that are unexpectedly not included in the 1.4.2 spec") asserts.assert_equal(set(one_four_two.keys())-set(one_five.keys()), set(), "There are some 1.4.2 device types that are unexpectedly not included in the 1.5 spec") + asserts.assert_equal(set(one_five.keys())-set(one_five_one.keys()), + set(), "There are some 1.5 device types that are unexpectedly not included in the 1.5.1 spec") @run_against_all_spec_revisions def test_application_device_type_on_root(self): diff --git a/src/python_testing/test_testing/TestSpecParsingSelection.py b/src/python_testing/test_testing/TestSpecParsingSelection.py index 487fa47974f..bbd0d4e3f1c 100644 --- a/src/python_testing/test_testing/TestSpecParsingSelection.py +++ b/src/python_testing/test_testing/TestSpecParsingSelection.py @@ -20,7 +20,7 @@ from mobly import asserts, signals import matter.clusters as Clusters -from matter.testing.conformance import ConformanceDecision, ConformanceException +from matter.testing.conformance import ConformanceAssessmentData, ConformanceDecision, ConformanceException from matter.testing.global_attribute_ids import is_standard_attribute_id from matter.testing.matter_testing import MatterBaseTest, default_matter_test_main from matter.testing.spec_parsing import PrebuiltDataModelDirectory, build_xml_clusters, dm_from_spec_version @@ -50,6 +50,8 @@ def test_dm_from_spec_version(self): "Incorrect directory selected for 1.4.2") asserts.assert_equal(dm_from_spec_version(0x01050000), PrebuiltDataModelDirectory.k1_5, "Incorrect directory selected for 1.5") + asserts.assert_equal(dm_from_spec_version(0x01050100), PrebuiltDataModelDirectory.k1_5_1, + "Incorrect directory selected for 1.5.1") # 1.2 doesn't include a specification revision field, so this should error with asserts.assert_raises(ConformanceException, "Expected assertion was not raised for spec version 1.2"): @@ -62,9 +64,9 @@ def test_dm_from_spec_version(self): with asserts.assert_raises(ConformanceException, "Data model incorrectly identified for 1.4.FF"): dm_from_spec_version(0x0104FF00) - # Any dot release besides 0 for 1.5 should error - with asserts.assert_raises(ConformanceException, "Data model incorrectly identified for 1.5.1"): - dm_from_spec_version(0x01050100) + # Any dot release above .1 should error for 1.5 + with asserts.assert_raises(ConformanceException, "Data model incorrectly identified for 1.5.2"): + dm_from_spec_version(0x01050200) with asserts.assert_raises(ConformanceException, "Data model incorrectly identified for 1.5.FF"): dm_from_spec_version(0x0105FF00) @@ -94,13 +96,14 @@ def create_cluster_globals(cluster, feature_map): spec_attributes = xml_clusters[cluster.id].attributes spec_accepted_commands = xml_clusters[cluster.id].accepted_commands spec_generated_commands = xml_clusters[cluster.id].generated_commands + info = ConformanceAssessmentData(feature_map=feature_map, attribute_list=[], all_command_list=[], cluster_revision=1) # Build just the lists - basic composition checks the wildcard against the lists, conformance just uses lists attributes = [id for id, a in spec_attributes.items() if a.conformance( - feature_map, [], []).decision == ConformanceDecision.MANDATORY] + info).decision == ConformanceDecision.MANDATORY] accepted_commands = [id for id, c in spec_accepted_commands.items() if c.conformance( - feature_map, [], []).decision == ConformanceDecision.MANDATORY] + info).decision == ConformanceDecision.MANDATORY] generated_commands = [id for id, c in spec_generated_commands.items() if c.conformance( - feature_map, [], []).decision == ConformanceDecision.MANDATORY] + info).decision == ConformanceDecision.MANDATORY] attr = cluster.Attributes resp = {} diff --git a/src/python_testing/test_testing/TestSpecParsingSupport.py b/src/python_testing/test_testing/TestSpecParsingSupport.py index 32c47f0db0e..71355ce046a 100644 --- a/src/python_testing/test_testing/TestSpecParsingSupport.py +++ b/src/python_testing/test_testing/TestSpecParsingSupport.py @@ -275,6 +275,7 @@ def test_build_xml_override(self): one_four_one_clusters, one_four_one_problems = build_xml_clusters(PrebuiltDataModelDirectory.k1_4_1) one_four_two_xml_clusters, one_four_two_problems = build_xml_clusters(PrebuiltDataModelDirectory.k1_4_2) one_five_xml_clusters, one_five_problems = build_xml_clusters(PrebuiltDataModelDirectory.k1_5) + one_five_one_xml_clusters, one_five_one_problems = build_xml_clusters(PrebuiltDataModelDirectory.k1_5_1) # We know 1.2, 1.3, 1.4 and 1.4.1, 1.4.2 are clear of errors, ensure it stays that way. asserts.assert_equal(len(one_two_problems), 0, "Unexpected problems found on 1.2 cluster parsing") @@ -285,6 +286,9 @@ def test_build_xml_override(self): for p in one_five_problems: print(p) asserts.assert_equal(len(one_five_problems), 0, "Unexpected problems found on 1.5 cluster parsing") + for p in one_five_one_problems: + print(p) + asserts.assert_equal(len(one_five_problems), 0, "Unexpected problems found on 1.5.1 cluster parsing") asserts.assert_greater(len(set(one_four_two_xml_clusters.keys()) - set(one_two_clusters.keys())), 0, "1.2.2 dir does not contain any clusters not in 1.3") @@ -298,6 +302,8 @@ def test_build_xml_override(self): "1.4 and 1.4.1 do not contain the same clusters") asserts.assert_greater(len(set(one_five_xml_clusters.keys()) - set(one_four_two_xml_clusters.keys())), 0, "1.5 dir does not contain any clusters not in 1.4.2") + asserts.assert_greater_equal(len(set(one_five_one_xml_clusters.keys()) - set(one_five_xml_clusters.keys())), + 0, "1.5.1 has fewer clusters than 1.5") # The following clusters were removed in 1.3: Scenes, Leaf Wetness Measurement, Soil Moisture Measurement one_two_removed = {0x0005, 0x0407, 0x0408} diff --git a/src/python_testing/test_testing/fake_device_builder.py b/src/python_testing/test_testing/fake_device_builder.py index e30f2810ad7..42ff1f2c13f 100644 --- a/src/python_testing/test_testing/fake_device_builder.py +++ b/src/python_testing/test_testing/fake_device_builder.py @@ -17,14 +17,15 @@ from typing import Any, Optional import matter.clusters as Clusters -from matter.testing.conformance import ConformanceDecision +from matter.testing.conformance import ConformanceAssessmentData, ConformanceDecision from matter.testing.global_attribute_ids import GlobalAttributeIds from matter.testing.spec_parsing import XmlCluster, XmlDeviceType from matter.tlv import uint -def _is_mandatory(conformance, feature_map=0): - return conformance(feature_map, [], []).decision == ConformanceDecision.MANDATORY +def _is_mandatory(conformance, feature_map=0, revision=1): + info = ConformanceAssessmentData(feature_map, [], [], revision) + return conformance(info).decision == ConformanceDecision.MANDATORY def _get_field_by_label(cl_object: Clusters.ClusterObjects.ClusterObject, label: str) -> Optional[Clusters.ClusterObjects.ClusterObjectFieldDescriptor]: @@ -36,24 +37,26 @@ def _get_field_by_label(cl_object: Clusters.ClusterObjects.ClusterObject, label: def create_minimal_cluster(xml_clusters: dict[uint, XmlCluster], cluster_id: int, is_tlv_endpoint: bool = True, additional_features: list[uint] = [], additional_attributes: list[uint] = [], additional_commands: list[uint] = []) -> dict[int, Any]: attrs = {} - mandatory_features = [mask for mask, f in xml_clusters[cluster_id].features.items() if _is_mandatory(f.conformance)] + mandatory_features = [mask for mask, f in xml_clusters[cluster_id].features.items( + ) if _is_mandatory(f.conformance, revision=xml_clusters[cluster_id].revision)] mandatory_features.extend(additional_features) feature_map = 0 for mask in mandatory_features: feature_map |= mask + revision = xml_clusters[cluster_id].revision + info = ConformanceAssessmentData(feature_map, [], [], revision) mandatory_attributes = [id for id, a in xml_clusters[cluster_id].attributes.items( - ) if a.conformance(feature_map, [], []).decision == ConformanceDecision.MANDATORY] + ) if a.conformance(info).decision == ConformanceDecision.MANDATORY] mandatory_attributes.extend(additional_attributes) mandatory_accepted_commands = [id for id, c in xml_clusters[cluster_id].accepted_commands.items( - ) if c.conformance(feature_map, [], []).decision == ConformanceDecision.MANDATORY] + ) if c.conformance(info).decision == ConformanceDecision.MANDATORY] mandatory_accepted_commands.extend(additional_commands) mandatory_generated_commands = [id for id, c in xml_clusters[cluster_id].generated_commands.items( - ) if c.conformance(feature_map, [], []).decision == ConformanceDecision.MANDATORY] + ) if c.conformance(info).decision == ConformanceDecision.MANDATORY] - revision = xml_clusters[cluster_id].revision if is_tlv_endpoint: for m in mandatory_attributes: # dummy versions - we're not using the values in this test diff --git a/src/python_testing/test_testing/test_TC_DA_1_2.py b/src/python_testing/test_testing/test_TC_DA_1_2.py index 07b79dc6aed..3fdccc90335 100755 --- a/src/python_testing/test_testing/test_TC_DA_1_2.py +++ b/src/python_testing/test_testing/test_TC_DA_1_2.py @@ -16,17 +16,19 @@ # limitations under the License. # +import io import json import os import subprocess import sys +from typing import Optional CHIP_ROOT = os.path.abspath(os.path.join( os.path.dirname(__file__), '../../..')) RUNNER_SCRIPT_DIR = os.path.join(CHIP_ROOT, 'scripts/tests') -def run_single_test(dac_provider: str, product_id: int, factory_reset: bool = False) -> int: +def run_single_test(dac_provider: str, product_id: int, factory_reset: bool = False, additional_script_args: Optional[str] = None) -> int: reset = "" if factory_reset: @@ -34,6 +36,7 @@ def run_single_test(dac_provider: str, product_id: int, factory_reset: bool = Fa app = os.path.join( CHIP_ROOT, 'objdir-clone/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app') + app = os.path.join(CHIP_ROOT, 'out', 'linux-x64-all-clusters-no-ble', 'chip-all-clusters-app') # Certs in the commissioner_dut directory use 0x8000 as the PID app_args = '--discriminator 1234 --KVS kvs1 --product-id ' + \ @@ -43,6 +46,8 @@ def run_single_test(dac_provider: str, product_id: int, factory_reset: bool = Fa CHIP_ROOT, 'src/app/tests/suites/certification/ci-pics-values')) script_args = '--storage-path admin_storage.json --discriminator 1234 --passcode 20202021 --dut-node-id 1 --PICS ' + \ str(ci_pics_values) + if additional_script_args: + script_args = script_args + ' ' + additional_script_args # for any test with a dac_provider, we don't want to recommission because there's a chance the # dac could be wrong and the commissioning would fail. Rely on the original commissioning. This is also faster. @@ -78,7 +83,22 @@ def main(): exclude_cases = ['struct_cd_version_number_wrong', 'struct_cd_cert_id_mismatch'] + # Provisional CDs signed by the test key are handled two different ways by this test. + # By default, these fail DA-1.2 even though they work in the commissioner. + # They can be made to pass the test with a flag, so these are tested separately + exclude_cases += ['struct_cd_provisional_cd'] + passes = [] + + def load_test_case_vector(cert_path, p) -> tuple[str, bool, int]: + ''' Loads the test_case_vector.json and returns a tuple with the path, expected success response and the pid''' + path = str(os.path.join(cert_path, p, 'test_case_vector.json')) + with open(path, 'r') as f: + j = json.loads(f.read()) + success_expected = j['is_success_case'].lower() == 'true' + pid = j['basic_info_pid'] + return (path, success_expected, pid) + for p in os.listdir(cert_path): matches = list(filter(lambda t: t in str(p), test_cases)) if len(matches) != 1: @@ -87,15 +107,29 @@ def main(): if str(p) in exclude_cases: continue - path = str(os.path.join(cert_path, p, 'test_case_vector.json')) - with open(path, 'r') as f: - j = json.loads(f.read()) - success_expected = j['is_success_case'].lower() == 'true' - pid = j['basic_info_pid'] + path, success_expected, pid = load_test_case_vector(cert_path, p) ret = run_single_test(path, pid) passes.append((str(p), ret, success_expected)) + # Provisional CDs work two ways currently, depending on the flag + p = 'struct_cd_provisional_cd' + path, _, pid = load_test_case_vector(cert_path, p) + # Default is to fail + ret = run_single_test(path, pid) + passes.append((f'{str(p)} (no flag)', ret, False)) + + # This should pass, but there is a manual step to acknowledge the provisional CD with the wrong signer + mock_input = io.StringIO("\n") + original_stdin = sys.stdin + sys.stdin = mock_input + ret = run_single_test(path, pid, additional_script_args='--bool-arg override_provisional_cd_check_warning:true') + passes.append((f'{str(p)} (flag=true)', ret, True)) + sys.stdin = original_stdin + + ret = run_single_test(path, pid, additional_script_args='--bool-arg override_provisional_cd_check_warning:false') + passes.append((f'{str(p)} (flag=false)', ret, False)) + retval = 0 for p in passes: success = p[1] == 0 diff --git a/src/system/SystemPacketBuffer.cpp b/src/system/SystemPacketBuffer.cpp index f644d1a23eb..73a09c0325c 100644 --- a/src/system/SystemPacketBuffer.cpp +++ b/src/system/SystemPacketBuffer.cpp @@ -589,10 +589,35 @@ PacketBufferHandle PacketBufferHandle::New(size_t aAvailableSize, uint16_t aRese } #if CHIP_SYSTEM_CONFIG_USE_LWIP +#if CHIP_SYSTEM_CONFIG_PACKETBUFFER_LWIP_PBUF_RAM + // Allocate buffer using kMaxAllocSize instead of the requested size (lAllocSize). + // + // Rationale: + // 1. PBUF_RAM provides a contiguous payload buffer, ensuring consistent behavior + // with PBUF_POOL (non-chained) operations regardless of actual data size. + // 2. The standard lwIP pbuf structure lacks a field to store the actual allocated + // size. By always allocating kMaxAllocSize, AllocSize() can return a constant + // value (kMaxAllocSize) without needing to track the original allocation size. + // + // kMaxAllocSize configuration: + // - TCP: Configurable via CHIP_SYSTEM_CONFIG_MAX_LARGE_BUFFER_SIZE_BYTES to support + // larger packets exceeding IPv6 MTU. Note: This may result in unused buffer + // space; configure based on the maximum packet size requirements. + // - UDP: Fixed to LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) + // + // Despite allocating kMaxAllocSize, we still keep the validation for lAllocSize + // to fail early if the requested size exceeds the maximum capacity. + // + // This cast is safe because kLargeBufMaxSizeWithoutReserve has been statically + // asserted to fit in uint16_t. + lPacket = static_cast( + pbuf_alloc(PBUF_RAW, static_cast(PacketBuffer::kMaxAllocSize), CHIP_SYSTEM_PACKETBUFFER_LWIP_PBUF_TYPE)); +#else // This cast is safe because lAllocSize is no larger than // kMaxSizeWithoutReserve, which fits in uint16_t. lPacket = static_cast( pbuf_alloc(PBUF_RAW, static_cast(lAllocSize), CHIP_SYSTEM_PACKETBUFFER_LWIP_PBUF_TYPE)); +#endif SYSTEM_STATS_UPDATE_LWIP_PBUF_COUNTS(); diff --git a/src/system/SystemPacketBuffer.h b/src/system/SystemPacketBuffer.h index 8fd73b9c352..6363521c443 100644 --- a/src/system/SystemPacketBuffer.h +++ b/src/system/SystemPacketBuffer.h @@ -178,6 +178,8 @@ class DLL_EXPORT PacketBuffer : private pbuf return LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) - kStructureSize; else return LWIP_MEM_ALIGN_SIZE(memp_sizes[this->pool]) - kStructureSize; +#elif CHIP_SYSTEM_CONFIG_PACKETBUFFER_LWIP_PBUF_RAM + return PacketBuffer::kMaxAllocSize; #else #error "Unimplemented PacketBuffer storage case" #endif diff --git a/src/tools/chip-cert/Cmd_GenCD.cpp b/src/tools/chip-cert/Cmd_GenCD.cpp index e2577ff0350..42079b3b4c4 100644 --- a/src/tools/chip-cert/Cmd_GenCD.cpp +++ b/src/tools/chip-cert/Cmd_GenCD.cpp @@ -691,11 +691,16 @@ bool HandleOption(const char * progName, OptionSet * optSet, int id, const char { gCDConfig.SetCMSSignatureWrong(); } + else if ((strcmp(arg, "provisional-cd") != 0) || (strcmp(arg, "official-cd") != 0)) + { + // Set by the -t flag, do nothing + } else if (strcmp(arg, "no-error") != 0) { PrintArgError("%s: Invalid value specified for the error type: %s\n", progName, arg); return false; } + break; #endif default: diff --git a/src/tools/chip-cert/gen_com_dut_test_vectors.py b/src/tools/chip-cert/gen_com_dut_test_vectors.py index 702868c691b..c0522f1770f 100755 --- a/src/tools/chip-cert/gen_com_dut_test_vectors.py +++ b/src/tools/chip-cert/gen_com_dut_test_vectors.py @@ -684,6 +684,22 @@ class CertType(Enum): "error_flag": 'different-origin', "is_success_case": 'true', }, + { + "description": 'CD certification type is provisional (signed by test key)', + "test_folder": "provisional_cd", + "error_flag": 'provisional-cd', + # This is currently success by default when the SDK supports test keys. This should be moved to + # default failure after a sufficient notice period. + # https://github.com/project-chip/connectedhomeip/issues/42460 + "is_success_case": 'true', + }, + { + "description": 'CD certification type is official (signed by test key)', + "test_folder": "official_cd", + "error_flag": 'official-cd', + # This is an error because it is an official CD signed by a test key. + "is_success_case": 'false', + }, ] @@ -1018,9 +1034,16 @@ def main(): else: authorized_paa_flag = '' + if test_case["error_flag"] == 'provisional-cd': + certification_type = 1 + elif test_case["error_flag"] == 'official-cd': + certification_type = 2 + else: + certification_type = 0 + cmd = chipcert + ' gen-cd -I -E ' + test_case["error_flag"] + ' -K ' + cd_key + ' -C ' + cd_cert + ' -O ' + \ test_case_out_dir + '/cd.der' + ' -f 1 ' + vid_flag + pid_flag + dac_origin_flag + authorized_paa_flag + \ - ' -d 0x1234 -c "ZIG20141ZB330001-24" -l 0 -i 0 -n 9876 -t 0' + ' -d 0x1234 -c "ZIG20141ZB330001-24" -l 0 -i 0 -n 9876 -t ' + str(certification_type) subprocess.run(cmd, shell=True) # Generate Test Case Data Container in JSON Format diff --git a/src/transport/SessionManager.cpp b/src/transport/SessionManager.cpp index 899b7dbfe05..ecd67f8a553 100644 --- a/src/transport/SessionManager.cpp +++ b/src/transport/SessionManager.cpp @@ -711,6 +711,7 @@ void SessionManager::HandleConnectionClosed(Transport::ActiveTCPConnectionState appTCPConnCbCtxt->connClosedCb(conn, conErr); } MarkSecureSessionOverTCPForEviction(conn, conErr); + mUnauthenticatedSessions.MarkSessionOverTCPForEviction(conn); } CHIP_ERROR SessionManager::TCPConnect(const PeerAddress & peerAddress, Transport::AppTCPConnectionCallbackCtxt * appState, diff --git a/src/transport/UnauthenticatedSessionTable.h b/src/transport/UnauthenticatedSessionTable.h index 172b5011871..6b6d5592b65 100644 --- a/src/transport/UnauthenticatedSessionTable.h +++ b/src/transport/UnauthenticatedSessionTable.h @@ -294,6 +294,25 @@ class UnauthenticatedSessionTable return Optional::Missing(); } +#if INET_CONFIG_ENABLE_TCP_ENDPOINT + void MarkSessionOverTCPForEviction(Transport::ActiveTCPConnectionState & conn) + { + mEntries.ForEachActiveObject([&](UnauthenticatedSession * session) { + if (session->GetTCPConnection() == conn) + { + session->ReleaseTCPConnection(); + + // If the session has no other references, we can release it. + if (session->GetReferenceCount() == 0) + { + mEntries.ReleaseObject(static_cast(session)); + } + } + return Loop::Continue; + }); + } +#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT + private: using EntryType = detail::UnauthenticatedSessionPoolEntry; friend EntryType; @@ -304,7 +323,6 @@ class UnauthenticatedSessionTable * @returns CHIP_NO_ERROR if new session created. May fail if maximum session count has been reached (with * CHIP_ERROR_NO_MEMORY). */ - CHECK_RETURN_VALUE CHIP_ERROR AllocEntry(UnauthenticatedSession::SessionRole sessionRole, NodeId ephemeralInitiatorNodeID, const PeerAddress & peerAddress, const ReliableMessageProtocolConfig & config, UnauthenticatedSession *& entry) diff --git a/src/transport/raw/TCP.cpp b/src/transport/raw/TCP.cpp index 6fc6c9343e1..2bbf1396d6a 100644 --- a/src/transport/raw/TCP.cpp +++ b/src/transport/raw/TCP.cpp @@ -160,6 +160,8 @@ ActiveTCPConnectionState * TCPBase::AllocateConnection(const Inet::TCPEndPointHa char addrStr[Transport::PeerAddress::kMaxToStringSize]; activeConnection->mPeerAddr.ToString(addrStr); ChipLogError(Inet, "Leaked TCP connection %p to %s.", activeConnection, addrStr); + // Try to notify callbacks in the hope that they release; the connection is no good + CloseConnectionInternal(*activeConnection, CHIP_ERROR_CONNECTION_CLOSED_UNEXPECTEDLY, SuppressCallback::No); } ActiveTCPConnectionHandle releaseUnclaimed(activeConnection); } diff --git a/src/transport/tests/BUILD.gn b/src/transport/tests/BUILD.gn index c5c269fe940..6ad36d40030 100644 --- a/src/transport/tests/BUILD.gn +++ b/src/transport/tests/BUILD.gn @@ -46,7 +46,11 @@ chip_test_suite("tests") { if (chip_device_platform != "esp32" && chip_device_platform != "nrfconnect" && chip_device_platform != "nxp") { - test_sources += [ "TestSecureSessionTable.cpp" ] + test_sources += [ + "TestSecureSessionTable.cpp", + # Disabling this test because of changes to the Testing namespace in master + # "TestTCPConnection.cpp", + ] } cflags = [ "-Wconversion" ] @@ -58,6 +62,7 @@ chip_test_suite("tests") { "${chip_root}/src/lib/core", "${chip_root}/src/lib/core:string-builder-adapters", "${chip_root}/src/lib/support", + "${chip_root}/src/lib/support:test_utils", "${chip_root}/src/lib/support:testing", "${chip_root}/src/protocols", "${chip_root}/src/transport", diff --git a/src/transport/tests/TestTCPConnection.cpp b/src/transport/tests/TestTCPConnection.cpp new file mode 100644 index 00000000000..ae959ba9297 --- /dev/null +++ b/src/transport/tests/TestTCPConnection.cpp @@ -0,0 +1,235 @@ +/* + * + * Copyright (c) 2025 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * This file implements an E2E test for the SessionManager/Transport/UnauthenticatedSession + * TCP connection. + */ + +#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::Inet; +using namespace chip::Transport; +using namespace chip::Testing; + +namespace { + +// Use only 2 active connections (1 outgoing, 1 incoming) to easily detect leaks (exhaustion) +constexpr size_t kMaxTcpActiveConnectionCount = 2; +constexpr size_t kMaxTcpPendingPackets = 4; +constexpr int kMaxPortBindRetries = 100; + +using TCPImpl = Transport::TCP; + +uint16_t GetRandomPort() +{ + return static_cast(CHIP_PORT + chip::Crypto::GetRandU16() % 1000); +} + +CHIP_ERROR RetryPortSetup(uint16_t & outPort, std::function setupFn) +{ + CHIP_ERROR err; + for (int retryCount = 0; retryCount < kMaxPortBindRetries; retryCount++) + { + uint16_t port = GetRandomPort(); + + err = setupFn(port); + if (err == CHIP_ERROR_POSIX(EADDRINUSE)) + { + continue; + } + + outPort = (err == CHIP_NO_ERROR) ? port : 0; + return err; + } + return err; +} + +class TestTCPConnection : public ::testing::Test, public SessionConnectionDelegate, public SessionMessageDelegate +{ +public: + static void SetUpTestSuite() + { + if (mIOContext == nullptr) + { + mIOContext = new IOContext(); + ASSERT_NE(mIOContext, nullptr); + } + EXPECT_SUCCESS(mIOContext->Init()); + } + static void TearDownTestSuite() + { + if (mIOContext != nullptr) + { + mIOContext->Shutdown(); + delete mIOContext; + mIOContext = nullptr; + } + } + + void SetUp() override + { + // Ignore Init return value, we check correctness later/implicitly + (void) mTransportMgrBase.Init(&mTCP); + mTransportMgrBase.SetSessionManager(&mSessionManager); + + mSessionManager.SetConnectionDelegate(this); + mSessionManager.SetMessageDelegate(this); + } + + void TearDown() override + { + mSessionManager.Shutdown(); + mTransportMgrBase.Close(); + mTCP.Close(); + mFabricTable.Shutdown(); + mOpKeyStore.Finish(); + mOpCertStore.Finish(); + } + + // SessionConnectionDelegate + void OnTCPConnectionClosed(const Transport::ActiveTCPConnectionState & conn, const SessionHandle & session, + CHIP_ERROR conErr) override + {} + + bool OnTCPConnectionAttemptComplete(Transport::ActiveTCPConnectionHandle & conn, CHIP_ERROR conErr) override { return true; } + + // SessionMessageDelegate + void OnMessageReceived(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader, const SessionHandle & session, + DuplicateMessage isDuplicate, System::PacketBufferHandle && msgBuf) override + {} + +protected: + static IOContext * mIOContext; + TCPImpl mTCP; + TransportMgrBase mTransportMgrBase; + SessionManager mSessionManager; + secure_channel::MessageCounterManager mMessageCounterManager; + chip::TestPersistentStorageDelegate mDeviceStorage; + chip::Crypto::DefaultSessionKeystore mSessionKeystore; + chip::PersistentStorageOperationalKeystore mOpKeyStore; + chip::Credentials::PersistentStorageOpCertStore mOpCertStore; + FabricTable mFabricTable; + + CHIP_ERROR InitTCP(uint16_t & outPort) + { + return RetryPortSetup(outPort, [&](uint16_t port) { + return mTCP.Init(Transport::TcpListenParameters(mIOContext->GetTCPEndPointManager()) + .SetAddressType(IPAddressType::kIPv6) + .SetListenPort(port) + .SetServerListenEnabled(true)); + }); + } + + CHIP_ERROR InitSessionManager() + { + ReturnErrorOnFailure(mOpKeyStore.Init(&mDeviceStorage)); + ReturnErrorOnFailure(mOpCertStore.Init(&mDeviceStorage)); + + chip::FabricTable::InitParams initParams; + initParams.storage = &mDeviceStorage; + initParams.operationalKeystore = &mOpKeyStore; + initParams.opCertStore = &mOpCertStore; + + ReturnErrorOnFailure(mFabricTable.Init(initParams)); + + return mSessionManager.Init(&mIOContext->GetSystemLayer(), &mTransportMgrBase, &mMessageCounterManager, &mDeviceStorage, + &mFabricTable, mSessionKeystore); + } +}; + +IOContext * TestTCPConnection::mIOContext = nullptr; + +TEST_F(TestTCPConnection, TestUnauthenticatedSessionReleaseOnConnectionClose) +{ + uint16_t port; + EXPECT_SUCCESS(InitTCP(port)); + EXPECT_SUCCESS(InitSessionManager()); + + IPAddress addr; + IPAddress::FromString("::1", addr); + + // Connect to self (loopback) + Transport::PeerAddress peerAddr = Transport::PeerAddress::TCP(addr, port); + + // 1. Establish initial connection (Leaked Candidate) + ActiveTCPConnectionHandle connHandle; + EXPECT_SUCCESS(mTCP.TCPConnect(peerAddr, nullptr, connHandle)); + + mIOContext->DriveIOUntil(chip::System::Clock::Seconds16(5), + [&]() { return !connHandle.IsNull() && connHandle->IsConnected(); }); + ASSERT_FALSE(connHandle.IsNull()); + ASSERT_TRUE(connHandle->IsConnected()); + + // 2. Create UnauthenticatedSession by simulating an incoming message + PayloadHeader header; + uint8_t payloadBuffer[64]; + uint16_t encodeLen; + header.SetMessageType(Protocols::Id(VendorId::Common, 1221), 112).SetExchangeID(2233).SetInitiator(true); + EXPECT_SUCCESS(header.Encode(payloadBuffer, &encodeLen)); + + auto msgBuf = System::PacketBufferHandle::NewWithData(payloadBuffer, encodeLen); + PacketHeader packetHeader; + packetHeader.SetSourceNodeId(1234).SetMessageCounter(1); + packetHeader.SetSessionType(Header::SessionType::kUnicastSession); // Unauthenticated + + EXPECT_SUCCESS(packetHeader.EncodeBeforeData(msgBuf)); + + { + Transport::MessageTransportContext ctxt; + ctxt.conn = connHandle; + + mSessionManager.OnMessageReceived(peerAddr, std::move(msgBuf), &ctxt); + } + + // Close TCP connection & release local handle + connHandle->ForceDisconnect(); + connHandle.Release(); + + // Drive IO to process TCP closure + mIOContext->DriveIOUntil(chip::System::Clock::Seconds16(1), [&]() { return false; }); + + // 5. Try to connect again to make sure there's no leak + EXPECT_SUCCESS(mTCP.TCPConnect(peerAddr, nullptr, connHandle)); +} + +} // namespace diff --git a/third_party/nxp/nxp_matter_support b/third_party/nxp/nxp_matter_support index 5a002007a61..d5e65670b37 160000 --- a/third_party/nxp/nxp_matter_support +++ b/third_party/nxp/nxp_matter_support @@ -1 +1 @@ -Subproject commit 5a002007a613fa6ce725ce2663de3cf77221290c +Subproject commit d5e65670b37c6bef48b310da5540a9ef0492106e diff --git a/third_party/openthread/ot-nxp b/third_party/openthread/ot-nxp index 0993e0a8140..9330a58a6c2 160000 --- a/third_party/openthread/ot-nxp +++ b/third_party/openthread/ot-nxp @@ -1 +1 @@ -Subproject commit 0993e0a8140d1c6d002c5fb5b9d39b294a147499 +Subproject commit 9330a58a6c2a3518b1c1415600f3323f103f2637 diff --git a/third_party/openthread/platforms/nxp/rt/rt1060/BUILD.gn b/third_party/openthread/platforms/nxp/rt/rt1060/BUILD.gn index 06e8741d183..d8d6ae9aae0 100644 --- a/third_party/openthread/platforms/nxp/rt/rt1060/BUILD.gn +++ b/third_party/openthread/platforms/nxp/rt/rt1060/BUILD.gn @@ -67,6 +67,8 @@ config("openthread_rt1060_config") { "OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE=1", "DISABLE_TCPIP_INIT=1", "OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE=1", + "OPENTHREAD_CONFIG_TREL_MANAGE_DNSSD_ENABLE=1", + "OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_ENABLE=1", ] if (nxp_enable_matter_cli) { @@ -118,6 +120,7 @@ source_set("libopenthread-rt1060") { sources += [ "${openthread_nxp_root}/src/common/br/border_agent.c", "${openthread_nxp_root}/src/common/br/br_rtos_manager.c", + "${openthread_nxp_root}/src/common/br/dhcp6pd_socket.c", "${openthread_nxp_root}/src/common/br/dns_upstream_resolver.c", "${openthread_nxp_root}/src/common/br/infra_if.c", "${openthread_nxp_root}/src/common/br/lwip_hooks.c", diff --git a/third_party/openthread/platforms/nxp/rt/rt1170/BUILD.gn b/third_party/openthread/platforms/nxp/rt/rt1170/BUILD.gn index 93343c5efd0..e8730f1634d 100644 --- a/third_party/openthread/platforms/nxp/rt/rt1170/BUILD.gn +++ b/third_party/openthread/platforms/nxp/rt/rt1170/BUILD.gn @@ -66,6 +66,8 @@ config("openthread_rt1170_config") { "OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE=1", "DISABLE_TCPIP_INIT=1", "OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE=1", + "OPENTHREAD_CONFIG_TREL_MANAGE_DNSSD_ENABLE=1", + "OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_ENABLE=1", ] if (nxp_enable_matter_cli) { @@ -116,6 +118,7 @@ source_set("libopenthread-rt1170") { sources += [ "${openthread_nxp_root}/src/common/br/border_agent.c", "${openthread_nxp_root}/src/common/br/br_rtos_manager.c", + "${openthread_nxp_root}/src/common/br/dhcp6pd_socket.c", "${openthread_nxp_root}/src/common/br/dns_upstream_resolver.c", "${openthread_nxp_root}/src/common/br/infra_if.c", "${openthread_nxp_root}/src/common/br/lwip_hooks.c", diff --git a/third_party/openthread/platforms/nxp/rt/rw61x/BUILD.gn b/third_party/openthread/platforms/nxp/rt/rw61x/BUILD.gn index f52654a9680..0811d66654c 100644 --- a/third_party/openthread/platforms/nxp/rt/rw61x/BUILD.gn +++ b/third_party/openthread/platforms/nxp/rt/rw61x/BUILD.gn @@ -69,6 +69,8 @@ config("openthread_rw61x_config") { "OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE=1", "DISABLE_TCPIP_INIT=1", "OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE=1", + "OPENTHREAD_CONFIG_TREL_MANAGE_DNSSD_ENABLE=1", + "OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_ENABLE=1", ] if (nxp_enable_matter_cli) { @@ -118,6 +120,7 @@ source_set("libopenthread-rw61x") { sources += [ "${openthread_nxp_root}/src/common/br/border_agent.c", "${openthread_nxp_root}/src/common/br/br_rtos_manager.c", + "${openthread_nxp_root}/src/common/br/dhcp6pd_socket.c", "${openthread_nxp_root}/src/common/br/dns_upstream_resolver.c", "${openthread_nxp_root}/src/common/br/infra_if.c", "${openthread_nxp_root}/src/common/br/lwip_hooks.c", diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp index a09c7991671..b7aace1aba1 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp @@ -34262,394 +34262,6 @@ Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value) namespace CameraAvSettingsUserLevelManagement { namespace Attributes { -namespace MaxPresets { - -Protocols::InteractionModel::Status Get(EndpointId endpoint, uint8_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint8_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(ConcreteAttributePath(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id), - EmberAfWriteDataInput(writable, ZCL_INT8U_ATTRIBUTE_TYPE).SetMarkDirty(markDirty)); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint8_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id, writable, - ZCL_INT8U_ATTRIBUTE_TYPE); -} - -} // namespace MaxPresets - -namespace ZoomMax { - -Protocols::InteractionModel::Status Get(EndpointId endpoint, uint8_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint8_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(ConcreteAttributePath(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id), - EmberAfWriteDataInput(writable, ZCL_INT8U_ATTRIBUTE_TYPE).SetMarkDirty(markDirty)); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint8_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id, writable, - ZCL_INT8U_ATTRIBUTE_TYPE); -} - -} // namespace ZoomMax - -namespace TiltMin { - -Protocols::InteractionModel::Status Get(EndpointId endpoint, int16_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, int16_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(ConcreteAttributePath(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id), - EmberAfWriteDataInput(writable, ZCL_INT16S_ATTRIBUTE_TYPE).SetMarkDirty(markDirty)); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, int16_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id, writable, - ZCL_INT16S_ATTRIBUTE_TYPE); -} - -} // namespace TiltMin - -namespace TiltMax { - -Protocols::InteractionModel::Status Get(EndpointId endpoint, int16_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, int16_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(ConcreteAttributePath(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id), - EmberAfWriteDataInput(writable, ZCL_INT16S_ATTRIBUTE_TYPE).SetMarkDirty(markDirty)); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, int16_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id, writable, - ZCL_INT16S_ATTRIBUTE_TYPE); -} - -} // namespace TiltMax - -namespace PanMin { - -Protocols::InteractionModel::Status Get(EndpointId endpoint, int16_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, int16_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(ConcreteAttributePath(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id), - EmberAfWriteDataInput(writable, ZCL_INT16S_ATTRIBUTE_TYPE).SetMarkDirty(markDirty)); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, int16_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id, writable, - ZCL_INT16S_ATTRIBUTE_TYPE); -} - -} // namespace PanMin - -namespace PanMax { - -Protocols::InteractionModel::Status Get(EndpointId endpoint, int16_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, int16_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(ConcreteAttributePath(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id), - EmberAfWriteDataInput(writable, ZCL_INT16S_ATTRIBUTE_TYPE).SetMarkDirty(markDirty)); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, int16_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id, writable, - ZCL_INT16S_ATTRIBUTE_TYPE); -} - -} // namespace PanMax - -namespace MovementState { - -Protocols::InteractionModel::Status Get(EndpointId endpoint, - chip::app::Clusters::CameraAvSettingsUserLevelManagement::PhysicalMovementEnum * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, - chip::app::Clusters::CameraAvSettingsUserLevelManagement::PhysicalMovementEnum value, - MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(ConcreteAttributePath(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id), - EmberAfWriteDataInput(writable, ZCL_ENUM8_ATTRIBUTE_TYPE).SetMarkDirty(markDirty)); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, - chip::app::Clusters::CameraAvSettingsUserLevelManagement::PhysicalMovementEnum value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id, writable, - ZCL_ENUM8_ATTRIBUTE_TYPE); -} - -} // namespace MovementState - -namespace FeatureMap { - -Protocols::InteractionModel::Status Get(EndpointId endpoint, uint32_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint32_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(ConcreteAttributePath(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id), - EmberAfWriteDataInput(writable, ZCL_BITMAP32_ATTRIBUTE_TYPE).SetMarkDirty(markDirty)); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint32_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::CameraAvSettingsUserLevelManagement::Id, Id, writable, - ZCL_BITMAP32_ATTRIBUTE_TYPE); -} - -} // namespace FeatureMap - namespace ClusterRevision { Protocols::InteractionModel::Status Get(EndpointId endpoint, uint16_t * value) diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h index 591b15ef0b1..cc4aa9b47a0 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h +++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h @@ -5296,59 +5296,6 @@ Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value, Mar namespace CameraAvSettingsUserLevelManagement { namespace Attributes { -namespace MaxPresets { -Protocols::InteractionModel::Status Get(EndpointId endpoint, uint8_t * value); // int8u -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint8_t value); -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint8_t value, MarkAttributeDirty markDirty); -} // namespace MaxPresets - -namespace ZoomMax { -Protocols::InteractionModel::Status Get(EndpointId endpoint, uint8_t * value); // int8u -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint8_t value); -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint8_t value, MarkAttributeDirty markDirty); -} // namespace ZoomMax - -namespace TiltMin { -Protocols::InteractionModel::Status Get(EndpointId endpoint, int16_t * value); // int16s -Protocols::InteractionModel::Status Set(EndpointId endpoint, int16_t value); -Protocols::InteractionModel::Status Set(EndpointId endpoint, int16_t value, MarkAttributeDirty markDirty); -} // namespace TiltMin - -namespace TiltMax { -Protocols::InteractionModel::Status Get(EndpointId endpoint, int16_t * value); // int16s -Protocols::InteractionModel::Status Set(EndpointId endpoint, int16_t value); -Protocols::InteractionModel::Status Set(EndpointId endpoint, int16_t value, MarkAttributeDirty markDirty); -} // namespace TiltMax - -namespace PanMin { -Protocols::InteractionModel::Status Get(EndpointId endpoint, int16_t * value); // int16s -Protocols::InteractionModel::Status Set(EndpointId endpoint, int16_t value); -Protocols::InteractionModel::Status Set(EndpointId endpoint, int16_t value, MarkAttributeDirty markDirty); -} // namespace PanMin - -namespace PanMax { -Protocols::InteractionModel::Status Get(EndpointId endpoint, int16_t * value); // int16s -Protocols::InteractionModel::Status Set(EndpointId endpoint, int16_t value); -Protocols::InteractionModel::Status Set(EndpointId endpoint, int16_t value, MarkAttributeDirty markDirty); -} // namespace PanMax - -namespace MovementState { -Protocols::InteractionModel::Status -Get(EndpointId endpoint, - chip::app::Clusters::CameraAvSettingsUserLevelManagement::PhysicalMovementEnum * value); // PhysicalMovementEnum -Protocols::InteractionModel::Status Set(EndpointId endpoint, - chip::app::Clusters::CameraAvSettingsUserLevelManagement::PhysicalMovementEnum value); -Protocols::InteractionModel::Status Set(EndpointId endpoint, - chip::app::Clusters::CameraAvSettingsUserLevelManagement::PhysicalMovementEnum value, - MarkAttributeDirty markDirty); -} // namespace MovementState - -namespace FeatureMap { -Protocols::InteractionModel::Status Get(EndpointId endpoint, uint32_t * value); // bitmap32 -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint32_t value); -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint32_t value, MarkAttributeDirty markDirty); -} // namespace FeatureMap - namespace ClusterRevision { Protocols::InteractionModel::Status Get(EndpointId endpoint, uint16_t * value); // int16u Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value); diff --git a/zzz_generated/app-common/clusters/CameraAvStreamManagement/Enums.h b/zzz_generated/app-common/clusters/CameraAvStreamManagement/Enums.h index fd1768aba86..90a6aa2de4e 100644 --- a/zzz_generated/app-common/clusters/CameraAvStreamManagement/Enums.h +++ b/zzz_generated/app-common/clusters/CameraAvStreamManagement/Enums.h @@ -44,11 +44,12 @@ enum class AudioCodecEnum : uint8_t enum class ImageCodecEnum : uint8_t { kJpeg = 0x00, + kHeic = 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 = 1, + kUnknownEnumValue = 2, }; // Enum for TriStateAutoEnum diff --git a/zzz_generated/app-common/clusters/CameraAvStreamManagement/EnumsCheck.h b/zzz_generated/app-common/clusters/CameraAvStreamManagement/EnumsCheck.h index 210f3435c1f..93d0f9a4305 100644 --- a/zzz_generated/app-common/clusters/CameraAvStreamManagement/EnumsCheck.h +++ b/zzz_generated/app-common/clusters/CameraAvStreamManagement/EnumsCheck.h @@ -43,6 +43,7 @@ static auto __attribute__((unused)) EnsureKnownEnumValue(CameraAvStreamManagemen switch (val) { case EnumType::kJpeg: + case EnumType::kHeic: return val; default: return EnumType::kUnknownEnumValue; diff --git a/zzz_generated/app-common/clusters/Chime/Commands.h b/zzz_generated/app-common/clusters/Chime/Commands.h index 53c58696c20..3a852fac571 100644 --- a/zzz_generated/app-common/clusters/Chime/Commands.h +++ b/zzz_generated/app-common/clusters/Chime/Commands.h @@ -58,6 +58,7 @@ namespace Commands { namespace PlayChimeSound { enum class Fields : uint8_t { + kChimeID = 0, }; struct Type @@ -67,6 +68,8 @@ struct Type static constexpr CommandId GetCommandId() { return Commands::PlayChimeSound::Id; } static constexpr ClusterId GetClusterId() { return Clusters::Chime::Id; } + Optional chimeID; + CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; using ResponseType = DataModel::NullObjectType; @@ -81,6 +84,8 @@ struct DecodableType static constexpr ClusterId GetClusterId() { return Clusters::Chime::Id; } static constexpr bool kIsFabricScoped = false; + Optional chimeID; + CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace PlayChimeSound diff --git a/zzz_generated/app-common/clusters/Chime/Commands.ipp b/zzz_generated/app-common/clusters/Chime/Commands.ipp index e14fe63df08..9300d2e2d97 100644 --- a/zzz_generated/app-common/clusters/Chime/Commands.ipp +++ b/zzz_generated/app-common/clusters/Chime/Commands.ipp @@ -34,6 +34,7 @@ namespace PlayChimeSound { CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const { DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; + encoder.Encode(to_underlying(Fields::kChimeID), chimeID); return encoder.Finalize(); } @@ -47,6 +48,11 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) VerifyOrReturnError(err != CHIP_ERROR_END_OF_TLV, CHIP_NO_ERROR); ReturnErrorOnFailure(err); + if (__context_tag == to_underlying(Fields::kChimeID)) + { + err = DataModel::Decode(reader, chimeID); + } + ReturnErrorOnFailure(err); } } diff --git a/zzz_generated/app-common/clusters/Chime/EventIds.h b/zzz_generated/app-common/clusters/Chime/EventIds.h index 747b5263c7a..580cb220d5c 100644 --- a/zzz_generated/app-common/clusters/Chime/EventIds.h +++ b/zzz_generated/app-common/clusters/Chime/EventIds.h @@ -10,7 +10,12 @@ namespace chip { namespace app { namespace Clusters { namespace Chime { -namespace Events {} // namespace Events +namespace Events { +namespace ChimeStartedPlaying { +inline constexpr EventId Id = 0x00000000; +} // namespace ChimeStartedPlaying + +} // namespace Events } // namespace Chime } // namespace Clusters } // namespace app diff --git a/zzz_generated/app-common/clusters/Chime/Events.h b/zzz_generated/app-common/clusters/Chime/Events.h index 7c0bae83978..a3655e90c19 100644 --- a/zzz_generated/app-common/clusters/Chime/Events.h +++ b/zzz_generated/app-common/clusters/Chime/Events.h @@ -42,7 +42,41 @@ namespace chip { namespace app { namespace Clusters { namespace Chime { -namespace Events {} // namespace Events +namespace Events { +namespace ChimeStartedPlaying { +static constexpr PriorityLevel kPriorityLevel = PriorityLevel::Info; + +enum class Fields : uint8_t +{ + kChimeID = 0, +}; + +struct Type +{ +public: + static constexpr PriorityLevel GetPriorityLevel() { return kPriorityLevel; } + static constexpr EventId GetEventId() { return Events::ChimeStartedPlaying::Id; } + static constexpr ClusterId GetClusterId() { return Clusters::Chime::Id; } + static constexpr bool kIsFabricScoped = false; + + uint8_t chimeID = static_cast(0); + + CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; +}; + +struct DecodableType +{ +public: + static constexpr PriorityLevel GetPriorityLevel() { return kPriorityLevel; } + static constexpr EventId GetEventId() { return Events::ChimeStartedPlaying::Id; } + static constexpr ClusterId GetClusterId() { return Clusters::Chime::Id; } + + uint8_t chimeID = static_cast(0); + + CHIP_ERROR Decode(TLV::TLVReader & reader); +}; +} // namespace ChimeStartedPlaying +} // namespace Events } // namespace Chime } // namespace Clusters } // namespace app diff --git a/zzz_generated/app-common/clusters/Chime/Events.ipp b/zzz_generated/app-common/clusters/Chime/Events.ipp index 3ab605d48ac..1cce308381f 100644 --- a/zzz_generated/app-common/clusters/Chime/Events.ipp +++ b/zzz_generated/app-common/clusters/Chime/Events.ipp @@ -29,7 +29,39 @@ namespace chip { namespace app { namespace Clusters { namespace Chime { -namespace Events {} // namespace Events +namespace Events { +namespace ChimeStartedPlaying { +CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const +{ + TLV::TLVType outer; + ReturnErrorOnFailure(aWriter.StartContainer(aTag, TLV::kTLVType_Structure, outer)); + ReturnErrorOnFailure(DataModel::Encode(aWriter, TLV::ContextTag(Fields::kChimeID), chimeID)); + return aWriter.EndContainer(outer); +} + +CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) +{ + detail::StructDecodeIterator __iterator(reader); + while (true) + { + uint8_t __context_tag = 0; + CHIP_ERROR err = __iterator.Next(__context_tag); + VerifyOrReturnError(err != CHIP_ERROR_END_OF_TLV, CHIP_NO_ERROR); + ReturnErrorOnFailure(err); + + if (__context_tag == to_underlying(Fields::kChimeID)) + { + err = DataModel::Decode(reader, chimeID); + } + else + { + } + + ReturnErrorOnFailure(err); + } +} +} // namespace ChimeStartedPlaying. +} // namespace Events } // namespace Chime } // namespace Clusters } // namespace app diff --git a/zzz_generated/app-common/clusters/Chime/Metadata.h b/zzz_generated/app-common/clusters/Chime/Metadata.h index ed416c17953..9f59341e2ef 100644 --- a/zzz_generated/app-common/clusters/Chime/Metadata.h +++ b/zzz_generated/app-common/clusters/Chime/Metadata.h @@ -17,7 +17,7 @@ namespace app { namespace Clusters { namespace Chime { -inline constexpr uint32_t kRevision = 1; +inline constexpr uint32_t kRevision = 2; namespace Attributes { @@ -53,7 +53,12 @@ inline constexpr DataModel::AcceptedCommandEntry kMetadataEntry(PlayChimeSound:: } // namespace Commands -namespace Events {} // namespace Events +namespace Events { +namespace ChimeStartedPlaying { +inline constexpr DataModel::EventEntry kMetadataEntry{ Access::Privilege::kView }; +} // namespace ChimeStartedPlaying + +} // namespace Events } // namespace Chime } // namespace Clusters } // namespace app diff --git a/zzz_generated/app-common/clusters/PushAvStreamTransport/Enums.h b/zzz_generated/app-common/clusters/PushAvStreamTransport/Enums.h index 48087815b7d..48223f0fc67 100644 --- a/zzz_generated/app-common/clusters/PushAvStreamTransport/Enums.h +++ b/zzz_generated/app-common/clusters/PushAvStreamTransport/Enums.h @@ -76,6 +76,8 @@ enum class StatusCodeEnum : uint8_t kInvalidOptions = 0x09, kInvalidStreamUsage = 0x0A, kInvalidTime = 0x0B, + kInvalidPreRollLength = 0x0C, + kDuplicateStreamValues = 0x0D, // 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 @@ -111,14 +113,15 @@ enum class TransportTriggerTypeEnum : uint8_t // Enum for TriggerActivationReasonEnum enum class TriggerActivationReasonEnum : uint8_t { - kUserInitiated = 0x00, - kAutomation = 0x01, - kEmergency = 0x02, + kUserInitiated = 0x00, + kAutomation = 0x01, + kEmergency = 0x02, + kDoorbellPressed = 0x03, // 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 = 3, + kUnknownEnumValue = 4, }; // Bitmap for Feature diff --git a/zzz_generated/app-common/clusters/PushAvStreamTransport/EnumsCheck.h b/zzz_generated/app-common/clusters/PushAvStreamTransport/EnumsCheck.h index 9484b6e899a..07899c81337 100644 --- a/zzz_generated/app-common/clusters/PushAvStreamTransport/EnumsCheck.h +++ b/zzz_generated/app-common/clusters/PushAvStreamTransport/EnumsCheck.h @@ -75,6 +75,8 @@ static auto __attribute__((unused)) EnsureKnownEnumValue(PushAvStreamTransport:: case EnumType::kInvalidOptions: case EnumType::kInvalidStreamUsage: case EnumType::kInvalidTime: + case EnumType::kInvalidPreRollLength: + case EnumType::kDuplicateStreamValues: return val; default: return EnumType::kUnknownEnumValue; @@ -113,6 +115,7 @@ static auto __attribute__((unused)) EnsureKnownEnumValue(PushAvStreamTransport:: case EnumType::kUserInitiated: case EnumType::kAutomation: case EnumType::kEmergency: + case EnumType::kDoorbellPressed: return val; default: return EnumType::kUnknownEnumValue; diff --git a/zzz_generated/app-common/clusters/PushAvStreamTransport/Events.h b/zzz_generated/app-common/clusters/PushAvStreamTransport/Events.h index e0dfa00ce75..fff854ccb6f 100644 --- a/zzz_generated/app-common/clusters/PushAvStreamTransport/Events.h +++ b/zzz_generated/app-common/clusters/PushAvStreamTransport/Events.h @@ -48,9 +48,11 @@ static constexpr PriorityLevel kPriorityLevel = PriorityLevel::Info; enum class Fields : uint8_t { - kConnectionID = 0, - kTriggerType = 1, - kActivationReason = 2, + kConnectionID = 0, + kTriggerType = 1, + kActivationReason = 2, + kContainerType = 3, + kCMAFSessionNumber = 4, }; struct Type @@ -64,6 +66,8 @@ struct Type uint16_t connectionID = static_cast(0); TransportTriggerTypeEnum triggerType = static_cast(0); Optional activationReason; + ContainerFormatEnum containerType = static_cast(0); + Optional CMAFSessionNumber; CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; }; @@ -78,6 +82,8 @@ struct DecodableType uint16_t connectionID = static_cast(0); TransportTriggerTypeEnum triggerType = static_cast(0); Optional activationReason; + ContainerFormatEnum containerType = static_cast(0); + Optional CMAFSessionNumber; CHIP_ERROR Decode(TLV::TLVReader & reader); }; @@ -87,7 +93,9 @@ static constexpr PriorityLevel kPriorityLevel = PriorityLevel::Info; enum class Fields : uint8_t { - kConnectionID = 0, + kConnectionID = 0, + kContainerType = 1, + kCMAFSessionNumber = 2, }; struct Type @@ -98,7 +106,9 @@ struct Type static constexpr ClusterId GetClusterId() { return Clusters::PushAvStreamTransport::Id; } static constexpr bool kIsFabricScoped = false; - uint16_t connectionID = static_cast(0); + uint16_t connectionID = static_cast(0); + ContainerFormatEnum containerType = static_cast(0); + Optional CMAFSessionNumber; CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; }; @@ -110,7 +120,9 @@ struct DecodableType static constexpr EventId GetEventId() { return Events::PushTransportEnd::Id; } static constexpr ClusterId GetClusterId() { return Clusters::PushAvStreamTransport::Id; } - uint16_t connectionID = static_cast(0); + uint16_t connectionID = static_cast(0); + ContainerFormatEnum containerType = static_cast(0); + Optional CMAFSessionNumber; CHIP_ERROR Decode(TLV::TLVReader & reader); }; diff --git a/zzz_generated/app-common/clusters/PushAvStreamTransport/Events.ipp b/zzz_generated/app-common/clusters/PushAvStreamTransport/Events.ipp index 713303d0a2e..20aaca52a59 100644 --- a/zzz_generated/app-common/clusters/PushAvStreamTransport/Events.ipp +++ b/zzz_generated/app-common/clusters/PushAvStreamTransport/Events.ipp @@ -38,6 +38,8 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const ReturnErrorOnFailure(DataModel::Encode(aWriter, TLV::ContextTag(Fields::kConnectionID), connectionID)); ReturnErrorOnFailure(DataModel::Encode(aWriter, TLV::ContextTag(Fields::kTriggerType), triggerType)); ReturnErrorOnFailure(DataModel::Encode(aWriter, TLV::ContextTag(Fields::kActivationReason), activationReason)); + ReturnErrorOnFailure(DataModel::Encode(aWriter, TLV::ContextTag(Fields::kContainerType), containerType)); + ReturnErrorOnFailure(DataModel::Encode(aWriter, TLV::ContextTag(Fields::kCMAFSessionNumber), CMAFSessionNumber)); return aWriter.EndContainer(outer); } @@ -63,6 +65,14 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { err = DataModel::Decode(reader, activationReason); } + else if (__context_tag == to_underlying(Fields::kContainerType)) + { + err = DataModel::Decode(reader, containerType); + } + else if (__context_tag == to_underlying(Fields::kCMAFSessionNumber)) + { + err = DataModel::Decode(reader, CMAFSessionNumber); + } else { } @@ -77,6 +87,8 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const TLV::TLVType outer; ReturnErrorOnFailure(aWriter.StartContainer(aTag, TLV::kTLVType_Structure, outer)); ReturnErrorOnFailure(DataModel::Encode(aWriter, TLV::ContextTag(Fields::kConnectionID), connectionID)); + ReturnErrorOnFailure(DataModel::Encode(aWriter, TLV::ContextTag(Fields::kContainerType), containerType)); + ReturnErrorOnFailure(DataModel::Encode(aWriter, TLV::ContextTag(Fields::kCMAFSessionNumber), CMAFSessionNumber)); return aWriter.EndContainer(outer); } @@ -94,6 +106,14 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { err = DataModel::Decode(reader, connectionID); } + else if (__context_tag == to_underlying(Fields::kContainerType)) + { + err = DataModel::Decode(reader, containerType); + } + else if (__context_tag == to_underlying(Fields::kCMAFSessionNumber)) + { + err = DataModel::Decode(reader, CMAFSessionNumber); + } else { } diff --git a/zzz_generated/app-common/clusters/PushAvStreamTransport/Metadata.h b/zzz_generated/app-common/clusters/PushAvStreamTransport/Metadata.h index d45b68ff54e..b3502a0f31c 100644 --- a/zzz_generated/app-common/clusters/PushAvStreamTransport/Metadata.h +++ b/zzz_generated/app-common/clusters/PushAvStreamTransport/Metadata.h @@ -17,7 +17,7 @@ namespace app { namespace Clusters { namespace PushAvStreamTransport { -inline constexpr uint32_t kRevision = 1; +inline constexpr uint32_t kRevision = 2; namespace Attributes { diff --git a/zzz_generated/app-common/clusters/PushAvStreamTransport/Structs.h b/zzz_generated/app-common/clusters/PushAvStreamTransport/Structs.h index 1301f3206f3..d9633071e15 100644 --- a/zzz_generated/app-common/clusters/PushAvStreamTransport/Structs.h +++ b/zzz_generated/app-common/clusters/PushAvStreamTransport/Structs.h @@ -87,6 +87,52 @@ struct Type using DecodableType = Type; } // namespace TransportZoneOptionsStruct +namespace AudioStreamStruct { +enum class Fields : uint8_t +{ + kAudioStreamName = 0, + kAudioStreamID = 1, +}; + +struct Type +{ +public: + chip::CharSpan audioStreamName; + uint16_t audioStreamID = static_cast(0); + + CHIP_ERROR Decode(TLV::TLVReader & reader); + + static constexpr bool kIsFabricScoped = false; + + CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; +}; + +using DecodableType = Type; + +} // namespace AudioStreamStruct +namespace VideoStreamStruct { +enum class Fields : uint8_t +{ + kVideoStreamName = 0, + kVideoStreamID = 1, +}; + +struct Type +{ +public: + chip::CharSpan videoStreamName; + uint16_t videoStreamID = static_cast(0); + + CHIP_ERROR Decode(TLV::TLVReader & reader); + + static constexpr bool kIsFabricScoped = false; + + CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; +}; + +using DecodableType = Type; + +} // namespace VideoStreamStruct namespace TransportTriggerOptionsStruct { enum class Fields : uint8_t { @@ -196,6 +242,8 @@ enum class Fields : uint8_t kIngestMethod = 6, kContainerOptions = 7, kExpiryTime = 8, + kVideoStreams = 9, + kAudioStreams = 10, }; struct Type @@ -210,6 +258,8 @@ struct Type IngestMethodsEnum ingestMethod = static_cast(0); Structs::ContainerOptionsStruct::Type containerOptions; Optional expiryTime; + Optional> videoStreams; + Optional> audioStreams; static constexpr bool kIsFabricScoped = false; @@ -228,6 +278,8 @@ struct DecodableType IngestMethodsEnum ingestMethod = static_cast(0); Structs::ContainerOptionsStruct::DecodableType containerOptions; Optional expiryTime; + Optional> videoStreams; + Optional> audioStreams; CHIP_ERROR Decode(TLV::TLVReader & reader); diff --git a/zzz_generated/app-common/clusters/PushAvStreamTransport/Structs.ipp b/zzz_generated/app-common/clusters/PushAvStreamTransport/Structs.ipp index 80ce7691719..096935e1879 100644 --- a/zzz_generated/app-common/clusters/PushAvStreamTransport/Structs.ipp +++ b/zzz_generated/app-common/clusters/PushAvStreamTransport/Structs.ipp @@ -107,6 +107,74 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) } // namespace TransportZoneOptionsStruct +namespace AudioStreamStruct { +CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const +{ + DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; + encoder.Encode(to_underlying(Fields::kAudioStreamName), audioStreamName); + encoder.Encode(to_underlying(Fields::kAudioStreamID), audioStreamID); + return encoder.Finalize(); +} + +CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) +{ + detail::StructDecodeIterator __iterator(reader); + while (true) + { + uint8_t __context_tag = 0; + CHIP_ERROR err = __iterator.Next(__context_tag); + VerifyOrReturnError(err != CHIP_ERROR_END_OF_TLV, CHIP_NO_ERROR); + ReturnErrorOnFailure(err); + + if (__context_tag == to_underlying(Fields::kAudioStreamName)) + { + err = DataModel::Decode(reader, audioStreamName); + } + else if (__context_tag == to_underlying(Fields::kAudioStreamID)) + { + err = DataModel::Decode(reader, audioStreamID); + } + + ReturnErrorOnFailure(err); + } +} + +} // namespace AudioStreamStruct + +namespace VideoStreamStruct { +CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const +{ + DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; + encoder.Encode(to_underlying(Fields::kVideoStreamName), videoStreamName); + encoder.Encode(to_underlying(Fields::kVideoStreamID), videoStreamID); + return encoder.Finalize(); +} + +CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) +{ + detail::StructDecodeIterator __iterator(reader); + while (true) + { + uint8_t __context_tag = 0; + CHIP_ERROR err = __iterator.Next(__context_tag); + VerifyOrReturnError(err != CHIP_ERROR_END_OF_TLV, CHIP_NO_ERROR); + ReturnErrorOnFailure(err); + + if (__context_tag == to_underlying(Fields::kVideoStreamName)) + { + err = DataModel::Decode(reader, videoStreamName); + } + else if (__context_tag == to_underlying(Fields::kVideoStreamID)) + { + err = DataModel::Decode(reader, videoStreamID); + } + + ReturnErrorOnFailure(err); + } +} + +} // namespace VideoStreamStruct + namespace TransportTriggerOptionsStruct { CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const { @@ -267,6 +335,8 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const encoder.Encode(to_underlying(Fields::kIngestMethod), ingestMethod); encoder.Encode(to_underlying(Fields::kContainerOptions), containerOptions); encoder.Encode(to_underlying(Fields::kExpiryTime), expiryTime); + encoder.Encode(to_underlying(Fields::kVideoStreams), videoStreams); + encoder.Encode(to_underlying(Fields::kAudioStreams), audioStreams); return encoder.Finalize(); } @@ -316,6 +386,14 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { err = DataModel::Decode(reader, expiryTime); } + else if (__context_tag == to_underlying(Fields::kVideoStreams)) + { + err = DataModel::Decode(reader, videoStreams); + } + else if (__context_tag == to_underlying(Fields::kAudioStreams)) + { + err = DataModel::Decode(reader, audioStreams); + } ReturnErrorOnFailure(err); } diff --git a/zzz_generated/app-common/clusters/WebRTCTransportProvider/Commands.h b/zzz_generated/app-common/clusters/WebRTCTransportProvider/Commands.h index 0f7643cc22e..cf04f2482fe 100644 --- a/zzz_generated/app-common/clusters/WebRTCTransportProvider/Commands.h +++ b/zzz_generated/app-common/clusters/WebRTCTransportProvider/Commands.h @@ -96,6 +96,8 @@ enum class Fields : uint8_t kICETransportPolicy = 5, kMetadataEnabled = 6, kSFrameConfig = 7, + kVideoStreams = 8, + kAudioStreams = 9, }; struct Type @@ -113,6 +115,8 @@ struct Type Optional ICETransportPolicy; Optional metadataEnabled; Optional SFrameConfig; + Optional> videoStreams; + Optional> audioStreams; CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; @@ -136,6 +140,8 @@ struct DecodableType Optional ICETransportPolicy; Optional metadataEnabled; Optional SFrameConfig; + Optional> videoStreams; + Optional> audioStreams; CHIP_ERROR Decode(TLV::TLVReader & reader, FabricIndex aAccessingFabricIndex); }; @@ -195,6 +201,8 @@ enum class Fields : uint8_t kICETransportPolicy = 7, kMetadataEnabled = 8, kSFrameConfig = 9, + kVideoStreams = 10, + kAudioStreams = 11, }; struct Type @@ -214,6 +222,8 @@ struct Type Optional ICETransportPolicy; Optional metadataEnabled; Optional SFrameConfig; + Optional> videoStreams; + Optional> audioStreams; CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; @@ -239,6 +249,8 @@ struct DecodableType Optional ICETransportPolicy; Optional metadataEnabled; Optional SFrameConfig; + Optional> videoStreams; + Optional> audioStreams; CHIP_ERROR Decode(TLV::TLVReader & reader, FabricIndex aAccessingFabricIndex); }; diff --git a/zzz_generated/app-common/clusters/WebRTCTransportProvider/Commands.ipp b/zzz_generated/app-common/clusters/WebRTCTransportProvider/Commands.ipp index 6856a8b8c1b..02db930aa85 100644 --- a/zzz_generated/app-common/clusters/WebRTCTransportProvider/Commands.ipp +++ b/zzz_generated/app-common/clusters/WebRTCTransportProvider/Commands.ipp @@ -42,6 +42,8 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const encoder.Encode(to_underlying(Fields::kICETransportPolicy), ICETransportPolicy); encoder.Encode(to_underlying(Fields::kMetadataEnabled), metadataEnabled); encoder.Encode(to_underlying(Fields::kSFrameConfig), SFrameConfig); + encoder.Encode(to_underlying(Fields::kVideoStreams), videoStreams); + encoder.Encode(to_underlying(Fields::kAudioStreams), audioStreams); return encoder.Finalize(); } @@ -87,6 +89,14 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader, FabricIndex aAccessing { err = DataModel::Decode(reader, SFrameConfig); } + else if (__context_tag == to_underlying(Fields::kVideoStreams)) + { + err = DataModel::Decode(reader, videoStreams); + } + else if (__context_tag == to_underlying(Fields::kAudioStreams)) + { + err = DataModel::Decode(reader, audioStreams); + } ReturnErrorOnFailure(err); } @@ -150,6 +160,8 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const encoder.Encode(to_underlying(Fields::kICETransportPolicy), ICETransportPolicy); encoder.Encode(to_underlying(Fields::kMetadataEnabled), metadataEnabled); encoder.Encode(to_underlying(Fields::kSFrameConfig), SFrameConfig); + encoder.Encode(to_underlying(Fields::kVideoStreams), videoStreams); + encoder.Encode(to_underlying(Fields::kAudioStreams), audioStreams); return encoder.Finalize(); } @@ -203,6 +215,14 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader, FabricIndex aAccessing { err = DataModel::Decode(reader, SFrameConfig); } + else if (__context_tag == to_underlying(Fields::kVideoStreams)) + { + err = DataModel::Decode(reader, videoStreams); + } + else if (__context_tag == to_underlying(Fields::kAudioStreams)) + { + err = DataModel::Decode(reader, audioStreams); + } ReturnErrorOnFailure(err); } diff --git a/zzz_generated/app-common/clusters/WebRTCTransportProvider/Metadata.h b/zzz_generated/app-common/clusters/WebRTCTransportProvider/Metadata.h index 7790dea37dd..3f4f706a6c7 100644 --- a/zzz_generated/app-common/clusters/WebRTCTransportProvider/Metadata.h +++ b/zzz_generated/app-common/clusters/WebRTCTransportProvider/Metadata.h @@ -17,7 +17,7 @@ namespace app { namespace Clusters { namespace WebRTCTransportProvider { -inline constexpr uint32_t kRevision = 1; +inline constexpr uint32_t kRevision = 2; namespace Attributes { diff --git a/zzz_generated/app-common/clusters/WebRTCTransportRequestor/Metadata.h b/zzz_generated/app-common/clusters/WebRTCTransportRequestor/Metadata.h index f1d958e5727..118938c653c 100644 --- a/zzz_generated/app-common/clusters/WebRTCTransportRequestor/Metadata.h +++ b/zzz_generated/app-common/clusters/WebRTCTransportRequestor/Metadata.h @@ -17,7 +17,7 @@ namespace app { namespace Clusters { namespace WebRTCTransportRequestor { -inline constexpr uint32_t kRevision = 1; +inline constexpr uint32_t kRevision = 2; namespace Attributes { diff --git a/zzz_generated/app-common/clusters/shared/Structs.h b/zzz_generated/app-common/clusters/shared/Structs.h index 0613881aeee..2ad1073e095 100644 --- a/zzz_generated/app-common/clusters/shared/Structs.h +++ b/zzz_generated/app-common/clusters/shared/Structs.h @@ -604,6 +604,8 @@ enum class Fields : uint8_t kVideoStreamID = 4, kAudioStreamID = 5, kMetadataEnabled = 6, + kVideoStreams = 7, + kAudioStreams = 8, kFabricIndex = 254, }; @@ -616,11 +618,11 @@ struct Type Globals::StreamUsageEnum streamUsage = static_cast(0); DataModel::Nullable videoStreamID; DataModel::Nullable audioStreamID; - bool metadataEnabled = static_cast(0); + bool metadataEnabled = static_cast(0); + Optional> videoStreams; + Optional> audioStreams; chip::FabricIndex fabricIndex = static_cast(0); - CHIP_ERROR Decode(TLV::TLVReader & reader); - static constexpr bool kIsFabricScoped = true; auto GetFabricIndex() const { return fabricIndex; } @@ -634,7 +636,28 @@ struct Type CHIP_ERROR DoEncode(TLV::TLVWriter & aWriter, TLV::Tag aTag, const Optional & aAccessingFabricIndex) const; }; -using DecodableType = Type; +struct DecodableType +{ +public: + uint16_t id = static_cast(0); + chip::NodeId peerNodeID = static_cast(0); + chip::EndpointId peerEndpointID = static_cast(0); + Globals::StreamUsageEnum streamUsage = static_cast(0); + DataModel::Nullable videoStreamID; + DataModel::Nullable audioStreamID; + bool metadataEnabled = static_cast(0); + Optional> videoStreams; + Optional> audioStreams; + chip::FabricIndex fabricIndex = static_cast(0); + + CHIP_ERROR Decode(TLV::TLVReader & reader); + + static constexpr bool kIsFabricScoped = true; + + auto GetFabricIndex() const { return fabricIndex; } + + void SetFabricIndex(chip::FabricIndex fabricIndex_) { fabricIndex = fabricIndex_; } +}; } // namespace WebRTCSessionStruct diff --git a/zzz_generated/app-common/clusters/shared/Structs.ipp b/zzz_generated/app-common/clusters/shared/Structs.ipp index c93586b31ce..cc166247bef 100644 --- a/zzz_generated/app-common/clusters/shared/Structs.ipp +++ b/zzz_generated/app-common/clusters/shared/Structs.ipp @@ -856,6 +856,8 @@ CHIP_ERROR Type::DoEncode(TLV::TLVWriter & aWriter, TLV::Tag aTag, const Optiona encoder.Encode(to_underlying(Fields::kVideoStreamID), videoStreamID); encoder.Encode(to_underlying(Fields::kAudioStreamID), audioStreamID); encoder.Encode(to_underlying(Fields::kMetadataEnabled), metadataEnabled); + encoder.Encode(to_underlying(Fields::kVideoStreams), videoStreams); + encoder.Encode(to_underlying(Fields::kAudioStreams), audioStreams); if (aAccessingFabricIndex.HasValue()) { encoder.Encode(to_underlying(Fields::kFabricIndex), fabricIndex); @@ -902,6 +904,14 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { err = DataModel::Decode(reader, metadataEnabled); } + else if (__context_tag == to_underlying(Fields::kVideoStreams)) + { + err = DataModel::Decode(reader, videoStreams); + } + else if (__context_tag == to_underlying(Fields::kAudioStreams)) + { + err = DataModel::Decode(reader, audioStreams); + } else if (__context_tag == to_underlying(Fields::kFabricIndex)) { err = DataModel::Decode(reader, fabricIndex); diff --git a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h index b45e5de8e02..a1a6f615eeb 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h @@ -15382,7 +15382,8 @@ class WebRTCTransportProviderSolicitOffer : public ClusterCommand public: WebRTCTransportProviderSolicitOffer(CredentialIssuerCommands * credsIssuerConfig) : ClusterCommand("solicit-offer", credsIssuerConfig), mComplex_ICEServers(&mRequest.ICEServers), - mComplex_SFrameConfig(&mRequest.SFrameConfig) + mComplex_SFrameConfig(&mRequest.SFrameConfig), mComplex_VideoStreams(&mRequest.videoStreams), + mComplex_AudioStreams(&mRequest.audioStreams) { AddArgument("StreamUsage", 0, UINT8_MAX, &mRequest.streamUsage); AddArgument("OriginatingEndpointID", 0, UINT16_MAX, &mRequest.originatingEndpointID); @@ -15392,6 +15393,8 @@ class WebRTCTransportProviderSolicitOffer : public ClusterCommand AddArgument("ICETransportPolicy", &mRequest.ICETransportPolicy); AddArgument("MetadataEnabled", 0, 1, &mRequest.metadataEnabled); AddArgument("SFrameConfig", &mComplex_SFrameConfig, "", Argument::kOptional); + AddArgument("VideoStreams", &mComplex_VideoStreams, "", Argument::kOptional); + AddArgument("AudioStreams", &mComplex_AudioStreams, "", Argument::kOptional); ClusterCommand::AddArguments(); } @@ -15423,6 +15426,8 @@ class WebRTCTransportProviderSolicitOffer : public ClusterCommand mComplex_ICEServers; TypedComplexArgument> mComplex_SFrameConfig; + TypedComplexArgument>> mComplex_VideoStreams; + TypedComplexArgument>> mComplex_AudioStreams; }; /* @@ -15433,7 +15438,8 @@ class WebRTCTransportProviderProvideOffer : public ClusterCommand public: WebRTCTransportProviderProvideOffer(CredentialIssuerCommands * credsIssuerConfig) : ClusterCommand("provide-offer", credsIssuerConfig), mComplex_ICEServers(&mRequest.ICEServers), - mComplex_SFrameConfig(&mRequest.SFrameConfig) + mComplex_SFrameConfig(&mRequest.SFrameConfig), mComplex_VideoStreams(&mRequest.videoStreams), + mComplex_AudioStreams(&mRequest.audioStreams) { AddArgument("WebRTCSessionID", 0, UINT16_MAX, &mRequest.webRTCSessionID); AddArgument("Sdp", &mRequest.sdp); @@ -15445,6 +15451,8 @@ class WebRTCTransportProviderProvideOffer : public ClusterCommand AddArgument("ICETransportPolicy", &mRequest.ICETransportPolicy); AddArgument("MetadataEnabled", 0, 1, &mRequest.metadataEnabled); AddArgument("SFrameConfig", &mComplex_SFrameConfig, "", Argument::kOptional); + AddArgument("VideoStreams", &mComplex_VideoStreams, "", Argument::kOptional); + AddArgument("AudioStreams", &mComplex_AudioStreams, "", Argument::kOptional); ClusterCommand::AddArguments(); } @@ -15476,6 +15484,8 @@ class WebRTCTransportProviderProvideOffer : public ClusterCommand mComplex_ICEServers; TypedComplexArgument> mComplex_SFrameConfig; + TypedComplexArgument>> mComplex_VideoStreams; + TypedComplexArgument>> mComplex_AudioStreams; }; /* @@ -16060,6 +16070,7 @@ class PushAvStreamTransportFindTransport : public ClusterCommand | * ClusterRevision | 0xFFFD | |------------------------------------------------------------------------------| | Events: | | +| * ChimeStartedPlaying | 0x0000 | \*----------------------------------------------------------------------------*/ /* @@ -16070,6 +16081,7 @@ class ChimePlayChimeSound : public ClusterCommand public: ChimePlayChimeSound(CredentialIssuerCommands * credsIssuerConfig) : ClusterCommand("play-chime-sound", credsIssuerConfig) { + AddArgument("ChimeID", 0, UINT8_MAX, &mRequest.chimeID); ClusterCommand::AddArguments(); } @@ -31124,8 +31136,10 @@ void registerClusterChime(Commands & commands, CredentialIssuerCommands * credsI // // Events // - make_unique(Id, credsIssuerConfig), // - make_unique(Id, credsIssuerConfig), // + make_unique(Id, credsIssuerConfig), // + make_unique(Id, "chime-started-playing", Events::ChimeStartedPlaying::Id, credsIssuerConfig), // + make_unique(Id, credsIssuerConfig), // + make_unique(Id, "chime-started-playing", Events::ChimeStartedPlaying::Id, credsIssuerConfig), // }; commands.RegisterCluster(clusterName, clusterCommands); diff --git a/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp b/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp index 056442e97c5..c1c0bdab0c3 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp +++ b/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp @@ -588,6 +588,20 @@ CHIP_ERROR ComplexArgumentParser::Setup(const char * label, ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.metadataEnabled, value["metadataEnabled"])); valueCopy.removeMember("metadataEnabled"); + if (value.isMember("videoStreams")) + { + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "videoStreams"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.videoStreams, value["videoStreams"])); + } + valueCopy.removeMember("videoStreams"); + + if (value.isMember("audioStreams")) + { + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "audioStreams"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.audioStreams, value["audioStreams"])); + } + valueCopy.removeMember("audioStreams"); + if (value.isMember("fabricIndex")) { snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "fabricIndex"); @@ -607,6 +621,8 @@ void ComplexArgumentParser::Finalize(chip::app::Clusters::Globals::Structs::WebR ComplexArgumentParser::Finalize(request.videoStreamID); ComplexArgumentParser::Finalize(request.audioStreamID); ComplexArgumentParser::Finalize(request.metadataEnabled); + ComplexArgumentParser::Finalize(request.videoStreams); + ComplexArgumentParser::Finalize(request.audioStreams); ComplexArgumentParser::Finalize(request.fabricIndex); } @@ -7462,6 +7478,70 @@ void ComplexArgumentParser::Finalize( ComplexArgumentParser::Finalize(request.sensitivity); } +CHIP_ERROR ComplexArgumentParser::Setup(const char * label, + chip::app::Clusters::PushAvStreamTransport::Structs::AudioStreamStruct::Type & request, + Json::Value & value) +{ + VerifyOrReturnError(value.isObject(), CHIP_ERROR_INVALID_ARGUMENT); + + // Copy to track which members we already processed. + Json::Value valueCopy(value); + + ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("AudioStreamStruct.audioStreamName", "audioStreamName", + value.isMember("audioStreamName"))); + ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("AudioStreamStruct.audioStreamID", "audioStreamID", + value.isMember("audioStreamID"))); + + char labelWithMember[kMaxLabelLength]; + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "audioStreamName"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.audioStreamName, value["audioStreamName"])); + valueCopy.removeMember("audioStreamName"); + + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "audioStreamID"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.audioStreamID, value["audioStreamID"])); + valueCopy.removeMember("audioStreamID"); + + return ComplexArgumentParser::EnsureNoMembersRemaining(label, valueCopy); +} + +void ComplexArgumentParser::Finalize(chip::app::Clusters::PushAvStreamTransport::Structs::AudioStreamStruct::Type & request) +{ + ComplexArgumentParser::Finalize(request.audioStreamName); + ComplexArgumentParser::Finalize(request.audioStreamID); +} + +CHIP_ERROR ComplexArgumentParser::Setup(const char * label, + chip::app::Clusters::PushAvStreamTransport::Structs::VideoStreamStruct::Type & request, + Json::Value & value) +{ + VerifyOrReturnError(value.isObject(), CHIP_ERROR_INVALID_ARGUMENT); + + // Copy to track which members we already processed. + Json::Value valueCopy(value); + + ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("VideoStreamStruct.videoStreamName", "videoStreamName", + value.isMember("videoStreamName"))); + ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("VideoStreamStruct.videoStreamID", "videoStreamID", + value.isMember("videoStreamID"))); + + char labelWithMember[kMaxLabelLength]; + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "videoStreamName"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.videoStreamName, value["videoStreamName"])); + valueCopy.removeMember("videoStreamName"); + + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "videoStreamID"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.videoStreamID, value["videoStreamID"])); + valueCopy.removeMember("videoStreamID"); + + return ComplexArgumentParser::EnsureNoMembersRemaining(label, valueCopy); +} + +void ComplexArgumentParser::Finalize(chip::app::Clusters::PushAvStreamTransport::Structs::VideoStreamStruct::Type & request) +{ + ComplexArgumentParser::Finalize(request.videoStreamName); + ComplexArgumentParser::Finalize(request.videoStreamID); +} + CHIP_ERROR ComplexArgumentParser::Setup(const char * label, chip::app::Clusters::PushAvStreamTransport::Structs::TransportTriggerOptionsStruct::Type & request, @@ -7701,6 +7781,20 @@ CHIP_ERROR ComplexArgumentParser::Setup(const char * label, } valueCopy.removeMember("expiryTime"); + if (value.isMember("videoStreams")) + { + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "videoStreams"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.videoStreams, value["videoStreams"])); + } + valueCopy.removeMember("videoStreams"); + + if (value.isMember("audioStreams")) + { + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "audioStreams"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.audioStreams, value["audioStreams"])); + } + valueCopy.removeMember("audioStreams"); + return ComplexArgumentParser::EnsureNoMembersRemaining(label, valueCopy); } @@ -7715,6 +7809,8 @@ void ComplexArgumentParser::Finalize(chip::app::Clusters::PushAvStreamTransport: ComplexArgumentParser::Finalize(request.ingestMethod); ComplexArgumentParser::Finalize(request.containerOptions); ComplexArgumentParser::Finalize(request.expiryTime); + ComplexArgumentParser::Finalize(request.videoStreams); + ComplexArgumentParser::Finalize(request.audioStreams); } CHIP_ERROR diff --git a/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.h b/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.h index 991b5d3331c..41e8d2cb6fb 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.h @@ -848,6 +848,16 @@ static CHIP_ERROR Setup(const char * label, static void Finalize(chip::app::Clusters::PushAvStreamTransport::Structs::TransportZoneOptionsStruct::Type & request); +static CHIP_ERROR Setup(const char * label, chip::app::Clusters::PushAvStreamTransport::Structs::AudioStreamStruct::Type & request, + Json::Value & value); + +static void Finalize(chip::app::Clusters::PushAvStreamTransport::Structs::AudioStreamStruct::Type & request); + +static CHIP_ERROR Setup(const char * label, chip::app::Clusters::PushAvStreamTransport::Structs::VideoStreamStruct::Type & request, + Json::Value & value); + +static void Finalize(chip::app::Clusters::PushAvStreamTransport::Structs::VideoStreamStruct::Type & request); + static CHIP_ERROR Setup(const char * label, chip::app::Clusters::PushAvStreamTransport::Structs::TransportTriggerOptionsStruct::Type & request, Json::Value & value); 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 4ea56ba482e..ff30d07b729 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp +++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp @@ -536,6 +536,22 @@ CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, return err; } } + { + CHIP_ERROR err = LogValue("VideoStreams", indent + 1, value.videoStreams); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'VideoStreams'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("AudioStreams", indent + 1, value.audioStreams); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'AudioStreams'"); + return err; + } + } { CHIP_ERROR err = LogValue("FabricIndex", indent + 1, value.fabricIndex); if (err != CHIP_NO_ERROR) @@ -6623,6 +6639,58 @@ CHIP_ERROR DataModelLogger::LogValue( return CHIP_NO_ERROR; } +CHIP_ERROR +DataModelLogger::LogValue(const char * label, size_t indent, + const chip::app::Clusters::PushAvStreamTransport::Structs::AudioStreamStruct::DecodableType & value) +{ + DataModelLogger::LogString(label, indent, "{"); + { + CHIP_ERROR err = LogValue("AudioStreamName", indent + 1, value.audioStreamName); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'AudioStreamName'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("AudioStreamID", indent + 1, value.audioStreamID); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'AudioStreamID'"); + return err; + } + } + DataModelLogger::LogString(indent, "}"); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR +DataModelLogger::LogValue(const char * label, size_t indent, + const chip::app::Clusters::PushAvStreamTransport::Structs::VideoStreamStruct::DecodableType & value) +{ + DataModelLogger::LogString(label, indent, "{"); + { + CHIP_ERROR err = LogValue("VideoStreamName", indent + 1, value.videoStreamName); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'VideoStreamName'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("VideoStreamID", indent + 1, value.videoStreamID); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'VideoStreamID'"); + return err; + } + } + DataModelLogger::LogString(indent, "}"); + + return CHIP_NO_ERROR; +} + CHIP_ERROR DataModelLogger::LogValue( const char * label, size_t indent, const chip::app::Clusters::PushAvStreamTransport::Structs::TransportTriggerOptionsStruct::DecodableType & value) @@ -6850,6 +6918,22 @@ DataModelLogger::LogValue(const char * label, size_t indent, return err; } } + { + CHIP_ERROR err = LogValue("VideoStreams", indent + 1, value.videoStreams); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'VideoStreams'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("AudioStreams", indent + 1, value.audioStreams); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'AudioStreams'"); + return err; + } + } DataModelLogger::LogString(indent, "}"); return CHIP_NO_ERROR; @@ -11321,6 +11405,22 @@ CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, return err; } } + { + CHIP_ERROR err = DataModelLogger::LogValue("ContainerType", indent + 1, value.containerType); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Event truncated due to invalid value for 'ContainerType'"); + return err; + } + } + { + CHIP_ERROR err = DataModelLogger::LogValue("CMAFSessionNumber", indent + 1, value.CMAFSessionNumber); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Event truncated due to invalid value for 'CMAFSessionNumber'"); + return err; + } + } DataModelLogger::LogString(indent, "}"); return CHIP_NO_ERROR; @@ -11337,6 +11437,38 @@ CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, return err; } } + { + CHIP_ERROR err = DataModelLogger::LogValue("ContainerType", indent + 1, value.containerType); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Event truncated due to invalid value for 'ContainerType'"); + return err; + } + } + { + CHIP_ERROR err = DataModelLogger::LogValue("CMAFSessionNumber", indent + 1, value.CMAFSessionNumber); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Event truncated due to invalid value for 'CMAFSessionNumber'"); + return err; + } + } + DataModelLogger::LogString(indent, "}"); + + return CHIP_NO_ERROR; +} +CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, + const Chime::Events::ChimeStartedPlaying::DecodableType & value) +{ + DataModelLogger::LogString(label, indent, "{"); + { + CHIP_ERROR err = DataModelLogger::LogValue("ChimeID", indent + 1, value.chimeID); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Event truncated due to invalid value for 'ChimeID'"); + return err; + } + } DataModelLogger::LogString(indent, "}"); return CHIP_NO_ERROR; @@ -24904,6 +25036,17 @@ CHIP_ERROR DataModelLogger::LogEvent(const chip::app::EventHeader & header, chip } break; } + case Chime::Id: { + switch (header.mPath.mEventId) + { + case Chime::Events::ChimeStartedPlaying::Id: { + chip::app::Clusters::Chime::Events::ChimeStartedPlaying::DecodableType value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("ChimeStartedPlaying", 1, value); + } + } + break; + } case CommissionerControl::Id: { switch (header.mPath.mEventId) { diff --git a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.h b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.h index e460fc9b228..099d3bf550e 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.h @@ -518,6 +518,12 @@ static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::PushAvStreamTransport::Structs::TransportZoneOptionsStruct::DecodableType & value); +static CHIP_ERROR LogValue(const char * label, size_t indent, + const chip::app::Clusters::PushAvStreamTransport::Structs::AudioStreamStruct::DecodableType & value); + +static CHIP_ERROR LogValue(const char * label, size_t indent, + const chip::app::Clusters::PushAvStreamTransport::Structs::VideoStreamStruct::DecodableType & value); + static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::PushAvStreamTransport::Structs::TransportTriggerOptionsStruct::DecodableType & value); @@ -950,6 +956,8 @@ static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::PushAvStreamTransport::Events::PushTransportBegin::DecodableType & value); static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::PushAvStreamTransport::Events::PushTransportEnd::DecodableType & value); +static CHIP_ERROR LogValue(const char * label, size_t indent, + const chip::app::Clusters::Chime::Events::ChimeStartedPlaying::DecodableType & value); static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::CommissionerControl::Events::CommissioningRequestResult::DecodableType & value); diff --git a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h index 959b5723f58..e661632bbe4 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h @@ -162823,6 +162823,8 @@ class WebRTCTransportProviderSolicitOffer : public ClusterCommand { : ClusterCommand("solicit-offer") , mComplex_ICEServers(&mRequest.ICEServers) , mComplex_SFrameConfig(&mRequest.SFrameConfig) + , mComplex_VideoStreams(&mRequest.videoStreams) + , mComplex_AudioStreams(&mRequest.audioStreams) { #if MTR_ENABLE_PROVISIONAL AddArgument("StreamUsage", 0, UINT8_MAX, &mRequest.streamUsage); @@ -162847,6 +162849,12 @@ class WebRTCTransportProviderSolicitOffer : public ClusterCommand { #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL AddArgument("SFrameConfig", &mComplex_SFrameConfig); +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + AddArgument("VideoStreams", &mComplex_VideoStreams); +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + AddArgument("AudioStreams", &mComplex_AudioStreams); #endif // MTR_ENABLE_PROVISIONAL ClusterCommand::AddArguments(); } @@ -162952,6 +162960,36 @@ class WebRTCTransportProviderSolicitOffer : public ClusterCommand { } else { params.sFrameConfig = nil; } +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + if (mRequest.videoStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_1 = [NSMutableArray new]; + for (auto & entry_1 : mRequest.videoStreams.Value()) { + NSNumber * newElement_1; + newElement_1 = [NSNumber numberWithUnsignedShort:entry_1]; + [array_1 addObject:newElement_1]; + } + params.videoStreams = array_1; + } + } else { + params.videoStreams = nil; + } +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + if (mRequest.audioStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_1 = [NSMutableArray new]; + for (auto & entry_1 : mRequest.audioStreams.Value()) { + NSNumber * newElement_1; + newElement_1 = [NSNumber numberWithUnsignedShort:entry_1]; + [array_1 addObject:newElement_1]; + } + params.audioStreams = array_1; + } + } else { + params.audioStreams = nil; + } #endif // MTR_ENABLE_PROVISIONAL uint16_t repeatCount = mRepeatCount.ValueOr(1); uint16_t __block responsesNeeded = repeatCount; @@ -162982,6 +163020,8 @@ class WebRTCTransportProviderSolicitOffer : public ClusterCommand { chip::app::Clusters::WebRTCTransportProvider::Commands::SolicitOffer::Type mRequest; TypedComplexArgument>> mComplex_ICEServers; TypedComplexArgument> mComplex_SFrameConfig; + TypedComplexArgument>> mComplex_VideoStreams; + TypedComplexArgument>> mComplex_AudioStreams; }; #endif // MTR_ENABLE_PROVISIONAL @@ -162995,6 +163035,8 @@ class WebRTCTransportProviderProvideOffer : public ClusterCommand { : ClusterCommand("provide-offer") , mComplex_ICEServers(&mRequest.ICEServers) , mComplex_SFrameConfig(&mRequest.SFrameConfig) + , mComplex_VideoStreams(&mRequest.videoStreams) + , mComplex_AudioStreams(&mRequest.audioStreams) { #if MTR_ENABLE_PROVISIONAL AddArgument("WebRTCSessionID", 0, UINT16_MAX, &mRequest.webRTCSessionID); @@ -163025,6 +163067,12 @@ class WebRTCTransportProviderProvideOffer : public ClusterCommand { #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL AddArgument("SFrameConfig", &mComplex_SFrameConfig); +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + AddArgument("VideoStreams", &mComplex_VideoStreams); +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + AddArgument("AudioStreams", &mComplex_AudioStreams); #endif // MTR_ENABLE_PROVISIONAL ClusterCommand::AddArguments(); } @@ -163140,6 +163188,36 @@ class WebRTCTransportProviderProvideOffer : public ClusterCommand { } else { params.sFrameConfig = nil; } +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + if (mRequest.videoStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_1 = [NSMutableArray new]; + for (auto & entry_1 : mRequest.videoStreams.Value()) { + NSNumber * newElement_1; + newElement_1 = [NSNumber numberWithUnsignedShort:entry_1]; + [array_1 addObject:newElement_1]; + } + params.videoStreams = array_1; + } + } else { + params.videoStreams = nil; + } +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + if (mRequest.audioStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_1 = [NSMutableArray new]; + for (auto & entry_1 : mRequest.audioStreams.Value()) { + NSNumber * newElement_1; + newElement_1 = [NSNumber numberWithUnsignedShort:entry_1]; + [array_1 addObject:newElement_1]; + } + params.audioStreams = array_1; + } + } else { + params.audioStreams = nil; + } #endif // MTR_ENABLE_PROVISIONAL uint16_t repeatCount = mRepeatCount.ValueOr(1); uint16_t __block responsesNeeded = repeatCount; @@ -163170,6 +163248,8 @@ class WebRTCTransportProviderProvideOffer : public ClusterCommand { chip::app::Clusters::WebRTCTransportProvider::Commands::ProvideOffer::Type mRequest; TypedComplexArgument>> mComplex_ICEServers; TypedComplexArgument> mComplex_SFrameConfig; + TypedComplexArgument>> mComplex_VideoStreams; + TypedComplexArgument>> mComplex_AudioStreams; }; #endif // MTR_ENABLE_PROVISIONAL @@ -164896,6 +164976,36 @@ class PushAvStreamTransportAllocatePushTransport : public ClusterCommand { } else { params.transportOptions.expiryTime = nil; } + if (mRequest.transportOptions.videoStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_2 = [NSMutableArray new]; + for (auto & entry_2 : mRequest.transportOptions.videoStreams.Value()) { + MTRPushAVStreamTransportClusterVideoStreamStruct * newElement_2; + newElement_2 = [MTRPushAVStreamTransportClusterVideoStreamStruct new]; + newElement_2.videoStreamName = [[NSString alloc] initWithBytes:entry_2.videoStreamName.data() length:entry_2.videoStreamName.size() encoding:NSUTF8StringEncoding]; + newElement_2.videoStreamID = [NSNumber numberWithUnsignedShort:entry_2.videoStreamID]; + [array_2 addObject:newElement_2]; + } + params.transportOptions.videoStreams = array_2; + } + } else { + params.transportOptions.videoStreams = nil; + } + if (mRequest.transportOptions.audioStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_2 = [NSMutableArray new]; + for (auto & entry_2 : mRequest.transportOptions.audioStreams.Value()) { + MTRPushAVStreamTransportClusterAudioStreamStruct * newElement_2; + newElement_2 = [MTRPushAVStreamTransportClusterAudioStreamStruct new]; + newElement_2.audioStreamName = [[NSString alloc] initWithBytes:entry_2.audioStreamName.data() length:entry_2.audioStreamName.size() encoding:NSUTF8StringEncoding]; + newElement_2.audioStreamID = [NSNumber numberWithUnsignedShort:entry_2.audioStreamID]; + [array_2 addObject:newElement_2]; + } + params.transportOptions.audioStreams = array_2; + } + } else { + params.transportOptions.audioStreams = nil; + } #endif // MTR_ENABLE_PROVISIONAL uint16_t repeatCount = mRepeatCount.ValueOr(1); uint16_t __block responsesNeeded = repeatCount; @@ -165122,6 +165232,36 @@ class PushAvStreamTransportModifyPushTransport : public ClusterCommand { } else { params.transportOptions.expiryTime = nil; } + if (mRequest.transportOptions.videoStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_2 = [NSMutableArray new]; + for (auto & entry_2 : mRequest.transportOptions.videoStreams.Value()) { + MTRPushAVStreamTransportClusterVideoStreamStruct * newElement_2; + newElement_2 = [MTRPushAVStreamTransportClusterVideoStreamStruct new]; + newElement_2.videoStreamName = [[NSString alloc] initWithBytes:entry_2.videoStreamName.data() length:entry_2.videoStreamName.size() encoding:NSUTF8StringEncoding]; + newElement_2.videoStreamID = [NSNumber numberWithUnsignedShort:entry_2.videoStreamID]; + [array_2 addObject:newElement_2]; + } + params.transportOptions.videoStreams = array_2; + } + } else { + params.transportOptions.videoStreams = nil; + } + if (mRequest.transportOptions.audioStreams.HasValue()) { + { // Scope for our temporary variables + auto * array_2 = [NSMutableArray new]; + for (auto & entry_2 : mRequest.transportOptions.audioStreams.Value()) { + MTRPushAVStreamTransportClusterAudioStreamStruct * newElement_2; + newElement_2 = [MTRPushAVStreamTransportClusterAudioStreamStruct new]; + newElement_2.audioStreamName = [[NSString alloc] initWithBytes:entry_2.audioStreamName.data() length:entry_2.audioStreamName.size() encoding:NSUTF8StringEncoding]; + newElement_2.audioStreamID = [NSNumber numberWithUnsignedShort:entry_2.audioStreamID]; + [array_2 addObject:newElement_2]; + } + params.transportOptions.audioStreams = array_2; + } + } else { + params.transportOptions.audioStreams = nil; + } #endif // MTR_ENABLE_PROVISIONAL uint16_t repeatCount = mRepeatCount.ValueOr(1); uint16_t __block responsesNeeded = repeatCount; @@ -165978,6 +166118,7 @@ class SubscribeAttributePushAvStreamTransportClusterRevision : public SubscribeA | * ClusterRevision | 0xFFFD | |------------------------------------------------------------------------------| | Events: | | +| * ChimeStartedPlaying | 0x0000 | \*----------------------------------------------------------------------------*/ #if MTR_ENABLE_PROVISIONAL @@ -165989,6 +166130,9 @@ class ChimePlayChimeSound : public ClusterCommand { ChimePlayChimeSound() : ClusterCommand("play-chime-sound") { +#if MTR_ENABLE_PROVISIONAL + AddArgument("ChimeID", 0, UINT8_MAX, &mRequest.chimeID); +#endif // MTR_ENABLE_PROVISIONAL ClusterCommand::AddArguments(); } @@ -166003,6 +166147,13 @@ class ChimePlayChimeSound : public ClusterCommand { __auto_type * cluster = [[MTRBaseClusterChime alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; __auto_type * params = [[MTRChimeClusterPlayChimeSoundParams alloc] init]; params.timedInvokeTimeoutMs = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; +#if MTR_ENABLE_PROVISIONAL + if (mRequest.chimeID.HasValue()) { + params.chimeID = [NSNumber numberWithUnsignedChar:mRequest.chimeID.Value()]; + } else { + params.chimeID = nil; + } +#endif // MTR_ENABLE_PROVISIONAL uint16_t repeatCount = mRepeatCount.ValueOr(1); uint16_t __block responsesNeeded = repeatCount; while (repeatCount--) { @@ -166023,6 +166174,7 @@ class ChimePlayChimeSound : public ClusterCommand { } private: + chip::app::Clusters::Chime::Commands::PlayChimeSound::Type mRequest; }; #endif // MTR_ENABLE_PROVISIONAL @@ -199362,6 +199514,8 @@ void registerClusterChime(Commands & commands) make_unique(), // make_unique(), // #endif // MTR_ENABLE_PROVISIONAL + make_unique(Id), // + make_unique(Id), // }; commands.RegisterCluster(clusterName, clusterCommands);