From 8c986c710a422267d99fbbb1cb1c7020a88625b4 Mon Sep 17 00:00:00 2001 From: dinabenamar <108664279+dinabenamar@users.noreply.github.com> Date: Fri, 20 Oct 2023 22:33:33 +0200 Subject: [PATCH] [NXP] Initial support for RW61x (#29126) * [NXP] Adding Matter support for RW61x platform * [NXP] Updating ot-nxp submodule to support RW61x * [RW61x] Fix misspell errors * [RW61x] Fix code-lints errors and updating zap generation : expose the EndpointList attribute in PowerSource cluster * [RW61x] Fix build-and-publish errors * [RW61x] Reworking all-clusters README.md to fix build-and-publish errors * [NXP] Fix application build : Adding device_layer_target_define for NXP device platform * [NXP] Addressing review comment : Removing unnecessary factory reset at ConfigurationManagerImpl init * [NXP] Updating zap files * [NXP] Fix all-clusters app build : update path of ErrorStr.h * [NXP] Run clang-format on RW61x/COMMON sources * Restyled by whitespace * Restyled by clang-format * Restyled by gn * Restyled by prettier-markdown --------- Co-authored-by: Restyled.io --- .gitmodules | 2 +- build_overrides/nxp_sdk.gni | 18 + docs/guides/nxp_rw61x_ota_software_update.md | 268 + .../nxp/common/main/AppAssert.cpp | 34 + .../common/main/AppFactoryDataDefaultImpl.cpp | 76 + .../nxp/common/main/AppMatterButtonEmpty.cpp | 26 + .../nxp/common/main/AppMatterCli.cpp | 137 + .../nxp/common/main/AppTask.cpp | 477 + .../nxp/common/main/CHIPDeviceManager.cpp | 63 + .../nxp/common/main/DeviceCallbacks.cpp | 177 + .../nxp/common/main/ZclCallbacks.cpp | 41 + .../nxp/common/main/include/AppEvent.h | 49 + .../nxp/common/main/include/AppFactoryData.h | 43 + .../nxp/common/main/include/AppMatterButton.h | 38 + .../nxp/common/main/include/AppMatterCli.h | 26 + .../nxp/common/main/include/AppTask.h | 65 + .../common/main/include/CHIPDeviceManager.h | 125 + .../nxp/common/main/include/DeviceCallbacks.h | 49 + .../all-clusters-app/nxp/common/main/main.cpp | 49 + examples/all-clusters-app/nxp/rt/rw61x/.gn | 33 + .../all-clusters-app/nxp/rt/rw61x/BUILD.gn | 191 + .../all-clusters-app/nxp/rt/rw61x/README.md | 294 + .../all-clusters-app/nxp/rt/rw61x/args.gni | 19 + .../nxp/rt/rw61x/build_overrides | 1 + .../rw61x/include/config/CHIPProjectConfig.h | 212 + .../nxp/rt/rw61x/third_party/connectedhomeip | 1 + examples/build_overrides/nxp_sdk.gni | 18 + .../nxp/common/OTARequestorInitiator.cpp | 71 + .../nxp/common/OTARequestorInitiator.h | 50 + .../platform/nxp/common/app/support/BUILD.gn | 49 + .../nxp/common/app/support/Memconfig.cpp | 210 + examples/platform/nxp/rt/rw61x/BUILD.gn | 25 + .../nxp/rt/rw61x/app/ldscripts/RW610_flash.ld | 584 + .../project_include/freeRTOS/FreeRTOSConfig.h | 185 + .../openthread/OpenThreadConfig.h | 84 + examples/platform/nxp/rt/rw61x/board/board.c | 395 + examples/platform/nxp/rt/rw61x/board/board.h | 173 + .../nxp/rt/rw61x/board/clock_config.c | 254 + .../nxp/rt/rw61x/board/clock_config.h | 65 + .../nxp/rt/rw61x/board/hardware_init.c | 33 + .../platform/nxp/rt/rw61x/board/peripherals.c | 149 + .../platform/nxp/rt/rw61x/board/peripherals.h | 102 + .../platform/nxp/rt/rw61x/board/pin_mux.c | 39 + .../platform/nxp/rt/rw61x/board/pin_mux.h | 51 + .../nxp/rt/rw61x/doc/images/mcu-set.PNG | Bin 0 -> 153442 bytes .../nxp/rt/rw61x/doc/images/mcuboot_demo.PNG | Bin 0 -> 84377 bytes .../doc/images/mcuboot_monolithic_app.PNG | Bin 0 -> 122627 bytes .../rt/rw61x/doc/images/mcux-sdk-download.PNG | Bin 0 -> 110232 bytes .../nxp/rt/rw61x/doc/images/toolchain.JPG | Bin 0 -> 129143 bytes examples/thermostat/nxp/zap/BUILD.gn | 34 + .../nxp/zap/thermostat_matter_thread.matter | 2116 ++ .../nxp/zap/thermostat_matter_thread.zap | 16543 ++++++++++++++++ .../nxp/zap/thermostat_matter_wifi.matter | 1972 ++ .../nxp/zap/thermostat_matter_wifi.zap | 16543 ++++++++++++++++ src/crypto/tests/BUILD.gn | 3 +- src/lib/shell/BUILD.gn | 5 + src/lib/shell/streamer_nxp.cpp | 243 + src/lwip/BUILD.gn | 23 +- src/platform/BUILD.gn | 11 + src/platform/device.gni | 12 +- src/platform/nxp/BUILD.gn | 21 + .../CHIPDeviceNXPPlatformDefaultConfig.h | 108 + .../nxp/common/CHIPDevicePlatformEvent.h | 124 + .../nxp/common/ConfigurationManagerImpl.cpp | 311 + .../nxp/common/ConfigurationManagerImpl.h | 92 + .../nxp/common/ConnectivityManagerImpl.cpp | 513 + .../nxp/common/ConnectivityManagerImpl.h | 188 + .../nxp/common/DiagnosticDataProviderImpl.cpp | 332 + .../nxp/common/DiagnosticDataProviderImpl.h | 91 + .../nxp/common/InetNXPPlatformDefaultConfig.h | 31 + .../nxp/common/KeyValueStoreManagerImpl.cpp | 96 + .../nxp/common/KeyValueStoreManagerImpl.h | 82 + src/platform/nxp/common/Logging.cpp | 97 + src/platform/nxp/common/NXPConfig.cpp | 614 + src/platform/nxp/common/NXPConfig.h | 201 + .../nxp/common/NetworkCommissioningDriver.h | 114 + .../common/NetworkCommissioningWiFiDriver.cpp | 447 + .../common/NetworkProvisioningServerImpl.cpp | 41 + .../common/NetworkProvisioningServerImpl.h | 80 + .../nxp/common/OTAImageProcessorImpl.cpp | 357 + .../nxp/common/OTAImageProcessorImpl.h | 84 + src/platform/nxp/common/PlatformManagerImpl.h | 108 + .../nxp/common/SoftwareUpdateManagerImpl.cpp | 46 + .../nxp/common/SoftwareUpdateManagerImpl.h | 89 + .../common/SystemNXPPlatformDefaultConfig.h | 87 + .../nxp/common/ThreadStackManagerImpl.cpp | 122 + .../nxp/common/ThreadStackManagerImpl.h | 111 + .../nxp/common/ble_zephyr/BLEManagerImpl.h | 31 + .../ble_zephyr/BleNXPPlatformDefaultConfig.h | 53 + .../factory_data/FactoryDataProvider.cpp | 357 + .../common/factory_data/FactoryDataProvider.h | 125 + .../FactoryDataProviderFwkImpl.cpp | 136 + .../factory_data/FactoryDataProviderFwkImpl.h | 65 + src/platform/nxp/common/ram_storage.c | 344 + src/platform/nxp/common/ram_storage.h | 71 + src/platform/nxp/rt/rw61x/BUILD.gn | 153 + src/platform/nxp/rt/rw61x/BlePlatformConfig.h | 37 + .../nxp/rt/rw61x/CHIPDevicePlatformConfig.h | 43 + .../nxp/rt/rw61x/CHIPPlatformConfig.h | 55 + .../nxp/rt/rw61x/InetPlatformConfig.h | 41 + .../nxp/rt/rw61x/PlatformManagerImpl.cpp | 346 + .../nxp/rt/rw61x/SystemPlatformConfig.h | 41 + src/platform/nxp/rt/rw61x/args.gni | 69 + src/system/BUILD.gn | 5 + third_party/nxp/BUILD.gn | 34 + third_party/nxp/nxp_sdk.gni | 55 + third_party/nxp/rt_sdk/BUILD.gn | 177 + third_party/nxp/rt_sdk/bt_ble/bt_ble.gni | 228 + .../nxp/rt_sdk/lwip/common/lwipopts_common.h | 595 + .../nxp/rt_sdk/lwip/common/lwippools.h | 30 + third_party/nxp/rt_sdk/lwip/lwip.gni | 252 + .../nxp/rt_sdk/lwip/openthread/lwipopts.h | 37 + third_party/nxp/rt_sdk/lwip/wifi/lwipopts.h | 31 + .../rt_sdk/lwip/wifi_openthread/lwipopts.h | 33 + .../config/matter_ksdk_mbedtls_config.h | 16 + third_party/nxp/rt_sdk/mbedtls/mbedtls.gni | 138 + third_party/nxp/rt_sdk/nxp_arm.gni | 34 + third_party/nxp/rt_sdk/nxp_executable.gni | 34 + third_party/nxp/rt_sdk/rt_executable.gni | 34 + third_party/nxp/rt_sdk/rt_sdk.gni | 648 + third_party/nxp/rt_sdk/rw61x/BUILD.gn | 53 + third_party/nxp/rt_sdk/rw61x/rw61x.gni | 686 + .../nxp/rt_sdk/sdk_hook/bt_pal/EM_platform.h | 22 + third_party/nxp/rt_sdk/sdk_hook/littlefs_pl.c | 16 + third_party/nxp/rt_sdk/sdk_hook/logging/log.h | 0 .../sdk_hook/mbedtls/ksdk_mbedtls_hook.c | 35 + .../sdk_hook/mbedtls/ksdk_mbedtls_software.c | 203 + .../rt_sdk/sdk_hook/zephyr/bluetooth/addr.h | 17 + .../sdk_hook/zephyr/bluetooth/bluetooth.h | 17 + .../rt_sdk/sdk_hook/zephyr/bluetooth/conn.h | 17 + .../rt_sdk/sdk_hook/zephyr/bluetooth/gatt.h | 17 + .../nxp/rt_sdk/sdk_hook/zephyr/kernel.c | 14 + .../nxp/rt_sdk/sdk_hook/zephyr/kernel.h | 19 + .../rt_sdk/sdk_hook/zephyr/random/rand32.cpp | 23 + .../rt_sdk/sdk_hook/zephyr/random/rand32.h | 29 + .../rt_sdk/sdk_hook/zephyr/sys/byteorder.h | 17 + .../nxp/rt_sdk/sdk_hook/zephyr/sys/slist.h | 16 + .../nxp/rt_sdk/sdk_hook/zephyr/sys/util.h | 17 + .../transceiver/app_transceiver_config.h | 37 + third_party/openthread/ot-nxp | 2 +- .../platforms/nxp/rt/rw61x/BUILD.gn | 96 + 141 files changed, 52833 insertions(+), 11 deletions(-) create mode 100644 build_overrides/nxp_sdk.gni create mode 100644 docs/guides/nxp_rw61x_ota_software_update.md create mode 100644 examples/all-clusters-app/nxp/common/main/AppAssert.cpp create mode 100644 examples/all-clusters-app/nxp/common/main/AppFactoryDataDefaultImpl.cpp create mode 100644 examples/all-clusters-app/nxp/common/main/AppMatterButtonEmpty.cpp create mode 100644 examples/all-clusters-app/nxp/common/main/AppMatterCli.cpp create mode 100644 examples/all-clusters-app/nxp/common/main/AppTask.cpp create mode 100644 examples/all-clusters-app/nxp/common/main/CHIPDeviceManager.cpp create mode 100644 examples/all-clusters-app/nxp/common/main/DeviceCallbacks.cpp create mode 100644 examples/all-clusters-app/nxp/common/main/ZclCallbacks.cpp create mode 100644 examples/all-clusters-app/nxp/common/main/include/AppEvent.h create mode 100644 examples/all-clusters-app/nxp/common/main/include/AppFactoryData.h create mode 100644 examples/all-clusters-app/nxp/common/main/include/AppMatterButton.h create mode 100644 examples/all-clusters-app/nxp/common/main/include/AppMatterCli.h create mode 100644 examples/all-clusters-app/nxp/common/main/include/AppTask.h create mode 100644 examples/all-clusters-app/nxp/common/main/include/CHIPDeviceManager.h create mode 100644 examples/all-clusters-app/nxp/common/main/include/DeviceCallbacks.h create mode 100644 examples/all-clusters-app/nxp/common/main/main.cpp create mode 100644 examples/all-clusters-app/nxp/rt/rw61x/.gn create mode 100644 examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn create mode 100644 examples/all-clusters-app/nxp/rt/rw61x/README.md create mode 100644 examples/all-clusters-app/nxp/rt/rw61x/args.gni create mode 120000 examples/all-clusters-app/nxp/rt/rw61x/build_overrides create mode 100644 examples/all-clusters-app/nxp/rt/rw61x/include/config/CHIPProjectConfig.h create mode 120000 examples/all-clusters-app/nxp/rt/rw61x/third_party/connectedhomeip create mode 100644 examples/build_overrides/nxp_sdk.gni create mode 100644 examples/platform/nxp/common/OTARequestorInitiator.cpp create mode 100644 examples/platform/nxp/common/OTARequestorInitiator.h create mode 100644 examples/platform/nxp/common/app/support/BUILD.gn create mode 100644 examples/platform/nxp/common/app/support/Memconfig.cpp create mode 100644 examples/platform/nxp/rt/rw61x/BUILD.gn create mode 100644 examples/platform/nxp/rt/rw61x/app/ldscripts/RW610_flash.ld create mode 100644 examples/platform/nxp/rt/rw61x/app/project_include/freeRTOS/FreeRTOSConfig.h create mode 100644 examples/platform/nxp/rt/rw61x/app/project_include/openthread/OpenThreadConfig.h create mode 100644 examples/platform/nxp/rt/rw61x/board/board.c create mode 100644 examples/platform/nxp/rt/rw61x/board/board.h create mode 100644 examples/platform/nxp/rt/rw61x/board/clock_config.c create mode 100644 examples/platform/nxp/rt/rw61x/board/clock_config.h create mode 100644 examples/platform/nxp/rt/rw61x/board/hardware_init.c create mode 100644 examples/platform/nxp/rt/rw61x/board/peripherals.c create mode 100644 examples/platform/nxp/rt/rw61x/board/peripherals.h create mode 100644 examples/platform/nxp/rt/rw61x/board/pin_mux.c create mode 100644 examples/platform/nxp/rt/rw61x/board/pin_mux.h create mode 100644 examples/platform/nxp/rt/rw61x/doc/images/mcu-set.PNG create mode 100644 examples/platform/nxp/rt/rw61x/doc/images/mcuboot_demo.PNG create mode 100644 examples/platform/nxp/rt/rw61x/doc/images/mcuboot_monolithic_app.PNG create mode 100644 examples/platform/nxp/rt/rw61x/doc/images/mcux-sdk-download.PNG create mode 100644 examples/platform/nxp/rt/rw61x/doc/images/toolchain.JPG create mode 100644 examples/thermostat/nxp/zap/BUILD.gn create mode 100644 examples/thermostat/nxp/zap/thermostat_matter_thread.matter create mode 100644 examples/thermostat/nxp/zap/thermostat_matter_thread.zap create mode 100644 examples/thermostat/nxp/zap/thermostat_matter_wifi.matter create mode 100644 examples/thermostat/nxp/zap/thermostat_matter_wifi.zap create mode 100644 src/lib/shell/streamer_nxp.cpp create mode 100644 src/platform/nxp/BUILD.gn create mode 100644 src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h create mode 100644 src/platform/nxp/common/CHIPDevicePlatformEvent.h create mode 100644 src/platform/nxp/common/ConfigurationManagerImpl.cpp create mode 100644 src/platform/nxp/common/ConfigurationManagerImpl.h create mode 100644 src/platform/nxp/common/ConnectivityManagerImpl.cpp create mode 100644 src/platform/nxp/common/ConnectivityManagerImpl.h create mode 100644 src/platform/nxp/common/DiagnosticDataProviderImpl.cpp create mode 100644 src/platform/nxp/common/DiagnosticDataProviderImpl.h create mode 100644 src/platform/nxp/common/InetNXPPlatformDefaultConfig.h create mode 100644 src/platform/nxp/common/KeyValueStoreManagerImpl.cpp create mode 100644 src/platform/nxp/common/KeyValueStoreManagerImpl.h create mode 100644 src/platform/nxp/common/Logging.cpp create mode 100644 src/platform/nxp/common/NXPConfig.cpp create mode 100644 src/platform/nxp/common/NXPConfig.h create mode 100644 src/platform/nxp/common/NetworkCommissioningDriver.h create mode 100644 src/platform/nxp/common/NetworkCommissioningWiFiDriver.cpp create mode 100644 src/platform/nxp/common/NetworkProvisioningServerImpl.cpp create mode 100644 src/platform/nxp/common/NetworkProvisioningServerImpl.h create mode 100644 src/platform/nxp/common/OTAImageProcessorImpl.cpp create mode 100644 src/platform/nxp/common/OTAImageProcessorImpl.h create mode 100644 src/platform/nxp/common/PlatformManagerImpl.h create mode 100644 src/platform/nxp/common/SoftwareUpdateManagerImpl.cpp create mode 100644 src/platform/nxp/common/SoftwareUpdateManagerImpl.h create mode 100644 src/platform/nxp/common/SystemNXPPlatformDefaultConfig.h create mode 100644 src/platform/nxp/common/ThreadStackManagerImpl.cpp create mode 100644 src/platform/nxp/common/ThreadStackManagerImpl.h create mode 100644 src/platform/nxp/common/ble_zephyr/BLEManagerImpl.h create mode 100644 src/platform/nxp/common/ble_zephyr/BleNXPPlatformDefaultConfig.h create mode 100644 src/platform/nxp/common/factory_data/FactoryDataProvider.cpp create mode 100644 src/platform/nxp/common/factory_data/FactoryDataProvider.h create mode 100644 src/platform/nxp/common/factory_data/FactoryDataProviderFwkImpl.cpp create mode 100644 src/platform/nxp/common/factory_data/FactoryDataProviderFwkImpl.h create mode 100644 src/platform/nxp/common/ram_storage.c create mode 100644 src/platform/nxp/common/ram_storage.h create mode 100644 src/platform/nxp/rt/rw61x/BUILD.gn create mode 100644 src/platform/nxp/rt/rw61x/BlePlatformConfig.h create mode 100644 src/platform/nxp/rt/rw61x/CHIPDevicePlatformConfig.h create mode 100644 src/platform/nxp/rt/rw61x/CHIPPlatformConfig.h create mode 100644 src/platform/nxp/rt/rw61x/InetPlatformConfig.h create mode 100644 src/platform/nxp/rt/rw61x/PlatformManagerImpl.cpp create mode 100644 src/platform/nxp/rt/rw61x/SystemPlatformConfig.h create mode 100644 src/platform/nxp/rt/rw61x/args.gni create mode 100644 third_party/nxp/BUILD.gn create mode 100644 third_party/nxp/nxp_sdk.gni create mode 100644 third_party/nxp/rt_sdk/BUILD.gn create mode 100644 third_party/nxp/rt_sdk/bt_ble/bt_ble.gni create mode 100644 third_party/nxp/rt_sdk/lwip/common/lwipopts_common.h create mode 100644 third_party/nxp/rt_sdk/lwip/common/lwippools.h create mode 100644 third_party/nxp/rt_sdk/lwip/lwip.gni create mode 100644 third_party/nxp/rt_sdk/lwip/openthread/lwipopts.h create mode 100644 third_party/nxp/rt_sdk/lwip/wifi/lwipopts.h create mode 100644 third_party/nxp/rt_sdk/lwip/wifi_openthread/lwipopts.h create mode 100644 third_party/nxp/rt_sdk/mbedtls/config/matter_ksdk_mbedtls_config.h create mode 100644 third_party/nxp/rt_sdk/mbedtls/mbedtls.gni create mode 100644 third_party/nxp/rt_sdk/nxp_arm.gni create mode 100644 third_party/nxp/rt_sdk/nxp_executable.gni create mode 100644 third_party/nxp/rt_sdk/rt_executable.gni create mode 100644 third_party/nxp/rt_sdk/rt_sdk.gni create mode 100644 third_party/nxp/rt_sdk/rw61x/BUILD.gn create mode 100644 third_party/nxp/rt_sdk/rw61x/rw61x.gni create mode 100644 third_party/nxp/rt_sdk/sdk_hook/bt_pal/EM_platform.h create mode 100644 third_party/nxp/rt_sdk/sdk_hook/littlefs_pl.c create mode 100644 third_party/nxp/rt_sdk/sdk_hook/logging/log.h create mode 100644 third_party/nxp/rt_sdk/sdk_hook/mbedtls/ksdk_mbedtls_hook.c create mode 100644 third_party/nxp/rt_sdk/sdk_hook/mbedtls/ksdk_mbedtls_software.c create mode 100644 third_party/nxp/rt_sdk/sdk_hook/zephyr/bluetooth/addr.h create mode 100644 third_party/nxp/rt_sdk/sdk_hook/zephyr/bluetooth/bluetooth.h create mode 100644 third_party/nxp/rt_sdk/sdk_hook/zephyr/bluetooth/conn.h create mode 100644 third_party/nxp/rt_sdk/sdk_hook/zephyr/bluetooth/gatt.h create mode 100644 third_party/nxp/rt_sdk/sdk_hook/zephyr/kernel.c create mode 100644 third_party/nxp/rt_sdk/sdk_hook/zephyr/kernel.h create mode 100644 third_party/nxp/rt_sdk/sdk_hook/zephyr/random/rand32.cpp create mode 100644 third_party/nxp/rt_sdk/sdk_hook/zephyr/random/rand32.h create mode 100644 third_party/nxp/rt_sdk/sdk_hook/zephyr/sys/byteorder.h create mode 100644 third_party/nxp/rt_sdk/sdk_hook/zephyr/sys/slist.h create mode 100644 third_party/nxp/rt_sdk/sdk_hook/zephyr/sys/util.h create mode 100644 third_party/nxp/rt_sdk/transceiver/app_transceiver_config.h create mode 100644 third_party/openthread/platforms/nxp/rt/rw61x/BUILD.gn diff --git a/.gitmodules b/.gitmodules index 28bdba881cb8b2..6683ee97ecb02e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -62,7 +62,7 @@ platforms = k32w [submodule "third_party/openthread/ot-nxp"] path = third_party/openthread/ot-nxp - url = https://github.com/openthread/ot-nxp.git + url = https://github.com/NXP/ot-nxp.git platforms = k32w [submodule "third_party/openthread/ot-qorvo"] path = third_party/openthread/ot-qorvo diff --git a/build_overrides/nxp_sdk.gni b/build_overrides/nxp_sdk.gni new file mode 100644 index 00000000000000..0fb6234c7d5aaf --- /dev/null +++ b/build_overrides/nxp_sdk.gni @@ -0,0 +1,18 @@ +# 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. + +declare_args() { + # Root directory for NXP SDKs. + nxp_sdk_build_root = "//third_party/nxp" +} diff --git a/docs/guides/nxp_rw61x_ota_software_update.md b/docs/guides/nxp_rw61x_ota_software_update.md new file mode 100644 index 00000000000000..c3bd5227a054ed --- /dev/null +++ b/docs/guides/nxp_rw61x_ota_software_update.md @@ -0,0 +1,268 @@ +# Matter Over-The-Air Software Update with NXP RW61x example applications + +## Overview + +The OTA Requestor feature enables the device to be informed of, download and +apply a software update from an OTA Provider. + +This section explains how to perform an OTA Software Update with NXP RW61x +example applications. Throughout this guide, the all-clusters application is +used as an example. + +In general, the Over-The-Air Software Update process consists of the following +steps : + +- The OTA Requestor queries an update image from the OTA Provider which + responds according to its availability. +- The update image is received in blocks and stored in the external flash of + the device. +- Once the update image is fully downloaded, the bootloader is notified and + the device resets applying the update in test-mode. +- If the test is successful, the update is applied permanently. Otherwise, the + bootloader reverts back to the primary application, preventing any + downgrade. + +### Flash Memory Layout + +The RW61x Flash is divided into different regions as follow : + +- Bootloader : MCUBoot resides at the base of the flash and occupies 0x20000 + (128 kB). +- Primary application partition : The example application which would be run + by the bootloader (active application). The size reserved for this partition + is 4.4 MB. +- Secondary application partition : Update image received with the OTA + (candidate application). The size reserved for the partition is 4.4 MB. + +Notes : + +- The CPU1/CPU2 firmware are embedded in the CPU3 example application. +- The sizes of the primary and secondary applications are provided as an + example (currently 4.4 MB is reserved for each partition). The size can be + changed by modifying the `m_app_max_sectors` value in the linker script of + the application (`RW610_flash.ld`). + +### MCUBoot Bootloader + +MCUBoot is an open-source secure bootloader used by RW61x to apply the +self-upgrade. For more details, please refer to the +[MCUBoot documentation](https://github.com/mcu-tools/mcuboot/blob/main/docs/design.md). + +In our use case, the bootloader runs the application residing in the primary +partition. In order to run the OTA update image, the bootloader will swap the +content of the primary and the secondary partitions. This type of upgrade is +called swap-move and is the default upgrade configured by MCUBoot. + +## OTA Software Update process for RW61x example application + +### Flashing the bootloader + +In order for the device to perform the software update, the MCUBoot bootloader +must be flashed first at the base of the flash. A step-by-step guide is given +below. + +- It is recommended to start with erasing the external flash of the device, + for this JLink from Segger can be used. It can be downloaded and installed + from https://www.segger.com/products/debug-probes/j-link. Once installed, + JLink can be run using the command line : + +``` +$ JLink +``` + +Run the following commands : + +``` +J-Link > connect +Device> ? # you will be presented with a dialog -> select `RW612` +Please specify target interface: +J) JTAG (Default) +S) SWD +T) cJTAG +TIF> S +Specify target interface speed [kHz]. : 4000 kHz +Speed> # +J-Link > exec EnableEraseAllFlashBanks +J-Link > erase 0x8000000, 0x88a0000 +``` + +- Using MCUXPresso, import the `mcuboot_opensource` demo example from the SDK + previously downloaded. + ![mcuboot_demo](../../examples/platform/nxp/rt/rw61x/doc/images/mcuboot_demo.PNG) +- Before building the demo example, it should be specified that the + application to be run by the bootloader is monolithic. As a result, only one + image will be upgraded by the bootloader. This can be done by defining + `MONOLITHIC_APP` as 1 in the settings of the `mcuboot_opensource` project : + +``` +Right click on the Project -> Properties -> C/C++ Build -> Settings -> Tool Settings -> MCU C Compiler -> Preprocessor -> Add "MONOLITHIC_APP=1" in the Defined Symbols +``` + +![rw610_mcuboot_monolithic](../../examples/platform/nxp/rt/rw61x/doc/images/mcuboot_monolithic_app.PNG) + +- Build the demo example project and program it to the target board. +- To run the flashed demo, either press the reset button of the device or use + the debugger IDE of MCUXpresso. If it runs successfully, the following logs + will be displayed on the terminal : + +``` +hello sbl. +Bootloader Version 1.9.0 +Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 +Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3 +Boot source: none +Swap type: none +erasing trailer; fa_id=2 +Unable to find bootable image +``` + +Note : By default, mcuboot application considers the primary and secondary +partitions to be the size of 4.4 MB. If the size is to be changed, the partition +addresses should be modified in the flash_partitioning.h accordingly. For more +information about the flash partitioning with mcuboot, please refer to the +dedicated readme.txt located in +"`SDK_RW612/boards/rdrw612bga/ota_examples/mcuboot_opensource/`". + +### Generating and flashing the signed application image + +After flashing the bootloader, the application can be programmed to the board. +The image must have the following format : + +- Header : contains general information about the image (version, size, + magic...) +- Code of the application : generated binary +- Trailer : contains metadata needed by the bootloader such as the image + signature, the upgrade type, the swap status... + +The all-clusters application can be generated using the instructions from the +[README.md 'Building'](../../examples/all-clusters-app/nxp/rt/rw61x/README.md#building) +section. The application is automatically linked to be executed from the primary +image partition, taking into consideration the offset imposed by mcuboot. + +The resulting executable file found in out/debug/chip-rw61x-all-cluster-example +needs to be converted into raw binary format as shown below. + +``` +arm-none-eabi-objcopy -R .flash_config -R .NVM -O binary chip-rw61x-all-cluster-example chip-rw61x-all-cluster-example.bin +``` + +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 +"`/middleware/mcuboot_opensource/scripts/`". + +The following commands can be run (make sure to replace the /path/to/file/binary +with the adequate files): + +``` +user@ubuntu: cd ~/Desktop/SDK_RW612/middleware/mcuboot_opensource/scripts + +user@ubuntu: python3 imgtool.py sign --key ~/Desktop/SDK_RW612/boards/rdrw612bga/ota_examples/mcuboot_opensource/keys/sign-rsa2048-priv.pem --align 4 --header-size 0x1000 --pad-header --slot-size 0x440000 --max-sectors 1088 --version "1.0" ~/Desktop/connectedhomeip/examples/all-clusters-app/nxp/rt/rw61x/out/debug/chip-rw61x-all-cluster-example.bin ~/Desktop/connectedhomeip/examples/all-clusters-app/nxp/rt/rw61x/out/debug/chip-rw61x-all-cluster-example_SIGNED.bin +``` + +Notes : + +- If internal SDK is used instead, the key can be found in : + "`~/Desktop/SDK_RW612/middleware/mcuboot_opensource/boot/nxp_mcux_sdk/keys/sign-rsa2048-priv.pem`". +- The arguments `slot-size` and `max-sectors` should be adjusted to the size + of the partitions reserved for the primary and the secondary applications. + (By default the size considered is 4.4 MB) +- In this example, the image is signed with the private key provided by the + SDK as an example + (`/path_to_sdk/middleware/mcuboot_opensource/boot/nxp_mcux_sdk/keys/sign-rsa2048-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 : + +``` +user@ubuntu: python3 imgtool.py keygen -k priv_key.pem -t rsa-2048 +``` + +- To extract the public key : + +``` +user@ubuntu: python3 imgtool.py getpub -k priv_key.pem +``` + +- The extracted public key can then be copied to the + `/path_to_sdk/middleware/mcuboot_opensource/boot/nxp_mcux_sdk/keys/sign-rsa2048-pub.c`, + given as a value to the rsa_pub_key[] array. + +The resulting output is the signed binary of the application version "1.0". + +JLink can be used to flash the application at the address 0x8020000, using the +command : + +``` +J-Link > loadbin chip-rw61x-all-cluster-example_SIGNED.bin 0x8020000 +``` + +The bootloader should then be able to jump directly to the start of the +application and run it. + +### Generating the OTA Update Image + +To generate the OTA update image the same procedure can be followed from the +[Generating and flashing the signed application image](#generating-and-flashing-the-signed-application-image) +sub-section, replacing the "--version "1.0"" argument with "--version "2.0"" +(recent version of the update). + +When the signed binary of the update is generated, the file should be converted +into OTA format. To do so, the ota_image_tool is provided in the repo and can be +used to convert a binary file into an .ota file. + +``` +user@ubuntu:~/connectedhomeip$ : ./src/app/ota_image_tool.py create -v 0xDEAD -p 0xBEEF -vn 2 -vs "2.0" -da sha256 chip-rw61x-all-cluster-example_SIGNED.bin chip-rw61x-all-cluster-example.ota +``` + +The generated OTA file can be used to perform the OTA Software Update. The +instructions below describe the procedure step-by-step. + +### Performing the OTA Software Update + +Setup example : + +- [Chip-tool](../../examples/chip-tool/README.md) application running on the + RPi. +- OTA Provider application built on the same RPi (as explained below). +- RW61x board programmed with the example application (with the instructions + above). + +Before starting the OTA process, the Linux OTA Provider application can be built +on the RPi (if not already present in the pre-installed apps) : + +``` +user@ubuntu:~/connectedhomeip$ : ./scripts/examples/gn_build_example.sh examples/ota-provider-app/linux out/ota-provider-app chip_config_network_layer_ble=false + +user@ubuntu:~/connectedhomeip$ : rm -rf /tmp/chip_* +user@ubuntu:~/connectedhomeip$ : ./out/ota-provider-app/chip-ota-provider-app -f chip-rw61x-all-cluster-example.ota +``` + +The OTA Provider should first be provisioned with chip-tool by assigning it the +node id 1, and then granted the ACL entries : + +``` +user@ubuntu:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool pairing onnetwork 1 20202021 +user@ubuntu:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}, {"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": null, "targets": null}]' 1 0 +``` + +The second step is to provision the device with the node id 2 using ble-wifi or +ble-thread commissioning. For example : + +``` +user@ubuntu:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool pairing ble-wifi 2 WIFI_SSID WIFI_PASSWORD 20202021 3840 +``` + +Once commissioned, the OTA process can be initiated with the +"announce-ota-provider" command using chip-tool (the given numbers refer +respectively to [ProviderNodeId][vendorid] [AnnouncementReason][endpoint] +[node-id][endpoint-id]) : + +``` +user@ubuntu:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool otasoftwareupdaterequestor announce-otaprovider 1 0 0 0 2 0 +``` + +When the full update image is downloaded and stored, the bootloader will be +notified and the device will reboot with the update image. diff --git a/examples/all-clusters-app/nxp/common/main/AppAssert.cpp b/examples/all-clusters-app/nxp/common/main/AppAssert.cpp new file mode 100644 index 00000000000000..81e028ceadd2f3 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/AppAssert.cpp @@ -0,0 +1,34 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * 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. + */ + +#include "fsl_debug_console.h" +#include + +/* + * Assert function implemented in the application layer. + * This implementation would produce a reset. + * But it could be extended with specific application contrains/requirements. + */ +void __assert_func(const char * file, int line, const char * func, const char * failedExpr) +{ + PRINTF("ASSERT ERROR \" %s \": file \"%s\" Line \"%d\" function name \"%s\" \n", failedExpr, file, line, func); + chip::DeviceLayer::PlatformMgrImpl().Reset(); + while (1) + ; +} diff --git a/examples/all-clusters-app/nxp/common/main/AppFactoryDataDefaultImpl.cpp b/examples/all-clusters-app/nxp/common/main/AppFactoryDataDefaultImpl.cpp new file mode 100644 index 00000000000000..0c28e5029eac99 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/AppFactoryDataDefaultImpl.cpp @@ -0,0 +1,76 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * 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. + */ + +#include "AppFactoryData.h" + +#include +#include +#include + +#if CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA +#include "FactoryDataProvider.h" +/* + * Test key used to encrypt factory data before storing it to the flash. + */ +static const uint8_t aes128TestKey[] + __attribute__((aligned)) = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; +#else +#include +#endif + +using namespace chip; +using namespace ::chip::Credentials; +using namespace ::chip::DeviceLayer; + +/** + * Allows to register Matter factory data before initializing the Matter stack + * Empty content here nothing particular to do. + */ +CHIP_ERROR AppFactoryData_PreMatterStackInit(void) +{ + return CHIP_NO_ERROR; +} + +/** + * Allows to register Matter factory data before initializing the Matter stack + * Load factory data. + * + * In this example we assume that the matter factory dataset is encrypted. + * This example demonstrates the usage of AES ecb with a software key. + */ +CHIP_ERROR AppFactoryData_PostMatterStackInit(void) +{ + CHIP_ERROR err = CHIP_NO_ERROR; +#if CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA + FactoryDataPrvdImpl().SetEncryptionMode(FactoryDataProvider::encrypt_ecb); + FactoryDataPrvdImpl().SetAes128Key(&aes128TestKey[0]); + + err = FactoryDataPrvdImpl().Init(); + if (err == CHIP_NO_ERROR) + { + SetDeviceInstanceInfoProvider(&FactoryDataPrvd()); + SetDeviceAttestationCredentialsProvider(&FactoryDataPrvd()); + SetCommissionableDataProvider(&FactoryDataPrvd()); + } +#else + // Initialize device attestation with example one (only for debug purpose) + SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); +#endif + return err; +} diff --git a/examples/all-clusters-app/nxp/common/main/AppMatterButtonEmpty.cpp b/examples/all-clusters-app/nxp/common/main/AppMatterButtonEmpty.cpp new file mode 100644 index 00000000000000..dfd3eca9eeb105 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/AppMatterButtonEmpty.cpp @@ -0,0 +1,26 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * 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. + */ + +#include "AppMatterButton.h" + +CHIP_ERROR AppMatterButton_registerButtons(void) +{ + /* Empty content could be re-defined in a dedicated platform AppMatterButton_registerButtons function */ + return CHIP_NO_ERROR; +} diff --git a/examples/all-clusters-app/nxp/common/main/AppMatterCli.cpp b/examples/all-clusters-app/nxp/common/main/AppMatterCli.cpp new file mode 100644 index 00000000000000..663bc85920ddb4 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/AppMatterCli.cpp @@ -0,0 +1,137 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * 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. + */ + +#include "AppMatterCli.h" +#include "AppTask.h" +#include +#include +#include + +#ifdef ENABLE_CHIP_SHELL +#include "task.h" +#include +#include + +#define MATTER_CLI_TASK_SIZE ((configSTACK_DEPTH_TYPE) 2048 / sizeof(portSTACK_TYPE)) +#define MATTER_CLI_LOG(message) (streamer_printf(streamer_get(), message)) + +using namespace chip::Shell; +TaskHandle_t AppMatterCliTaskHandle; +static bool isShellInitialized = false; +#else +#define MATTER_CLI_LOG(...) +#endif /* ENABLE_CHIP_SHELL */ + +void AppMatterCliTask(void * args) +{ +#ifdef ENABLE_CHIP_SHELL + Engine::Root().RunMainLoop(); +#endif /* ENABLE_CHIP_SHELL */ +} + +/* Application Matter CLI commands */ + +CHIP_ERROR commissioningManager(int argc, char * argv[]) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + if (strncmp(argv[0], "on", 2) == 0) + { + GetAppTask().StartCommissioningHandler(); + } + else if (strncmp(argv[0], "off", 3) == 0) + { + GetAppTask().StopCommissioningHandler(); + } + else + { + MATTER_CLI_LOG("wrong args should be either \"mattercommissioning on\" or \"mattercommissioning off\""); + error = CHIP_ERROR_INVALID_ARGUMENT; + } + return error; +} + +CHIP_ERROR cliFactoryReset(int argc, char * argv[]) +{ + GetAppTask().FactoryResetHandler(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR cliReset(int argc, char * argv[]) +{ + /* + Shutdown device before reboot, + this emits the ShutDown event, handles the server shutting down, + and stores in flash the total-operational-hours value. + */ + chip::DeviceLayer::PlatformMgr().Shutdown(); + chip::DeviceLayer::PlatformMgrImpl().ScheduleResetInIdle(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR AppMatterCli_RegisterCommands(void) +{ +#ifdef ENABLE_CHIP_SHELL + if (!isShellInitialized) + { + int error = Engine::Root().Init(); + if (error != 0) + { + ChipLogError(Shell, "Streamer initialization failed: %d", error); + return CHIP_ERROR_INTERNAL; + } + + /* Register common shell commands */ + cmd_misc_init(); + cmd_otcli_init(); +#if CHIP_SHELL_ENABLE_CMD_SERVER + cmd_app_server_init(); +#endif /* CHIP_SHELL_ENABLE_CMD_SERVER */ + + /* Register application commands */ + static const shell_command_t kCommands[] = { + { + .cmd_func = commissioningManager, + .cmd_name = "mattercommissioning", + .cmd_help = "Open/close the commissioning window. Usage : mattercommissioning [on|off]", + }, + { + .cmd_func = cliFactoryReset, + .cmd_name = "matterfactoryreset", + .cmd_help = "Perform a factory reset on the device", + }, + { + .cmd_func = cliReset, + .cmd_name = "matterreset", + .cmd_help = "Reset the device", + }, + }; + + Engine::Root().RegisterCommands(kCommands, sizeof(kCommands) / sizeof(kCommands[0])); + + if (xTaskCreate(&AppMatterCliTask, "AppMatterCli_task", MATTER_CLI_TASK_SIZE, NULL, 1, &AppMatterCliTaskHandle) != pdPASS) + { + ChipLogError(Shell, "Failed to start Matter CLI task"); + return CHIP_ERROR_INTERNAL; + } + isShellInitialized = true; + } +#endif /* ENABLE_CHIP_SHELL */ + + return CHIP_NO_ERROR; +} diff --git a/examples/all-clusters-app/nxp/common/main/AppTask.cpp b/examples/all-clusters-app/nxp/common/main/AppTask.cpp new file mode 100644 index 00000000000000..3ca3af76b96349 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/AppTask.cpp @@ -0,0 +1,477 @@ +/* + * + * Copyright (c) 2021-2023 Project CHIP Authors + * Copyright (c) 2021 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. + */ +#include "AppTask.h" +#include "AppEvent.h" +#include "CHIPDeviceManager.h" +#include "DeviceCallbacks.h" +#include "binding-handler.h" +#include "lib/core/ErrorStr.h" +#include +#include +#include + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA +#include +#endif // CHIP_DEVICE_CONFIG_ENABLE_WPA + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "AppFactoryData.h" +#include "AppMatterButton.h" +#include "AppMatterCli.h" + +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +#include "OTARequestorInitiator.h" +#endif + +#if ENABLE_OTA_PROVIDER +#include +#endif + +#if CHIP_ENABLE_OPENTHREAD +#include +#endif + +#if TCP_DOWNLOAD +#include "TcpDownload.h" +#endif + +#ifndef APP_TASK_STACK_SIZE +#define APP_TASK_STACK_SIZE ((configSTACK_DEPTH_TYPE) 6144 / sizeof(portSTACK_TYPE)) +#endif +#ifndef APP_TASK_PRIORITY +#define APP_TASK_PRIORITY 2 +#endif +#define APP_EVENT_QUEUE_SIZE 10 + +static QueueHandle_t sAppEventQueue; + +using namespace chip; +using namespace chip::TLV; +using namespace ::chip::Credentials; +using namespace ::chip::DeviceLayer; +using namespace ::chip::DeviceManager; +using namespace ::chip::app::Clusters; + +chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider; + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA +namespace { +chip::app::Clusters::NetworkCommissioning::Instance + sWiFiNetworkCommissioningInstance(0 /* Endpoint Id */, + &(::chip::DeviceLayer::NetworkCommissioning::NXPWiFiDriver::GetInstance())); +} // namespace + +void NetWorkCommissioningInstInit() +{ + sWiFiNetworkCommissioningInstance.Init(); +} +#endif // CHIP_DEVICE_CONFIG_ENABLE_WPA + +AppTask AppTask::sAppTask; + +CHIP_ERROR AppTask::StartAppTask() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + TaskHandle_t taskHandle; + + sAppEventQueue = xQueueCreate(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent)); + if (sAppEventQueue == NULL) + { + err = CHIP_ERROR_NO_MEMORY; + ChipLogError(DeviceLayer, "Failed to allocate app event queue"); + assert(err == CHIP_NO_ERROR); + } + + if (xTaskCreate(&AppTask::AppTaskMain, "AppTaskMain", APP_TASK_STACK_SIZE, &sAppTask, APP_TASK_PRIORITY, &taskHandle) != pdPASS) + { + err = CHIP_ERROR_NO_MEMORY; + ChipLogError(DeviceLayer, "Failed to start app task"); + assert(err == CHIP_NO_ERROR); + } + + return err; +} + +#if CHIP_ENABLE_OPENTHREAD +void LockOpenThreadTask(void) +{ + chip::DeviceLayer::ThreadStackMgr().LockThreadStack(); +} + +void UnlockOpenThreadTask(void) +{ + chip::DeviceLayer::ThreadStackMgr().UnlockThreadStack(); +} +#endif + +void AppTask::InitServer(intptr_t arg) +{ + static chip::CommonCaseDeviceServerInitParams initParams; + (void) initParams.InitializeStaticResourcesBeforeServerInit(); + +#if CHIP_ENABLE_OPENTHREAD + // 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); +#endif + VerifyOrDie((chip::Server::GetInstance().Init(initParams)) == CHIP_NO_ERROR); + + gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); + chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); + +#ifdef DEVICE_TYPE_ALL_CLUSTERS + // Disable last fixed endpoint, which is used as a placeholder for all of the + // supported clusters so that ZAP will generated the requisite code. + emberAfEndpointEnableDisable(emberAfEndpointFromIndex(static_cast(emberAfFixedEndpointCount() - 1)), false); +#endif /* DEVICE_TYPE_ALL_CLUSTERS */ + +#if ENABLE_OTA_PROVIDER + InitOTAServer(); +#endif +} + +CHIP_ERROR AppTask::Init() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + /* Init Chip memory management before the stack */ + chip::Platform::MemoryInit(); + + /* Initialize Matter factory data before initializing the Matter stack */ + err = AppFactoryData_PreMatterStackInit(); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Pre Factory Data Provider init failed"); + goto exit; + } + + /* + * Initialize the CHIP stack. + * Would also initialize all required platform modules + */ + err = PlatformMgr().InitChipStack(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "PlatformMgr().InitChipStack() failed: %s", ErrorStr(err)); + goto exit; + } + + /* Initialize Matter factory data after initializing the Matter stack */ + err = AppFactoryData_PostMatterStackInit(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Post Factory Data Provider init failed"); + goto exit; + } + + /* + * Register all application callbacks allowing to be informed of stack events + */ + err = CHIPDeviceManager::GetInstance().Init(&deviceCallbacks); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "CHIPDeviceManager.Init() failed: %s", ErrorStr(err)); + goto exit; + } + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + ConnectivityMgrImpl().StartWiFiManagement(); +#endif + +#if CHIP_ENABLE_OPENTHREAD + err = ThreadStackMgr().InitThreadStack(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Error during ThreadStackMgr().InitThreadStack()"); + goto exit; + } + + err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router); + if (err != CHIP_NO_ERROR) + { + goto exit; + } +#endif + + /* + * Schedule an event to the Matter stack to initialize + * the ZCL Data Model and start server + */ + PlatformMgr().ScheduleWork(InitServer, 0); + + /* Init binding handlers */ + err = InitBindingHandlers(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "InitBindingHandlers failed: %s", ErrorStr(err)); + goto exit; + } + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + NetWorkCommissioningInstInit(); +#endif // CHIP_DEVICE_CONFIG_ENABLE_WPA + +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + /* If an update is under test make it permanent */ + OTARequestorInitiator::Instance().HandleSelfTest(); +#endif + + /* Register Matter CLI cmds */ + err = AppMatterCli_RegisterCommands(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Error during AppMatterCli_RegisterCommands"); + goto exit; + } + /* Register Matter buttons */ + err = AppMatterButton_registerButtons(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Error during AppMatterButton_registerButtons"); + goto exit; + } + + err = DisplayDeviceInformation(); + if (err != CHIP_NO_ERROR) + goto exit; + + /* Start a task to run the CHIP Device event loop. */ + err = PlatformMgr().StartEventLoopTask(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Error during PlatformMgr().StartEventLoopTask()"); + goto exit; + } + +#if CHIP_ENABLE_OPENTHREAD + // Start OpenThread task + err = ThreadStackMgrImpl().StartThreadTask(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Error during ThreadStackMgrImpl().StartThreadTask()"); + goto exit; + } +#endif + +#if TCP_DOWNLOAD + EnableTcpDownloadComponent(); +#endif + +exit: + return err; +} + +void AppTask::AppTaskMain(void * pvParameter) +{ + AppTask * task = (AppTask *) pvParameter; + CHIP_ERROR err; + AppEvent event; + + ChipLogProgress(DeviceLayer, "Welcome to NXP All Clusters Demo App"); + + err = task->Init(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "AppTask.Init() failed"); + assert(err == CHIP_NO_ERROR); + } + + while (true) + { + BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, portMAX_DELAY); + while (eventReceived == pdTRUE) + { + sAppTask.DispatchEvent(&event); + eventReceived = xQueueReceive(sAppEventQueue, &event, 0); + } + } +} + +CHIP_ERROR AppTask::DisplayDeviceInformation(void) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + uint16_t discriminator; + uint32_t setupPasscode; + uint16_t vendorId; + uint16_t productId; + char currentSoftwareVer[ConfigurationManager::kMaxSoftwareVersionStringLength + 1]; + + err = GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Couldn't get discriminator: %s", ErrorStr(err)); + goto exit; + } + ChipLogProgress(DeviceLayer, "Setup discriminator: %u (0x%x)", discriminator, discriminator); + + err = GetCommissionableDataProvider()->GetSetupPasscode(setupPasscode); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Couldn't get setupPasscode: %s", ErrorStr(err)); + goto exit; + } + ChipLogProgress(DeviceLayer, "Setup passcode: %lu (0x%lx)", setupPasscode, setupPasscode); + + err = GetDeviceInstanceInfoProvider()->GetVendorId(vendorId); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Couldn't get vendorId: %s", ErrorStr(err)); + goto exit; + } + ChipLogProgress(DeviceLayer, "Vendor ID: %u (0x%x)", vendorId, vendorId); + + err = GetDeviceInstanceInfoProvider()->GetProductId(productId); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Couldn't get productId: %s", ErrorStr(err)); + goto exit; + } + ChipLogProgress(DeviceLayer, "nProduct ID: %u (0x%x)", productId, productId); + + // QR code will be used with CHIP Tool +#if CONFIG_NETWORK_LAYER_BLE + PrintOnboardingCodes(chip::RendezvousInformationFlag(chip::RendezvousInformationFlag::kBLE)); +#else + PrintOnboardingCodes(chip::RendezvousInformationFlag(chip::RendezvousInformationFlag::kOnNetwork)); +#endif /* CONFIG_NETWORK_LAYER_BLE */ + + err = ConfigurationMgr().GetSoftwareVersionString(currentSoftwareVer, sizeof(currentSoftwareVer)); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Get current software version error"); + goto exit; + } + + ChipLogProgress(DeviceLayer, "Current Software Version: %s", currentSoftwareVer); + +exit: + return err; +} + +void AppTask::PostEvent(const AppEvent * aEvent) +{ + if (sAppEventQueue != NULL) + { + if (!xQueueSend(sAppEventQueue, aEvent, 0)) + { + ChipLogError(DeviceLayer, "Failed to post event to app task event queue"); + } + } +} + +void AppTask::DispatchEvent(AppEvent * aEvent) +{ + if (aEvent->Handler) + { + aEvent->Handler(aEvent); + } + else + { + ChipLogProgress(DeviceLayer, "Event received with no handler. Dropping event."); + } +} + +void AppTask::StartCommissioning(intptr_t arg) +{ + /* Check the status of the commissioning */ + if (ConfigurationMgr().IsFullyProvisioned()) + { + ChipLogProgress(DeviceLayer, "Device already commissioned"); + } + else if (chip::Server::GetInstance().GetCommissioningWindowManager().IsCommissioningWindowOpen()) + { + ChipLogProgress(DeviceLayer, "Commissioning window already opened"); + } + else + { + chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow(); + } +} + +void AppTask::StopCommissioning(intptr_t arg) +{ + /* Check the status of the commissioning */ + if (ConfigurationMgr().IsFullyProvisioned()) + { + ChipLogProgress(DeviceLayer, "Device already commissioned"); + } + else if (!chip::Server::GetInstance().GetCommissioningWindowManager().IsCommissioningWindowOpen()) + { + ChipLogProgress(DeviceLayer, "Commissioning window not opened"); + } + else + { + chip::Server::GetInstance().GetCommissioningWindowManager().CloseCommissioningWindow(); + } +} + +void AppTask::SwitchCommissioningState(intptr_t arg) +{ + /* Check the status of the commissioning */ + if (ConfigurationMgr().IsFullyProvisioned()) + { + ChipLogProgress(DeviceLayer, "Device already commissioned"); + } + else if (!chip::Server::GetInstance().GetCommissioningWindowManager().IsCommissioningWindowOpen()) + { + chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow(); + } + else + { + chip::Server::GetInstance().GetCommissioningWindowManager().CloseCommissioningWindow(); + } +} + +void AppTask::StartCommissioningHandler(void) +{ + /* Publish an event to the Matter task to always set the commissioning state in the Matter task context */ + PlatformMgr().ScheduleWork(StartCommissioning, 0); +} + +void AppTask::StopCommissioningHandler(void) +{ + /* Publish an event to the Matter task to always set the commissioning state in the Matter task context */ + PlatformMgr().ScheduleWork(StopCommissioning, 0); +} + +void AppTask::SwitchCommissioningStateHandler(void) +{ + /* Publish an event to the Matter task to always set the commissioning state in the Matter task context */ + PlatformMgr().ScheduleWork(SwitchCommissioningState, 0); +} + +void AppTask::FactoryResetHandler(void) +{ + ConfigurationMgr().InitiateFactoryReset(); +} diff --git a/examples/all-clusters-app/nxp/common/main/CHIPDeviceManager.cpp b/examples/all-clusters-app/nxp/common/main/CHIPDeviceManager.cpp new file mode 100644 index 00000000000000..9211601de61862 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/CHIPDeviceManager.cpp @@ -0,0 +1,63 @@ +/* + * + * 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. + */ + +/** + * @file + * This file implements the CHIP Device Interface that is used by + * applications to interact with the CHIP stack + * + */ + +#include + +#include "CHIPDeviceManager.h" +#include +#include +#include +#include +#include + +using namespace ::chip; + +namespace chip { + +namespace DeviceManager { + +using namespace ::chip::DeviceLayer; + +void CHIPDeviceManager::CommonDeviceEventHandler(const ChipDeviceEvent * event, intptr_t arg) +{ + CHIPDeviceManagerCallbacks * cb = reinterpret_cast(arg); + if (cb != nullptr) + { + cb->DeviceEventCallback(event, reinterpret_cast(cb)); + } +} + +CHIP_ERROR CHIPDeviceManager::Init(CHIPDeviceManagerCallbacks * cb) +{ + CHIP_ERROR err; + mCB = cb; + + // Register a function to receive events from the CHIP device layer. Note that calls to + // this function will happen on the CHIP event loop thread. + err = PlatformMgr().AddEventHandler(CHIPDeviceManager::CommonDeviceEventHandler, reinterpret_cast(cb)); + + return err; +} +} // namespace DeviceManager +} // namespace chip diff --git a/examples/all-clusters-app/nxp/common/main/DeviceCallbacks.cpp b/examples/all-clusters-app/nxp/common/main/DeviceCallbacks.cpp new file mode 100644 index 00000000000000..419ad3b3003b2e --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/DeviceCallbacks.cpp @@ -0,0 +1,177 @@ +/* + * + * Copyright (c) 2020-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. + */ + +/** + * @file DeviceCallbacks.cpp + * + * Implements all the callbacks to the application from the CHIP Stack + * + **/ +#include "DeviceCallbacks.h" + +#include +#include +#include + +#include +#if CHIP_ENABLE_OPENTHREAD && CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED +#include "openthread-system.h" +#include "ot_platform_common.h" +#endif /* CHIP_ENABLE_OPENTHREAD && CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED */ + +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +#include "OTARequestorInitiator.h" +#endif + +Identify gIdentify0 = { + chip::EndpointId{ 1 }, + [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStart"); }, + [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStop"); }, + chip::app::Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator, + [](Identify *) { ChipLogProgress(Zcl, "onIdentifyTriggerEffect"); }, +}; + +Identify gIdentify1 = { + chip::EndpointId{ 1 }, + [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStart"); }, + [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStop"); }, + chip::app::Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator, + [](Identify *) { ChipLogProgress(Zcl, "onIdentifyTriggerEffect"); }, +}; + +using namespace ::chip; +using namespace ::chip::Inet; +using namespace ::chip::System; +using namespace ::chip::DeviceLayer; + +void DeviceCallbacks::DeviceEventCallback(const ChipDeviceEvent * event, intptr_t arg) +{ + ChipLogDetail(DeviceLayer, "DeviceEventCallback: 0x%04x", event->Type); + switch (event->Type) + { + case DeviceEventType::kWiFiConnectivityChange: + OnWiFiConnectivityChange(event); + break; + + case DeviceEventType::kInternetConnectivityChange: + OnInternetConnectivityChange(event); + break; + + case DeviceEventType::kInterfaceIpAddressChanged: + OnInterfaceIpAddressChanged(event); + break; + +#if CHIP_ENABLE_OPENTHREAD && CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED + case DeviceEventType::kCommissioningComplete: + DeviceCallbacks::OnComissioningComplete(event); + break; +#endif + case DeviceLayer::DeviceEventType::kDnssdInitialized: + ChipLogProgress(DeviceLayer, "kDnssdInitialized"); +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + /* Initialize OTA Requestor */ + OTARequestorInitiator::Instance().InitOTA(reinterpret_cast(&OTARequestorInitiator::Instance())); +#endif + break; + } +} + +void DeviceCallbacks::PostAttributeChangeCallback(EndpointId endpointId, ClusterId clusterId, AttributeId attributeId, uint8_t type, + uint16_t size, uint8_t * value) +{ + ChipLogProgress(DeviceLayer, + "endpointId " ChipLogFormatMEI " clusterId " ChipLogFormatMEI " attribute ID: " ChipLogFormatMEI + " Type: %u Value: %u, length %u", + ChipLogValueMEI(endpointId), ChipLogValueMEI(clusterId), ChipLogValueMEI(attributeId), type, *value, size); +} + +void DeviceCallbacks::OnWiFiConnectivityChange(const ChipDeviceEvent * event) +{ + if (event->WiFiConnectivityChange.Result == kConnectivity_Established) + { + ChipLogProgress(DeviceLayer, "WiFi connection established"); + } + else if (event->WiFiConnectivityChange.Result == kConnectivity_Lost) + { + ChipLogProgress(DeviceLayer, "WiFi connection lost"); + } +} + +void DeviceCallbacks::OnInternetConnectivityChange(const ChipDeviceEvent * event) +{ + if (event->InternetConnectivityChange.IPv4 == kConnectivity_Established) + { + char ip_addr[Inet::IPAddress::kMaxStringLength]; + event->InternetConnectivityChange.ipAddress.ToString(ip_addr); + ChipLogProgress(DeviceLayer, "Server ready at: %s:%d", ip_addr, CHIP_PORT); + } + else if (event->InternetConnectivityChange.IPv4 == kConnectivity_Lost) + { + ChipLogProgress(DeviceLayer, "Lost IPv4 connectivity..."); + } + if (event->InternetConnectivityChange.IPv6 == kConnectivity_Established) + { + char ip_addr[Inet::IPAddress::kMaxStringLength]; + event->InternetConnectivityChange.ipAddress.ToString(ip_addr); + ChipLogProgress(DeviceLayer, "IPv6 Server ready at: [%s]:%d", ip_addr, CHIP_PORT); + } + else if (event->InternetConnectivityChange.IPv6 == kConnectivity_Lost) + { + ChipLogProgress(DeviceLayer, "Lost IPv6 connectivity..."); + } +} + +void DeviceCallbacks::OnInterfaceIpAddressChanged(const ChipDeviceEvent * event) +{ + switch (event->InterfaceIpAddressChanged.Type) + { + case InterfaceIpChangeType::kIpV4_Assigned: + ChipLogProgress(DeviceLayer, "Interface IPv4 address assigned"); + break; + case InterfaceIpChangeType::kIpV4_Lost: + ChipLogProgress(DeviceLayer, "Interface IPv4 address lost"); + break; + case InterfaceIpChangeType::kIpV6_Assigned: + ChipLogProgress(DeviceLayer, "Interface IPv6 address assigned"); + break; + case InterfaceIpChangeType::kIpV6_Lost: + ChipLogProgress(DeviceLayer, "Interface IPv6 address lost"); + break; + } +} + +#if CHIP_ENABLE_OPENTHREAD && CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED +void DeviceCallbacks::OnComissioningComplete(const chip::DeviceLayer::ChipDeviceEvent * event) +{ + /* + * If a transceiver supporting a multiprotocol scenario is used, a check of the provisioning state is required, + * so that we can inform the transceiver to stop BLE to give the priority to another protocol. + * For example it is the case when a K32W0 transceiver supporting OT+BLE+Zigbee is used. When the device is already provisioned, + * BLE is no more required and the transceiver needs to be informed so that Zigbee can be switched on and BLE switched off. + * + * If a transceiver does not support such vendor property the cmd would be ignored. + */ + if (ConfigurationMgr().IsFullyProvisioned()) + { + ChipLogDetail(DeviceLayer, "Provisioning complete, stopping BLE\n"); + ThreadStackMgrImpl().LockThreadStack(); + PlatformMgrImpl().StopBLEConnectivity(); + ThreadStackMgrImpl().UnlockThreadStack(); + } +} +#endif diff --git a/examples/all-clusters-app/nxp/common/main/ZclCallbacks.cpp b/examples/all-clusters-app/nxp/common/main/ZclCallbacks.cpp new file mode 100644 index 00000000000000..86ea10f4687558 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/ZclCallbacks.cpp @@ -0,0 +1,41 @@ +/* + * + * Copyright (c) 2021-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 + +#include "AppTask.h" +#include "CHIPDeviceManager.h" + +#include +#include +#include +#include +#include + +using namespace ::chip; + +void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & path, uint8_t type, uint16_t size, uint8_t * value) +{ + chip::DeviceManager::CHIPDeviceManagerCallbacks * cb = + chip::DeviceManager::CHIPDeviceManager::GetInstance().GetCHIPDeviceManagerCallbacks(); + if (cb != nullptr) + { + // propagate event to device manager + cb->PostAttributeChangeCallback(path.mEndpointId, path.mClusterId, path.mAttributeId, type, size, value); + } +} diff --git a/examples/all-clusters-app/nxp/common/main/include/AppEvent.h b/examples/all-clusters-app/nxp/common/main/include/AppEvent.h new file mode 100644 index 00000000000000..8047da99982e23 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/include/AppEvent.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2021 Nest Labs, Inc. + * 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 + +struct AppEvent; +typedef void (*EventHandler)(AppEvent *); + +struct AppEvent +{ + enum AppEventTypes + { + kEventType_Timer = 0, + kEventType_TurnOn, + kEventType_Install, + }; + + uint16_t Type; + + union + { + struct + { + void * Context; + } TimerEvent; + struct + { + uint8_t Action; + int32_t Actor; + } ClusterEvent; + }; + + EventHandler Handler; +}; diff --git a/examples/all-clusters-app/nxp/common/main/include/AppFactoryData.h b/examples/all-clusters-app/nxp/common/main/include/AppFactoryData.h new file mode 100644 index 00000000000000..9c84a89b0f4bc2 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/include/AppFactoryData.h @@ -0,0 +1,43 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * 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. + */ + +#ifndef _APP_FACTORY_DATA_H_ +#define _APP_FACTORY_DATA_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Allows to register Matter factory data before initializing the Matter stack + */ +CHIP_ERROR AppFactoryData_PreMatterStackInit(void); + +/** + * Allows to register Matter factory data after initializing the Matter stack + */ +CHIP_ERROR AppFactoryData_PostMatterStackInit(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _APP_FACTORY_DATA_H_ */ diff --git a/examples/all-clusters-app/nxp/common/main/include/AppMatterButton.h b/examples/all-clusters-app/nxp/common/main/include/AppMatterButton.h new file mode 100644 index 00000000000000..0c107269be620a --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/include/AppMatterButton.h @@ -0,0 +1,38 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * 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. + */ + +#ifndef _MATTER_BUTTON_H_ +#define _MATTER_BUTTON_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * API allowing to register matter buttons + */ +CHIP_ERROR AppMatterButton_registerButtons(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _MATTER_BUTTON_H_ */ diff --git a/examples/all-clusters-app/nxp/common/main/include/AppMatterCli.h b/examples/all-clusters-app/nxp/common/main/include/AppMatterCli.h new file mode 100644 index 00000000000000..ee043e52320782 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/include/AppMatterCli.h @@ -0,0 +1,26 @@ +/* + * Copyright 2022 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _MATTER_CLI_H_ +#define _MATTER_CLI_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * API allowing to register matter cli command + */ +CHIP_ERROR AppMatterCli_RegisterCommands(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _MATTER_CLI_H_ */ diff --git a/examples/all-clusters-app/nxp/common/main/include/AppTask.h b/examples/all-clusters-app/nxp/common/main/include/AppTask.h new file mode 100644 index 00000000000000..e276e287aa92a6 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/include/AppTask.h @@ -0,0 +1,65 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2021-2023 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. + */ + +#pragma once + +#include +#include + +#include "AppEvent.h" +#include "DeviceCallbacks.h" + +class AppTask +{ +public: + CHIP_ERROR StartAppTask(); + static void AppTaskMain(void * pvParameter); + + void PostEvent(const AppEvent * event); + + /* Commissioning handlers */ + void StartCommissioningHandler(void); + void StopCommissioningHandler(void); + void SwitchCommissioningStateHandler(void); + + /* FactoryResetHandler */ + void FactoryResetHandler(void); + +private: + DeviceCallbacks deviceCallbacks; + + friend AppTask & GetAppTask(void); + + CHIP_ERROR Init(); + void DispatchEvent(AppEvent * event); + CHIP_ERROR DisplayDeviceInformation(void); + + /* Functions that would be called in the Matter task context */ + static void StartCommissioning(intptr_t arg); + static void StopCommissioning(intptr_t arg); + static void SwitchCommissioningState(intptr_t arg); + static void InitServer(intptr_t arg); + + static AppTask sAppTask; +}; + +inline AppTask & GetAppTask(void) +{ + return AppTask::sAppTask; +} diff --git a/examples/all-clusters-app/nxp/common/main/include/CHIPDeviceManager.h b/examples/all-clusters-app/nxp/common/main/include/CHIPDeviceManager.h new file mode 100644 index 00000000000000..3f3d6e51eb4067 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/include/CHIPDeviceManager.h @@ -0,0 +1,125 @@ +/* + * + * 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. + */ + +/** + * @file + * This file contains definitions for the CHIP DeviceManager Interface + * + * This object will co-ordinate multiple activities such as + * initialisation, rendezvous, session mgmt and other such + * activities within the CHIP stack. This is a singleton object. + */ + +#pragma once + +#include +#include +#include + +#include + +#include +#include + +#include + +namespace chip { +namespace DeviceManager { + +/** + * @brief + * This class provides a skeleton for all the callback functions. The functions will be + * called by other objects within the CHIP stack for specific events. + * Applications interested in receiving specific callbacks can specialize this class and handle + * these events in their implementation of this class. + */ +class DLL_EXPORT CHIPDeviceManagerCallbacks +{ +public: + /** + * @brief + * Called when CHIP Device events (PublicEventTypes) are triggered. + * + * @param event ChipDeviceEvent that occurred + * @param arg arguments specific to the event, if any + */ + virtual void DeviceEventCallback(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg) {} + + /** + * @brief + * Called after an attribute has been changed + * + * @param endpoint endpoint id + * @param clusterID cluster id + * @param attributeId attribute id that was changed + * @param mask mask of the attribute + * @param manufacturerCode manufacturer code + * @param type attribute type + * @param size size of the attribute + * @param value pointer to the new value + */ + virtual void PostAttributeChangeCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, chip::AttributeId attributeId, + uint8_t type, uint16_t size, uint8_t * value) + {} + + virtual ~CHIPDeviceManagerCallbacks() {} +}; + +/** + * @brief + * A common class that drives other components of the CHIP stack + */ +class DLL_EXPORT CHIPDeviceManager +{ +public: + CHIPDeviceManager(const CHIPDeviceManager &) = delete; + CHIPDeviceManager(const CHIPDeviceManager &&) = delete; + CHIPDeviceManager & operator=(const CHIPDeviceManager &) = delete; + + static CHIPDeviceManager & GetInstance() + { + static CHIPDeviceManager instance; + return instance; + } + + /** + * @brief + * Initialise CHIPDeviceManager + * + * @param cb Application's instance of the CHIPDeviceManagerCallbacks for consuming events + */ + CHIP_ERROR Init(CHIPDeviceManagerCallbacks * cb); + + /** + * @brief + * Fetch a pointer to the registered CHIPDeviceManagerCallbacks object. + * + */ + CHIPDeviceManagerCallbacks * GetCHIPDeviceManagerCallbacks() { return mCB; } + + /** + * Use internally for registration of the ChipDeviceEvents + */ + static void CommonDeviceEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); + +private: + CHIPDeviceManagerCallbacks * mCB = nullptr; + CHIPDeviceManager() {} +}; + +} // namespace DeviceManager +} // namespace chip diff --git a/examples/all-clusters-app/nxp/common/main/include/DeviceCallbacks.h b/examples/all-clusters-app/nxp/common/main/include/DeviceCallbacks.h new file mode 100644 index 00000000000000..2a37a2dfb99a94 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/include/DeviceCallbacks.h @@ -0,0 +1,49 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file DeviceCallbacks.h + * + * Implementations for the DeviceManager callbacks for this application + * + **/ + +#pragma once + +#include "CHIPDeviceManager.h" +#include +#include + +class DeviceCallbacks : public chip::DeviceManager::CHIPDeviceManagerCallbacks +{ +public: + virtual void DeviceEventCallback(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); + virtual void PostAttributeChangeCallback(chip::EndpointId endpointId, chip::ClusterId clusterId, chip::AttributeId attributeId, + uint8_t type, uint16_t size, uint8_t * value); + +private: + void OnWiFiConnectivityChange(const chip::DeviceLayer::ChipDeviceEvent * event); + void OnInternetConnectivityChange(const chip::DeviceLayer::ChipDeviceEvent * event); + void OnSessionEstablished(const chip::DeviceLayer::ChipDeviceEvent * event); + void OnInterfaceIpAddressChanged(const chip::DeviceLayer::ChipDeviceEvent * event); + void OnOnOffPostAttributeChangeCallback(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value); + void OnIdentifyPostAttributeChangeCallback(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value); +#if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED + void OnComissioningComplete(const chip::DeviceLayer::ChipDeviceEvent * event); +#endif +}; diff --git a/examples/all-clusters-app/nxp/common/main/main.cpp b/examples/all-clusters-app/nxp/common/main/main.cpp new file mode 100644 index 00000000000000..c2305cf9ac4eb6 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/main.cpp @@ -0,0 +1,49 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2021-2023 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. + */ + +// ================================================================================ +// Main Code +// ================================================================================ + +#include "FreeRTOS.h" +#include +#include +#include + +#if configAPPLICATION_ALLOCATED_HEAP +uint8_t __attribute__((section(".heap"))) ucHeap[configTOTAL_HEAP_SIZE]; +#endif + +using namespace ::chip::DeviceLayer; + +extern "C" int main(int argc, char * argv[]) +{ + TaskHandle_t taskHandle; + + PlatformMgrImpl().HardwareInit(); + GetAppTask().StartAppTask(); + vTaskStartScheduler(); +} + +#if (defined(configCHECK_FOR_STACK_OVERFLOW) && (configCHECK_FOR_STACK_OVERFLOW > 0)) +void vApplicationStackOverflowHook(TaskHandle_t xTask, char * pcTaskName) +{ + assert(0); +} +#endif diff --git a/examples/all-clusters-app/nxp/rt/rw61x/.gn b/examples/all-clusters-app/nxp/rt/rw61x/.gn new file mode 100644 index 00000000000000..c0a26c2dc77832 --- /dev/null +++ b/examples/all-clusters-app/nxp/rt/rw61x/.gn @@ -0,0 +1,33 @@ +# 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 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 new file mode 100644 index 00000000000000..4c0ccba283249b --- /dev/null +++ b/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn @@ -0,0 +1,191 @@ +# Copyright (c) 2021 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") +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() { + # This defines the device type as a "thermostat" by default, + # use "all-clusters" in order to build the all-clusters-app + nxp_device_type = "thermostat" +} + +example_platform_dir = "${chip_root}/examples/platform/nxp/${nxp_platform}" + +if (nxp_device_type == "thermostat") { + app_common_folder = "${nxp_device_type}/nxp/zap" +} else { + app_common_folder = "${nxp_device_type}-app/${nxp_device_type}-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" ] + + # 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" ] +} + +# 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" ] + + 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/AppFactoryDataDefaultImpl.cpp", + "../../common/main/AppMatterButtonEmpty.cpp", + "../../common/main/AppMatterCli.cpp", + "../../common/main/AppTask.cpp", + "../../common/main/CHIPDeviceManager.cpp", + "../../common/main/DeviceCallbacks.cpp", + "../../common/main/ZclCallbacks.cpp", + "../../common/main/include/AppEvent.h", + "../../common/main/include/AppTask.h", + "../../common/main/include/CHIPDeviceManager.h", + "../../common/main/include/DeviceCallbacks.h", + "../../common/main/main.cpp", + ] + + deps = [ "${chip_root}/examples/${app_common_folder}" ] + + if (nxp_device_type == "all-clusters") { + defines += [ "DEVICE_TYPE_ALL_CLUSTERS" ] + 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 (chip_enable_matter_cli) { + defines += [ "ENABLE_CHIP_SHELL" ] + deps += [ + "${chip_root}/examples/shell/shell_common:shell_common", + "${chip_root}/src/lib/shell:shell", + ] + } + + if (chip_enable_ota_requestor) { + sources += [ + "${chip_root}/examples/platform/nxp/common/OTARequestorInitiator.cpp", + "${chip_root}/examples/platform/nxp/common/OTARequestorInitiator.h", + ] + include_dirs += [ "${chip_root}/examples/platform/nxp/common" ] + } + + # 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/main/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/README.md b/examples/all-clusters-app/nxp/rt/rw61x/README.md new file mode 100644 index 00000000000000..d5b436d9fee8e1 --- /dev/null +++ b/examples/all-clusters-app/nxp/rt/rw61x/README.md @@ -0,0 +1,294 @@ +# CHIP RW61x All-clusters Application + +The all-clusters example implements a server which can be accessed by a CHIP +controller and can accept basic cluster commands. + +The example is based on +[Project CHIP](https://github.com/project-chip/connectedhomeip) and the NXP +RW612 SDK, and provides a prototype application that demonstrates device +commissioning and different cluster control. + +
+ +- [Introduction](#introduction) +- [Building](#building) +- [Flashing and debugging](#flashing-and-debugging) +- [Testing the example](#testing-the-example) +- [Matter Shell](#testing-the-all-clusters-application-with-matter-cli-enabled) +- [OTA Software Update](#ota-software-update) + +
+ + + +## Introduction + +The RW61x all-cluster application provides a working demonstration of the +RW610/RW612 board integration, built using the Project CHIP codebase and the NXP +RW612 SDK. The example supports basic ZCL commands and acts as a thermostat +device-type. + +The example supports: + +- Matter over Wi-Fi +- Matter over Openthread + +### Hardware requirements + +For Matter over Thread configuration : + +- [`NXP RD-RW612-BGA`] board +- BLE/15.4 antenna (to plug in Ant1) + +For Matter over WiFi configuration : + +- [`NXP RD-RW612-BGA`] or [`NXP RD-RW610-BGA`] board +- BLE antenna (to plug in Ant1) +- Wi-Fi antenna (to plug in Ant2) + + + +## Building + +In order to build the Project CHIP example, we recommend using a Linux +distribution (the demo-application was compiled on Ubuntu 20.04). + +- Follow instruction in [BUILDING.md](../../../../../docs/guides/BUILDING.md) + to setup the environment to be able to build Matter. + +- Download [RD-RW612 SDK v2.13.1](https://mcuxpresso.nxp.com/en/select). + Creating an nxp.com account is required before being able to download the + SDK. Once the account is created, login and follow the steps for downloading + SDK. The SDK Builder UI selection should be similar with the one from the + image below. In case you do not have access to the SDK, please ask your NXP + representative. + + ![MCUXpresso SDK Download](../../../../platform/nxp/rt/rw61x/doc/images/mcux-sdk-download.PNG) + + (Note: All SDK components should be selected. If size is an issue Azure RTOS + component can be omitted.) + +- Start building the application. + +``` +user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_SDK_ROOT=/home/user/Desktop/SDK_RW612/ +user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh +user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/all-clusters-app/nxp/rt/rw61x/ +``` + +#### Building with Matter over Wifi configuration on RW61x + +- Build Matter-over-Wifi configuration with BLE commissioning (ble-wifi) : + +``` +user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rw61x$ gn gen --args="chip_enable_wifi=true is_sdk_package=true" out/debug +user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rw61x$ ninja -C out/debug +``` + +#### Building with Matter over Thread configuration on RW612 + +- Build the Openthread configuration with BLE commissioning. + +``` +user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rw61x$ gn gen --args="chip_enable_openthread=true chip_inet_config_enable_ipv4=false chip_config_network_layer_ble=true is_sdk_package=true" out/debug +user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rw61x$ ninja -C out/debug +``` + +#### General information + +The resulting output file can be found in +out/debug/chip-rw61x-all-cluster-example. + +Optional GN options that can be added when building an application: + +- To enable the + [matter CLI](README.md#testing-the-all-clusters-application-with-matter-cli-enabled), + the argument `chip_enable_matter_cli=true` must be added to the _gn gen_ + command. +- To switch the SDK type used, the argument `is_=true` must be added + to the _gn gen_ command (with being either sdk_package or + sdk_internal). +- By default, the RW612 A1 board revision will be chosen. To switch to an A0 + revision, the argument `board_version=\"A0\"` must be added to the _gn gen_ + command. +- To build the application in debug mode, the argument + `is_debug=true optimize_debug=false` must be added to the _gn gen_ command. +- To build with the option to have Matter certificates/keys pre-loaded in a + specific flash area the argument `chip_with_factory_data=1` must be added to + the _gn gen_ command. (for more information see + [Guide for writing manufacturing data on NXP devices](../../../../../docs/guides/nxp_manufacturing_flow.md). +- To build the application with the OTA Requestor enabled, the arguments + `chip_enable_ota_requestor=true no_mcuboot=false` must be added to the _gn + gen_ command. (More information about the OTA Requestor feature in + [OTA Requestor README](README_OTA_Requestor.md))) + +## Manufacturing data + +See +[Guide for writing manufacturing data on NXP devices](../../../../../docs/guides/nxp_manufacturing_flow.md) + +Other comments: + +The all cluster app demonstrates the usage of encrypted Matter manufacturing +data storage. Matter manufacturing data should be encrypted using an AES 128 +software key before flashing them to the device flash. + + + +## Flashing and debugging + +### Flashing the All-Clusters application + +In order to flash the application we recommend using +[MCUXpresso IDE (version >= 11.6.0)](https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/mcuxpresso-integrated-development-environment-ide:MCUXpresso-IDE). + +- Import the previously downloaded NXP SDK into MCUXpresso IDE. + +Right click the empty space in the MCUXpresso IDE "Installed SDKs" tab to show +the menu, select the "Import archive" (or "Import folder" if a folder is used) +menu item. + +- Import the connectedhomeip repo in MCUXpresso IDE as Makefile Project. Use + _none_ as _Toolchain for Indexer Settings_: + +``` +File -> Import -> C/C++ -> Existing Code as Makefile Project +``` + +- Configure MCU Settings: + +``` +Right click on the Project -> Properties -> C/C++ Build -> MCU Settings -> Select RW612 -> Apply & Close +``` + +![MCU_Set](../../../../platform/nxp/rt/rw61x/doc/images/mcu-set.PNG) + +- Configure the toolchain editor: + +``` +Right click on the Project -> C/C++ Build-> Tool Chain Editor -> NXP MCU Tools -> Apply & Close +``` + +![toolchain](../../../../platform/nxp/rt/rw61x/doc/images/toolchain.JPG) + +- Create a debug configuration : + +``` +Right click on the Project -> Debug -> As->SEGGER JLink probes -> OK -> Select elf file +``` + +(Note : if SDK package is used, a simpler way could be duplicating the debug +configuration from the SDK Hello World example after importing it.) + +- Debug using the newly created configuration file. + + + +## Testing the example + +CHIP Tool is a Matter controller which can be used to commission a Matter device +into the network. For more information regarding how to use the CHIP Tool +controller, please refer to the +[CHIP Tool guide](../../../../../docs/guides/chip_tool_guide.md). + +To know how to commission a device over BLE, follow the instructions from +[chip-tool's README.md 'Commission a device over +BLE'][readme_ble_commissioning_section]. + +[readme_ble_commissioning_section]: + ../../../../chip-tool/README.md#commission-a-device-over-ble + +To know how to commissioning a device over IP, follow the instructions from +[chip-tool's README.md 'Pair a device over +IP'][readme_pair_ip_commissioning_section] + +[readme_pair_ip_commissioning_section]: + ../../../../chip-tool/README.md#pair-a-device-over-ip + +#### Matter over wifi configuration : + +The "ble-wifi" pairing method can be used in order to commission the device. + +#### Matter over thread configuration : + +The "ble-thread" pairing method can be used in order to commission the device. + +### Testing the all-clusters application without Matter CLI: + +1. Prepare the board with the flashed `All-cluster application` (as shown + above). +2. The All-cluster example uses UART1 (`FlexComm3`) to print logs while running + the server. To view raw UART output, start a terminal emulator like PuTTY and + connect to the used COM port with the following UART settings: + + - Baud rate: 115200 + - 8 data bits + - 1 stop bit + - No parity + - No flow control + +3. Open a terminal connection on the board and watch the printed logs. + +4. On the client side, start sending commands using the chip-tool application as + it is described + [here](../../../../chip-tool/README.md#using-the-client-to-send-matter-commands). + + + +### Testing the all-clusters application with Matter CLI enabled: + +The Matter CLI can be enabled with the all-clusters application. + +For more information about the Matter CLI default commands, you can refer to the +dedicated [ReadMe](../../../../shell/README.md). + +The All-clusters application supports additional commands : + +``` +> help +[...] +mattercommissioning Open/close the commissioning window. Usage : mattercommissioning [on|off] +matterfactoryreset Perform a factory reset on the device +matterreset Reset the device +``` + +- `matterfactoryreset` command erases the file system completely (all Matter + settings are erased). +- `matterreset` enables the device to reboot without erasing the settings. + +Here are described steps to use the all-cluster-app with the Matter CLI enabled + +1. Prepare the board with the flashed `All-cluster application` (as shown + above). +2. The matter CLI is accessible in UART1. For that, start a terminal emulator + like PuTTY and connect to the used COM port with the following UART settings: + + - Baud rate: 115200 + - 8 data bits + - 1 stop bit + - No parity + - No flow control + +3. The All-cluster example uses UART2 (`FlexComm0`) to print logs while running + the server. To view raw UART output, a pin should be plugged to an USB to + UART adapter (connector `HD2 pin 03`), then start a terminal emulator like + PuTTY and connect to the used COM port with the following UART settings: + + - Baud rate: 115200 + - 8 data bits + - 1 stop bit + - No parity + - No flow control + +4. On the client side, start sending commands using the chip-tool application as + it is described + [here](../../../../chip-tool/README.md#using-the-client-to-send-matter-commands). + + + +## OTA Software Update + +Over-The-Air software updates are supported with the RW61x all-clusters example. +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 RW61x example applications'](../../../../../docs/guides/nxp_rw61x_ota_software_update.md). diff --git a/examples/all-clusters-app/nxp/rt/rw61x/args.gni b/examples/all-clusters-app/nxp/rt/rw61x/args.gni new file mode 100644 index 00000000000000..c2d91a5db7bae7 --- /dev/null +++ b/examples/all-clusters-app/nxp/rt/rw61x/args.gni @@ -0,0 +1,19 @@ +# 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 new file mode 120000 index 00000000000000..f10867042f4d19 --- /dev/null +++ b/examples/all-clusters-app/nxp/rt/rw61x/build_overrides @@ -0,0 +1 @@ +../../../../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 new file mode 100644 index 00000000000000..9fe84849fd753f --- /dev/null +++ b/examples/all-clusters-app/nxp/rt/rw61x/include/config/CHIPProjectConfig.h @@ -0,0 +1,212 @@ +/* + * 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. +#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 +#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 + +// 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_MAX_BINDINGS + * + * Maximum number of simultaneously active bindings per ChipExchangeManager + * 1 (Time Sync) + 2 (Two 1-way subscriptions) + 1 (Software Update) = 4 + * in the worst case. Keeping another 4 as buffer. + */ +#define CHIP_CONFIG_MAX_BINDINGS 6 + +/** + * 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/all-clusters-app/nxp/rt/rw61x/third_party/connectedhomeip b/examples/all-clusters-app/nxp/rt/rw61x/third_party/connectedhomeip new file mode 120000 index 00000000000000..305f2077ffe860 --- /dev/null +++ b/examples/all-clusters-app/nxp/rt/rw61x/third_party/connectedhomeip @@ -0,0 +1 @@ +../../../../../.. \ No newline at end of file diff --git a/examples/build_overrides/nxp_sdk.gni b/examples/build_overrides/nxp_sdk.gni new file mode 100644 index 00000000000000..5648cc858a728b --- /dev/null +++ b/examples/build_overrides/nxp_sdk.gni @@ -0,0 +1,18 @@ +# 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. + +declare_args() { + # Root directory for NXP SDKs. + nxp_sdk_build_root = "//third_party/connectedhomeip/third_party/nxp" +} diff --git a/examples/platform/nxp/common/OTARequestorInitiator.cpp b/examples/platform/nxp/common/OTARequestorInitiator.cpp new file mode 100644 index 00000000000000..a7a898bb3718d1 --- /dev/null +++ b/examples/platform/nxp/common/OTARequestorInitiator.cpp @@ -0,0 +1,71 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * 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. + */ + +#include "OTARequestorInitiator.h" + +extern "C" { +#include "mflash_drv.h" +} + +using namespace chip; + +void 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.Init(&otaRequestorInit->gRequestorCore, &otaRequestorInit->gImageProcessor); + otaRequestorInit->gImageProcessor.SetOTADownloader(&otaRequestorInit->gDownloader); + + // Set the image processor instance used for handling image being downloaded + otaRequestorInit->gDownloader.SetImageProcessorDelegate(&otaRequestorInit->gImageProcessor); +} + +void OTARequestorInitiator::HandleSelfTest() +{ + /* If application is in test mode after an OTA update + mark image as "ok" to switch the update state to permanent + (if we have arrived this far, the bootloader had validated the image) */ + + mflash_drv_init(); + + OtaImgState_t update_state; + + /* Retrieve current update state */ + update_state = OTA_GetImgState(); + + if (update_state == OtaImgState_RunCandidate) + { + if (OTA_UpdateImgState(OtaImgState_Permanent) != gOtaSuccess_c) + { + ChipLogError(SoftwareUpdate, "Self-testing : Failed to switch update state to permanent"); + return; + } + + ChipLogProgress(SoftwareUpdate, "Successful software update... applied permanently"); + } + + OTA_Initialize(); + + /* If the image is not marked ok, the bootloader will automatically revert back to primary application at next reboot */ +} diff --git a/examples/platform/nxp/common/OTARequestorInitiator.h b/examples/platform/nxp/common/OTARequestorInitiator.h new file mode 100644 index 00000000000000..808a58d03dfe91 --- /dev/null +++ b/examples/platform/nxp/common/OTARequestorInitiator.h @@ -0,0 +1,50 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * 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. + */ + +#pragma once + +#include "app/clusters/ota-requestor/BDXDownloader.h" +#include "app/clusters/ota-requestor/DefaultOTARequestor.h" +#include "app/clusters/ota-requestor/DefaultOTARequestorDriver.h" +#include "app/clusters/ota-requestor/DefaultOTARequestorStorage.h" +#include "platform/nxp/common/OTAImageProcessorImpl.h" +#include + +using namespace chip; + +class OTARequestorInitiator +{ +public: + static OTARequestorInitiator & Instance(void) + { + static OTARequestorInitiator gOTARequestorInitiator; + return gOTARequestorInitiator; + } + /* Initialize OTA components */ + static void InitOTA(intptr_t context); + /* Handle update under test */ + static void HandleSelfTest(); + + /* OTA components */ + DefaultOTARequestor gRequestorCore; + DefaultOTARequestorStorage gRequestorStorage; + DeviceLayer::DefaultOTARequestorDriver gRequestorUser; + BDXDownloader gDownloader; + OTAImageProcessorImpl gImageProcessor; +}; diff --git a/examples/platform/nxp/common/app/support/BUILD.gn b/examples/platform/nxp/common/app/support/BUILD.gn new file mode 100644 index 00000000000000..c4ff97f4ee3d0c --- /dev/null +++ b/examples/platform/nxp/common/app/support/BUILD.gn @@ -0,0 +1,49 @@ +# 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("//build_overrides/nxp_sdk.gni") + +config("support_config") { + include_dirs = [ "../../.." ] + + # Link options that provides replace dynamic memory operations in standard + # library with the FreeRTOS malloc in platform code. + ldflags = [ + # memory allocation -- these must be re-entrant and do locking + "-Wl,--wrap=malloc", + "-Wl,--wrap=free", + "-Wl,--wrap=realloc", + "-Wl,--wrap=calloc", + "-Wl,--wrap=MemoryAlloc", + "-Wl,--wrap=exit", + "-Wl,--wrap=printf", + + # Wrap these in case internal newlib call them (e.g. strdup will) + # directly call _malloc_r) + "-Wl,--wrap=_malloc_r", + "-Wl,--wrap=_realloc_r", + "-Wl,--wrap=_free_r", + "-Wl,--wrap=_calloc_r", + ] +} + +source_set("freertos_memory_utils") { + sources = [ "Memconfig.cpp" ] + cflags = [ "-Wconversion" ] + + deps = [ "${nxp_sdk_build_root}:nxp_sdk" ] + + public_configs = [ ":support_config" ] +} diff --git a/examples/platform/nxp/common/app/support/Memconfig.cpp b/examples/platform/nxp/common/app/support/Memconfig.cpp new file mode 100644 index 00000000000000..65c9008f453916 --- /dev/null +++ b/examples/platform/nxp/common/app/support/Memconfig.cpp @@ -0,0 +1,210 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * 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 + * This file contains platform specific implementations for stdlib malloc/calloc/realloc/free + * functions, so that CHIPPlatformMemory* works as intended with the platform's heap. + */ + +#include "FreeRTOS.h" +#include "fsl_debug_console.h" +#include "task.h" +#include +#include +#include + +#ifndef NDEBUG +#include +#include +#endif + +#if CHIP_CONFIG_MEMORY_DEBUG_DMALLOC +#include +#include +#endif // CHIP_CONFIG_MEMORY_DEBUG_DMALLOC + +/* Assumes 8bit bytes! */ +#define heapBITS_PER_BYTE ((size_t) 8) + +/* Define the linked list structure. This is used to link free blocks in order +of their memory address. */ +typedef struct A_BLOCK_LINK +{ + struct A_BLOCK_LINK * pxNextFreeBlock; /*<< The next free block in the list. */ + size_t xBlockSize; /*<< The size of the free block. */ +} BlockLink_t; + +/* The size of the structure placed at the beginning of each allocated memory +block must by correctly byte aligned. */ +static const size_t xHeapStructSize = + (sizeof(BlockLink_t) + ((size_t) (portBYTE_ALIGNMENT - 1))) & ~((size_t) portBYTE_ALIGNMENT_MASK); + +/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize +member of an BlockLink_t structure is set then the block belongs to the +application. When the bit is free the block is still part of the free heap +space. */ +static size_t xBlockAllocatedBit = ((size_t) 1) << ((sizeof(size_t) * heapBITS_PER_BYTE) - 1); + +extern "C" { + +/* xPortMallocUsableSize relies on heap4 implementation. +It returns the size of an allocated block and it is +called by __wrap_realloc. +Thus it is validated in __wrap_realloc function that the allocated size +of the old_ptr is smaller than the allocated size of new_ptr */ +size_t xPortMallocUsableSize(void * pv) +{ + uint8_t * puc = (uint8_t *) pv; + BlockLink_t * pxLink; + void * voidp; + size_t sz = 0; + + if (pv != NULL) + { + vTaskSuspendAll(); + { + /* The memory being checked will have an BlockLink_t structure immediately + before it. */ + puc -= xHeapStructSize; + + /* This casting is to keep the compiler from issuing warnings. */ + voidp = (void *) puc; + pxLink = (BlockLink_t *) voidp; + + /* Check if the block is actually allocated. */ + configASSERT((pxLink->xBlockSize & xBlockAllocatedBit) != 0); + configASSERT(pxLink->pxNextFreeBlock == NULL); + + sz = (pxLink->xBlockSize & ~xBlockAllocatedBit) - xHeapStructSize; + } + (void) xTaskResumeAll(); + } + + return sz; +} + +void * __wrap_malloc(size_t size) +{ + return pvPortMalloc(size); +} + +void * operator new(size_t size) +{ + return pvPortMalloc(size); +} + +void operator delete(void * p) +{ + vPortFree(p); +} + +void operator delete(void * p, unsigned int size) +{ + vPortFree(p); +} + +void __wrap_free(void * ptr) +{ + vPortFree(ptr); +} + +void * __wrap_calloc(size_t num, size_t size) +{ + size_t total_size = num * size; + + // Handle overflow from (num * size) + if ((size != 0) && ((total_size / size) != num)) + { + return nullptr; + } + + void * ptr = pvPortMalloc(total_size); + if (ptr) + { + memset(ptr, 0, total_size); + } + + return ptr; +} + +void * __wrap_realloc(void * ptr, size_t new_size) +{ + + void * new_ptr = NULL; + + if (new_size) + { + size_t old_ptr_size = xPortMallocUsableSize(ptr); + if (new_size <= old_ptr_size) + { + /* Return old pointer if the newly allocated size is smaller + or equal to the allocated size for old_ptr */ + return ptr; + } + + /* if old_ptr is NULL, then old_ptr_size is zero and new_ptr will be returned */ + new_ptr = pvPortMalloc(new_size); + + if (!new_ptr) + { + return NULL; + } + + memset(reinterpret_cast(new_ptr) + old_ptr_size, 0, (new_size - old_ptr_size)); + memcpy(new_ptr, ptr, old_ptr_size); + } + + vPortFree(ptr); + + return new_ptr; +} + +void * __wrap__malloc_r(void * REENT, size_t size) +{ + return __wrap_malloc(size); +} + +void __wrap__free_r(void * REENT, void * ptr) +{ + __wrap_free(ptr); +} + +void * __wrap__realloc_r(void * REENT, void * ptr, size_t new_size) +{ + return __wrap_realloc(ptr, new_size); +} + +void * __wrap__calloc_r(void * REENT, size_t num, size_t size) +{ + return __wrap_calloc(num, size); +} + +int __wrap_printf(const char * fmt_s, ...) +{ + int res = 0; + va_list args; + + va_start(args, fmt_s); + res = DbgConsole_Vprintf(fmt_s, args); + va_end(args); + return res; +} + +} // extern "C" diff --git a/examples/platform/nxp/rt/rw61x/BUILD.gn b/examples/platform/nxp/rt/rw61x/BUILD.gn new file mode 100644 index 00000000000000..cb797b30e5c75f --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/BUILD.gn @@ -0,0 +1,25 @@ +# Copyright (c) 2020-2022 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/chip.gni") +import("//build_overrides/nxp_sdk.gni") + +config("chip_app_project_config") { + include_dirs = [ + "app/project_include", + "../../common/util/include", + "../../common/mbedtls", + ] +} diff --git a/examples/platform/nxp/rt/rw61x/app/ldscripts/RW610_flash.ld b/examples/platform/nxp/rt/rw61x/app/ldscripts/RW610_flash.ld new file mode 100644 index 00000000000000..e3b51876eca963 --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/app/ldscripts/RW610_flash.ld @@ -0,0 +1,584 @@ +/* +** ################################################################### +** Processors: RW610EVA0IK +** RW610EVA0IMP +** RW610HNA0IK +** RW610HNA0IMP +** RW610UKA0IZ +** +** Compiler: GNU C Compiler +** Reference manual: RW61X User manual Rev. 0.95, June 2022 +** Version: rev. 1.0, 2021-03-16 +** Build: b220615 +** +** Abstract: +** Linker file for the GNU C Compiler +** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2023 NXP +** All rights reserved. +** +** SPDX-License-Identifier: BSD-3-Clause +** +** http: www.nxp.com +** mail: support@nxp.com +** +** ################################################################### +*/ + +/** + * @file + * Linker instructions for RW610 + */ + +/** If OTA is enabled : MCUBoot bootloader resides at the base of the flash and occupies 0x20000 (128 kBytes) + slot 0 : main application partition (active app) + slot0 = header + ivt + m_app_cpu3 + fw_storage (cpu1/cpu2 fw) + trailer + slot 1 : OTA Update storage partition (candidate app) + slot1 = OTA image (the image received is already wrapped with header & trailer) +**/ + +/************************ Flash Layout with OTA enabled ********************* + + 0x0800_0000 FLASH_START + - - - +---------------+ - - - - - - - - - - - - - - - - - - - - + | | + | MCUBoot | + 128k | bootloader | + | | + - - - +---------------+ - - - - - - - - - - - - - - - - - - - - + 4k | Header_slot0 | ' + +---------------+ m_interrupts_start ' + | m_interrupts | ' ' + +---------------+ m_text_start ' ' + | | ' m_app_cpu3 ' + m_app_ | | ' + ' +_stated_ | m_text | ' fw_storage ' ACTIVE_APP (slot 0) + _size | | ' ' (4.4 MB) + | | ' ' + | | ' ' + +---------------+ m_text_end ' ' + 4k | Trailer_slot0 | ' + +---------------+ ' + 4k | padding | ' + - - - +---------------+ - - - - - - - - - - - - - - - - - - - - + | | FW_UPDATE_STORAGE_START ' + | | ' + | | ' + | | ' + | | ' + | OTA | ' + | Update | ' CANDIDATE_APP (slot 1) + | Image | ' (4.4 MB) + | | ' + | | ' + | | ' + | | ' + | | FW_UPDATE_STORAGE_END ' + - - - +---------------+ - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - +---------------+ - - - - - - - - - - - - - - - - - - - - + 4k | FactoryData | + - - - +---------------+ - - - - - - - - - - - - - - - - - - - - + | | NV_STORAGE_START_ADDRESS + | NVM_region | + | | NV_STORAGE_END_ADDRESS + - - - +---------------+ - - - - - - - - - - - - - - - - - - - - + 0x0C00_0000 FLASH_END + +*****************************************************************************/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0; +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0A00; +M_VECTOR_RAM_SIZE = DEFINED(__ram_vector_table__) ? 0x00000280 : 0; + +/* -------------------------------------------------------------------------- */ +/* FLEX SPI FLASH */ +/* -------------------------------------------------------------------------- */ + +m_flash_start = 0x08000000; +m_flash_size = 0x04000000; /* 64 MB */ +m_flash_end = m_flash_start + m_flash_size - 1; +m_sector_size = 0x1000; +m_vector_table_size = 0x280; + +m_flash_config_start = 0x08000400; +m_flash_config_size = 0xC00; +m_flash_config_end = m_flash_config_start + m_flash_config_size - 1; + +/* + * If OTA is enabled, we must reserve enough space for MCUboot and the image header. + * Note that MCUboot itself embeds the FlashConfig section. +*/ +m_mcuboot_size = DEFINED(__m_mcuboot_size__) ? __m_mcuboot_size__ : 0; /* 128 kB but 64kB could be enough */ +m_mcuboot_start = m_flash_start; /* The flash config section is comprised */ +m_mcuboot_end = m_mcuboot_start + m_mcuboot_size - 1; +m_mcuboot_img_hdr_sz = ((0x400 + (m_sector_size - 1))/m_sector_size)*m_sector_size; + +/* CPU1/CPU2 fw storage section */ +wifi_fw_size = 0xA0000; /* 640kB */ +ble_fw_size = 0x50000; /* 320kB */ +z154_fw_size = 0x50000; /* 320kB */ +/* fw_storage_size is the maximum possible size of CPU1 + CPU2 binaries. */ +fw_storage_size = (wifi_fw_size + ble_fw_size + z154_fw_size); + + +/* Active application section + * If OTA is enabled, the application starts after mcuboot app + image header. + * We reserve cpu3_app max size plus enough to store CPU1 and CPU2 apps because + * CPU1 and CPU2 binaries are embedded in app core binary. +*/ + +m_app_start = DEFINED(__m_mcuboot_size__) ? m_mcuboot_end + 1 : m_flash_config_end + 1; +m_app_trailer_size = m_sector_size; +m_padding_size = m_sector_size; + +/* Maximum number of sectors per slot */ +m_app_max_sectors = 0x440; /* (4.4MB / m_sector_size) */ + +/* The active image section contains the mcuboot header + m_interrupts + cpu3/cpu2/cpu1 apps + trailer + * The maximum image size available for the application is the (total_slot_size - m_padding_size). + * This is due to the last sector being used by mcuboot to perform the swap-move of the upgrade. +*/ +FW_ACTIVE_APP_START = m_app_start; +FW_ACTIVE_APP_OFFSET = m_app_start - m_flash_start; +FW_ACTIVE_APP_SIZE = m_sector_size * m_app_max_sectors - m_padding_size; +FW_ACTIVE_APP_END = FW_ACTIVE_APP_START + FW_ACTIVE_APP_SIZE - 1; + +/* The size of the stated application includes the sizes of cpu1/cpu2/cpu3 apps. + * Note that an empty sector (padding) must be kept at the end of the active image section, + * this would be used by mcuboot to perform a swap-move operation of the upgrade. + */ +m_app_stated_size = FW_ACTIVE_APP_SIZE - m_mcuboot_img_hdr_sz - m_app_trailer_size; + +m_interrupts_start = DEFINED(__m_mcuboot_size__) ? m_app_start + m_mcuboot_img_hdr_sz : m_app_start; +m_interrupts_end = m_interrupts_start + m_vector_table_size - 1; + +m_text_start = m_interrupts_end + 1; +m_text_size = m_app_stated_size - m_vector_table_size; +m_text_end = m_text_start + m_text_size - 1; + + + +/* Candidate application (OTA Update Image) section + * The size of the candidate image (slot 1) is equal to the active image (slot 0) size +*/ +FW_UPDATE_STORAGE_START = FW_ACTIVE_APP_END + 1 + m_padding_size; +FW_UPDATE_STORAGE_SIZE = FW_ACTIVE_APP_SIZE; +FW_UPDATE_STORAGE_OFFSET = FW_UPDATE_STORAGE_START - m_flash_start; +FW_UPDATE_STORAGE_END = FW_UPDATE_STORAGE_START + FW_UPDATE_STORAGE_SIZE - 1; + +fw_top = FW_UPDATE_STORAGE_END + 1; + +/* FileSystem Configuration */ +NV_STORAGE_END_ADDRESS = m_flash_end; +NV_STORAGE_MAX_SECTORS = DEFINED(gNVMSectorCountLink_d) ? gNVMSectorCountLink_d : 16; +NV_STORAGE_SECTOR_SIZE = m_sector_size; +NV_STORAGE_SIZE = NV_STORAGE_SECTOR_SIZE * NV_STORAGE_MAX_SECTORS; +NV_STORAGE_START_ADDRESS = NV_STORAGE_END_ADDRESS - NV_STORAGE_SIZE + 1; +NV_STORAGE_START_ADDRESS_OFFSET = NV_STORAGE_START_ADDRESS - m_flash_start; + +/*** FactoryData space 1 sector is reserved ***/ +__FACTORY_DATA_SIZE = m_sector_size; +__FACTORY_DATA_END = NV_STORAGE_START_ADDRESS -1; +__FACTORY_DATA_START = __FACTORY_DATA_END - __FACTORY_DATA_SIZE + 1; +__FACTORY_DATA_START_OFFSET = __FACTORY_DATA_START - m_flash_start; + +/* -------------------------------------------------------------------------- */ +/* RAM */ +/* -------------------------------------------------------------------------- */ + +m_data_start = 0x20000000; +m_data_size = 0x00130000; +m_data_end = 0x2012FFFF; + +/* -------------------------------------------------------------------------- */ +/* SMU1 - CPU3/CPU1 */ +/* -------------------------------------------------------------------------- */ + +m_sqram_cpu13_mbox_start = 0x41380000; +m_sqram_cpu13_mbox_size = 0x00000488; +m_sqram_cpu13_mbox_end = m_sqram_cpu13_mbox_start + m_sqram_cpu13_mbox_size - 1; + +m_sqram_cpu13_txq_start = m_sqram_cpu13_mbox_end + 1; +m_sqram_cpu13_txq_size = 0x1000; +m_sqram_cpu13_txq_end = m_sqram_cpu13_txq_start + m_sqram_cpu13_txq_size - 1; + +/* -------------------------------------------------------------------------- */ +/* SMU2 - CPU3/CPU2 */ +/* -------------------------------------------------------------------------- */ + +m_sqram_cpu23_mbox_start = 0x443C0000; +m_sqram_cpu23_mbox_size = 0x00000488; +m_sqram_cpu23_mbox_end = m_sqram_cpu23_mbox_start + m_sqram_cpu23_mbox_size - 1; + +m_sqram_cpu23_txq_start = m_sqram_cpu23_mbox_end + 1; +m_sqram_cpu23_txq_size = 0x1080; +m_sqram_cpu23_txq_end = m_sqram_cpu23_txq_start + m_sqram_cpu23_txq_size - 1; + +m_sqram_cpu32_txq_start = m_sqram_cpu23_txq_end + 1; +m_sqram_cpu32_txq_size = 0x1080; +m_sqram_cpu32_txq_end = m_sqram_cpu32_txq_start + m_sqram_cpu32_txq_size - 1; + + +/* Specify the memory areas */ +MEMORY +{ + m_flash_config (RX) : ORIGIN = m_flash_config_start, LENGTH = m_flash_config_size + m_interrupts (RX) : ORIGIN = m_interrupts_start, LENGTH = m_vector_table_size + m_text (RX) : ORIGIN = m_text_start, LENGTH = m_text_size + m_nvm_region (RW) : ORIGIN = NV_STORAGE_START_ADDRESS, LENGTH = NV_STORAGE_SIZE + m_data (RW) : ORIGIN = m_data_start, LENGTH = m_data_size + m_sqram_cpu13_mbox (RW) : ORIGIN = m_sqram_cpu13_mbox_start, LENGTH = m_sqram_cpu13_mbox_size + m_sqram_cpu13_txq (RW) : ORIGIN = m_sqram_cpu13_txq_start, LENGTH = m_sqram_cpu13_txq_size + m_sqram_cpu23_mbox (RW) : ORIGIN = m_sqram_cpu23_mbox_start, LENGTH = m_sqram_cpu23_mbox_size + m_sqram_cpu23_txq (RW) : ORIGIN = m_sqram_cpu23_txq_start, LENGTH = m_sqram_cpu23_txq_size + m_sqram_cpu32_txq (RW) : ORIGIN = m_sqram_cpu32_txq_start, LENGTH = m_sqram_cpu32_txq_size +} + + +/* Define output sections */ +SECTIONS +{ + .flash_config : ALIGN(4) + { + . = ALIGN(4); + __FLASH_BASE = .; + KEEP(* (.flash_conf)) /* flash config section */ + . = ALIGN(4); + } > m_flash_config + + /* The startup code goes first into internal ram */ + .interrupts : + { + . = ALIGN(4); + __VECTOR_TABLE = .; + __Vectors = .; + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } > m_interrupts + + /* The program code and other data goes into internal ram */ + .text : + { + . = ALIGN(4); + *(.rcs.*) + *(EXCLUDE_FILE( + *port.c.obj + *portasm.c.obj + *queue.c.obj + *timers.c.obj + *tasks.c.obj + *inet_chksum.c.obj + *ip4.c.obj + *pbuf.c.obj + *sys_arch.c.obj + *tcp_out.c.obj + *tcp_in.c.obj + *mlan_11n_rxreorder.c.obj + *mlan_wmm.c.obj + *wifi.c.obj + *wifi-imu.c.obj + *fsl_adapter_rfimu.c.obj + *fsl_cache.c.obj + *fsl_os_abstraction_free_rtos.c.obj + /* Exclude flash and frequently executed functions from XIP */ + *fsl_adapter_flexspi_nor_flash.c.o + *mflash_drv.c.o + *fsl_flexspi.c.o + ) .text*) /* .text* sections (code) */ + /*(EXCLUDE_FILE( + /* Exclude flash and frequently executed functions from XIP * + *fsl_adapter_flexspi_nor_flash.c.o + *mflash_drv.c.o + *fsl_flexspi.c.o + ).rodata*) /* .rodata* sections (constants, strings, etc.) */ + *(.rodata .rodata.* .constdata .constdata.*) + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + KEEP (*(.init)) + KEEP (*(.fini)) + . = ALIGN(4); + } > m_text + + ._bt_settings_area : + { + . = ALIGN(4); + _bt_settings_start = .; + KEEP(*(SORT(._bt_settings.static.*))) + _bt_settings_end = .; + . = ALIGN(4); + } > m_text + + ._settings_handler_static : + { + . = ALIGN(4); + _settings_handler_static_list_start = .; + KEEP(*(SORT(._settings_handler_static.static.*))) + _settings_handler_static_list_end = .; + . = ALIGN(4); + } > m_text + + ._bt_conn_cb : + { + . = ALIGN(4); + _bt_conn_cb_list_start = .; + KEEP(*(SORT(._bt_conn_cb.static.*))) + _bt_conn_cb_list_end = .; + . = ALIGN(4); + } > m_text + + ._bt_gatt_service_static : + { + . = ALIGN(4); + _bt_gatt_service_static_list_start = .; + KEEP(*(SORT(._bt_gatt_service_static.static.*))) + _bt_gatt_service_static_list_end = .; + . = ALIGN(4); + } > m_text + + ._bt_l2cap_fixed_chan : + { + . = ALIGN(4); + _bt_l2cap_fixed_chan_list_start = .; + KEEP(*(SORT(._bt_l2cap_fixed_chan.static.*))) + _bt_l2cap_fixed_chan_list_end = .; + . = ALIGN(4); + } > m_text + + ._bt_l2cap_br_fixed_chan : + { + . = ALIGN(4); + _bt_l2cap_br_fixed_chan_list_start = .; + KEEP(*(SORT(._bt_l2cap_br_fixed_chan.static.*))) + _bt_l2cap_br_fixed_chan_list_end = .; + . = ALIGN(4); + } > m_text + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > m_text + + .ARM : + { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } > m_text + + .ctors : + { + __CTOR_LIST__ = .; + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __CTOR_END__ = .; + } > m_text + + .dtors : + { + __DTOR_LIST__ = .; + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __DTOR_END__ = .; + } > m_text + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } > m_text + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } > m_text + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } > m_text + + __etext = .; /* define a global symbol at end of code */ + __DATA_ROM = .; /* Symbol is used by startup for data initialization */ + + .interrupts_ram : + { + . = ALIGN(4); + __VECTOR_RAM__ = .; + __interrupts_ram_start__ = .; /* Create a global symbol at data start */ + *(.m_interrupts_ram) /* This is a user defined section */ + . += M_VECTOR_RAM_SIZE; + . = ALIGN(4); + __interrupts_ram_end__ = .; /* Define a global symbol at data end */ + } > m_data + + __VECTOR_RAM = DEFINED(__ram_vector_table__) ? __VECTOR_RAM__ : ORIGIN(m_interrupts); + __RAM_VECTOR_TABLE_SIZE_BYTES = DEFINED(__ram_vector_table__) ? (__interrupts_ram_end__ - __interrupts_ram_start__) : 0x0; + + .data : AT(__DATA_ROM) + { + . = ALIGN(4); + __DATA_RAM = .; + __data_start__ = .; /* create a global symbol at data start */ + *(CodeQuickAccess) /* CodeQuickAccess sections */ + *(DataQuickAccess) /* DataQuickAccess sections */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + *port.c.obj(.text*) + *portasm.c.obj(.text*) + *queue.c.obj(.text*) + *timers.c.obj(.text*) + *tasks.c.obj(.text*) + *inet_chksum.c.obj(.text*) + *ip4.c.obj(.text*) + *pbuf.c.obj(.text*) + *sys_arch.c.obj(.text*) + *tcp_out.c.obj(.text*) + *tcp_in.c.obj(.text*) + *mlan_11n_rxreorder.c.obj(.text*) + *mlan_wmm.c.obj(.text*) + *wifi.c.obj(.text*) + *wifi-imu.c.obj(.text*) + *fsl_adapter_rfimu.c.obj(.text*) + *fsl_cache.c.obj(.text*) + *fsl_os_abstraction_free_rtos.c.obj(.text*) + /* Explicit placement of flash and frequently executed functions in RAM */ + *fsl_adapter_flexspi_nor_flash.c.o(.text .text* .rodata .rodata*) + *mflash_drv.c.o(.text* .text* .rodata .rodata*) + *fsl_flexspi.c.o(.text .text* .rodata .rodata*) + KEEP(*(.jcr*)) + . = ALIGN(4); + _k_mem_slab_list_start = .; + KEEP(*(SORT(._k_mem_slab*))) + _k_mem_slab_list_end = .; + . = ALIGN(4); + _net_buf_pool_list = .; + KEEP(*(SORT(._net_buf_pool*))) + . = ALIGN(4); + __data_end__ = .; /* define a global symbol at data end */ + } > m_data + + __DATA_END = __DATA_ROM + (__data_end__ - __data_start__); + + text_end = ORIGIN(m_text) + LENGTH(m_text); + + ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data") + + _image_size = __DATA_END - __VECTOR_TABLE; + + /* Uninitialized data section */ + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + . = ALIGN(4); + __START_BSS = .; + __bss_start__ = .; + *(.bss) + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + __END_BSS = .; + } > m_data + + .heap (NOLOAD) : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + __HeapBase = .; + KEEP(*(.heap*)) + __HeapLimit = .; + __heap_limit = .; /* Add for _sbrk */ + } > m_data + + .stack : + { + . = ALIGN(8); + __StackLimit = .; + . += STACK_SIZE; + __StackTop = .; + } > m_data + + PROVIDE(__stack = __StackTop); + + .smu_cpu13_mbox (NOLOAD) : + { + . = ALIGN(4); + *(.smu_cpu13_mbox) + KEEP (*(.smu_cpu13_mbox)) + . = ALIGN(4); + } > m_sqram_cpu13_mbox + + .smu_cpu31_txq (NOLOAD) : + { + . = ALIGN(4); + *(.smu_cpu31_txq) + KEEP (*(.smu_cpu31_txq)) + . = ALIGN(4); + } > m_sqram_cpu13_txq + + .smu_cpu23_mbox (NOLOAD) : + { + . = ALIGN(4); + SQRAM_CPU23_MBOX = .; + *(.smu_cpu23_mbox) + KEEP (*(.smu_cpu23_mbox)) + . = ALIGN(4); + } > m_sqram_cpu23_mbox + + .smu_cpu32_txq (NOLOAD) : + { + . = ALIGN(4); + *(.smu_cpu32_txq) + KEEP (*(.smu_cpu32_txq)) + . = ALIGN(4); + } > m_sqram_cpu32_txq + + .NVM : + { + FILL(0xFFFFFFFF); + . = ORIGIN(m_nvm_region) + LENGTH(m_nvm_region) - 1; + BYTE(0xFF); + } > m_nvm_region + + .ARM.attributes 0 : { *(.ARM.attributes) } + + ASSERT(__StackLimit >= __HeapLimit, "region m_data overflowed with stack and heap") + + ASSERT( (DEFINED(__m_mcuboot_size__) ? (__m_mcuboot_size__ % m_sector_size) : 0) == 0, "mcuboot size is not aligned on flash sector size") + + ASSERT(NV_STORAGE_START_ADDRESS >= FW_UPDATE_STORAGE_END, "OTA storage section overflowed") +} diff --git a/examples/platform/nxp/rt/rw61x/app/project_include/freeRTOS/FreeRTOSConfig.h b/examples/platform/nxp/rt/rw61x/app/project_include/freeRTOS/FreeRTOSConfig.h new file mode 100644 index 00000000000000..cb7d563f756f8c --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/app/project_include/freeRTOS/FreeRTOSConfig.h @@ -0,0 +1,185 @@ +/* + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK CHIP_DEVICE_CONFIG_ENABLE_WPA +#define configUSE_TICKLESS_IDLE 0 +#define configUSE_DAEMON_TASK_STARTUP_HOOK 0 +#define configCPU_CLOCK_HZ (SystemCoreClock) +#define configTICK_RATE_HZ ((TickType_t) 1000) +#define configMAX_PRIORITIES (10) + +/* stack size increased for NVM/LITTLE_FS save in idle task */ +#define configMINIMAL_STACK_SIZE ((uint16_t) 2048) +#ifndef configTOTAL_HEAP_SIZE +#define configTOTAL_HEAP_SIZE ((size_t) (122 * 1024)) +#endif +#define configAPPLICATION_ALLOCATED_HEAP 1 +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 +#define configFRTOS_MEMORY_SCHEME 4 +#define configMAX_TASK_NAME_LEN (16) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_MALLOC_FAILED_HOOK 0 +#define configUSE_APPLICATION_TASK_TAG 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configGENERATE_RUN_TIME_STATS 0 +#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +/* Define to 0 to be able to get task information in MCUXpresso */ +#define configENABLE_BACKWARD_COMPATIBILITY 1 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES (2) + +/* Software timer definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 3) +#define configTIMER_QUEUE_LENGTH 10 + +/* set to fixed value as configMINIMAL_STACK_SIZE was increased */ +#define configTIMER_TASK_STACK_DEPTH (2048) + +/* Set the following definitions to 1 to include the API function, or zero + * to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 + +/* Tasks.c additions (e.g. Thread Aware Debug capability) */ +#define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1 + +/* Normal assert() semantics without relying on the provision of an assert.h + * header file. */ +#define configASSERT(x) \ + if ((x) == 0) \ + { \ + taskDISABLE_INTERRUPTS(); \ + for (;;) \ + { \ + ; \ + } \ + } + +/* Map the FreeRTOS printf() to the logging task printf. */ +#define configPRINTF(x) vLoggingPrintf x + +/* Map the logging task's printf to the board specific output function. */ +#define configPRINT_STRING print_string + +/* Sets the length of the buffers into which logging messages are written - so + * also defines the maximum length of each log message. */ +#define configLOGGING_MAX_MESSAGE_LENGTH 256 + +/* Set to 1 to prepend each log message with a message number, the task name, + * and a time stamp. */ +#define configLOGGING_INCLUDE_TIME_AND_TASK_NAME 1 + +#define configPRE_STOP_PROCESSING vMainPreStopProcessing +#define configPOST_STOP_PROCESSING vMainPostStopProcessing + +#ifndef configENABLE_FPU +#define configENABLE_FPU 1 +#endif +#ifndef configENABLE_MPU +#define configENABLE_MPU 0 +#endif +#ifndef configENABLE_TRUSTZONE +#define configENABLE_TRUSTZONE 0 +#endif +#ifndef configRUN_FREERTOS_SECURE_ONLY +#define configRUN_FREERTOS_SECURE_ONLY 1 +#endif + +#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) +/* Clock manager provides in this variable system core clock frequency */ +#include +extern uint32_t SystemCoreClock; +#endif + +/* Interrupt nesting behaviour configuration. Cortex-M specific. */ +#ifdef __NVIC_PRIO_BITS +/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ +#define configPRIO_BITS __NVIC_PRIO_BITS +#else +#define configPRIO_BITS 4 /* 15 priority levels */ +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" +function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1U << (configPRIO_BITS)) - 1) + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL +INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER +PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2 + +/* Interrupt priorities used by the kernel port layer itself. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) + +/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS +standard names. */ +#define vPortSVCHandler SVC_Handler +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler + +#endif /* FREERTOS_CONFIG_H */ diff --git a/examples/platform/nxp/rt/rw61x/app/project_include/openthread/OpenThreadConfig.h b/examples/platform/nxp/rt/rw61x/app/project_include/openthread/OpenThreadConfig.h new file mode 100644 index 00000000000000..166222d1295311 --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/app/project_include/openthread/OpenThreadConfig.h @@ -0,0 +1,84 @@ +/* + * + * 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 + * Overrides to default OpenThread configuration. + * + */ + +#pragma once + +// When operating in a less than ideal RF environment, having a more forgiving configuration +// of OpenThread makes thread a great deal more reliable. +#define OPENTHREAD_CONFIG_TMF_ADDRESS_QUERY_MAX_RETRY_DELAY 120 // default is 28800 +#define OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_DIRECT 30 // default is 3 +#define OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_INDIRECT 1 // default is 0 +#define OPENTHREAD_CONFIG_MAC_MAX_TX_ATTEMPTS_INDIRECT_POLLS 16 // default is 4 + +// Enable periodic parent search to speed up finding a better parent. +#define OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE 1 // default is 0 +#define OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_THRESHOLD -45 // default is -65 +#define OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH 1 // default is 0 + +// Use smaller maximum interval to speed up reattaching. +#define OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MAXIMUM_INTERVAL (60 * 10 * 1000) // default 1200000 ms + +// disable unused features +#define OPENTHREAD_CONFIG_COAP_API_ENABLE 0 +#define OPENTHREAD_CONFIG_JOINER_ENABLE 0 +#define OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 0 +#define OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE 0 +#define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 0 +#define OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE 0 +#define OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE 0 +#define OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE 0 + +// Enable usage of external heap allocator for ot +#define OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE 1 + +// Disable TCP +#define OPENTHREAD_CONFIG_TCP_ENABLE 0 + +#define OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE 1 +#define OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE 1 +#define OPENTHREAD_CONFIG_ECDSA_ENABLE 1 + +// Temporary workaround till we can enable this via the gn +#ifdef SPINEL_INTERFACE_RPMSG +#define OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE 1 +#else +#define OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE 0 +#endif /* SPINEL_INTERFACE_RPMSG */ + +/* + * "ot-nxp/src/rw/rw612/platform/radio.c" has a dependency on + * "examples/platforms/utils/link_metrics.cpp" which is not built in the Matter build system + * for this reason, currently we are disabling this feature + */ +#define OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE 0 +#define OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 0 + +// Use the NXP-supplied default platform configuration for remainder +// of OpenThread config options. +// +// NB: This file gets included during the build of OpenThread. Hence +// it cannot use "openthread" in the path to the included file. +// +#include "openthread-core-rw612-config.h" diff --git a/examples/platform/nxp/rt/rw61x/board/board.c b/examples/platform/nxp/rt/rw61x/board/board.c new file mode 100644 index 00000000000000..8d378b550477f3 --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/board/board.c @@ -0,0 +1,395 @@ +/* + * Copyright 2021-2023 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "board.h" +#include "fsl_cache.h" +#include "fsl_clock.h" +#include "fsl_common.h" +#include "fsl_debug_console.h" +#include "fsl_flexspi.h" +#include "fsl_io_mux.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +#define BOARD_FLEXSPI_DLL_LOCK_RETRY (10) + +/******************************************************************************* + * Variables + ******************************************************************************/ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/******************************************************************************* + * Code + ******************************************************************************/ +/* Initialize debug console. */ +void BOARD_InitDebugConsole(void) +{ + uint32_t uartClkSrcFreq = 0; + + /* attach FRG0 clock to FLEXCOMM3 (debug console) */ + CLOCK_SetFRGClock(BOARD_DEBUG_UART_FRG_CLK); + CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH); + + uartClkSrcFreq = BOARD_DEBUG_UART_CLK_FREQ; + DbgConsole_Init(BOARD_DEBUG_UART_INSTANCE, BOARD_DEBUG_UART_BAUDRATE, BOARD_DEBUG_UART_TYPE, uartClkSrcFreq); +} + +static status_t flexspi_hyper_ram_read_id(FLEXSPI_Type * base, uint16_t * buffer) +{ + flexspi_transfer_t flashXfer; + status_t status; + + /* Write data */ + flashXfer.deviceAddress = 0x00; + flashXfer.port = kFLEXSPI_PortB1; + flashXfer.cmdType = kFLEXSPI_Read; + flashXfer.SeqNumber = 1; + flashXfer.seqIndex = 15; + flashXfer.data = (uint32_t *) buffer; + flashXfer.dataSize = 2; + + status = FLEXSPI_TransferBlocking(base, &flashXfer); + + return status; +} + +static status_t flexspi_hyper_ram_read_register(FLEXSPI_Type * base, uint32_t address, uint16_t * buffer) +{ + flexspi_transfer_t flashXfer; + status_t status; + + /* Write data */ + flashXfer.deviceAddress = address; + flashXfer.port = kFLEXSPI_PortB1; + flashXfer.cmdType = kFLEXSPI_Read; + flashXfer.SeqNumber = 1; + flashXfer.seqIndex = 13; + flashXfer.data = (uint32_t *) buffer; + flashXfer.dataSize = 2; + + status = FLEXSPI_TransferBlocking(base, &flashXfer); + + return status; +} + +static status_t flexspi_hyper_ram_write_register(FLEXSPI_Type * base, uint32_t address, uint16_t * buffer) +{ + flexspi_transfer_t flashXfer; + status_t status; + + /* Write data */ + flashXfer.deviceAddress = address; + flashXfer.port = kFLEXSPI_PortB1; + flashXfer.cmdType = kFLEXSPI_Write; + flashXfer.SeqNumber = 1; + flashXfer.seqIndex = 14; + flashXfer.data = (uint32_t *) buffer; + flashXfer.dataSize = 2; + + status = FLEXSPI_TransferBlocking(base, &flashXfer); + + return status; +} + +/* Initialize psram. */ +status_t BOARD_InitPsRam(void) +{ + flexspi_device_config_t deviceconfig = { + .flexspiRootClk = 320000000, /* 320MHZ SPI serial clock, DDR serial clock 160M */ + .isSck2Enabled = false, + .flashSize = 0x1000, /* 32Mb/KByte */ + .addressShift = true, + .CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle, + .CSInterval = 5, + .CSHoldTime = 2, + .CSSetupTime = 3, + .dataValidTime = 1, + .columnspace = 9 + 5, /* CA:9 + CA_SHIFT:5 */ + .enableWordAddress = false, + .AWRSeqIndex = 12, + .AWRSeqNumber = 1, + .ARDSeqIndex = 11, + .ARDSeqNumber = 1, + .AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle, + .AHBWriteWaitInterval = 0, + .enableWriteMask = true, + }; + + uint32_t customLUT[20] = { + /* Read Data */ + [0] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_4PAD, 0xAA, kFLEXSPI_Command_DDR, kFLEXSPI_4PAD, 0x00), + [1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_4PAD, 16, kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_4PAD, 16), + [2] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DUMMY_DDR, kFLEXSPI_4PAD, 28, kFLEXSPI_Command_READ_DDR, kFLEXSPI_4PAD, 0x01), + + /* Write Data */ + [4] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_4PAD, 0x22, kFLEXSPI_Command_DDR, kFLEXSPI_4PAD, 0x00), + [5] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_4PAD, 16, kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_4PAD, 16), + [6] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DUMMY_DDR, kFLEXSPI_4PAD, 28, kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_4PAD, 0x01), + + /* Read Register */ + [8] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_4PAD, 0xCC, kFLEXSPI_Command_DDR, kFLEXSPI_4PAD, 0x00), + [9] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_4PAD, 16, kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_4PAD, 16), + [10] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DUMMY_DDR, kFLEXSPI_4PAD, 12, kFLEXSPI_Command_READ_DDR, kFLEXSPI_4PAD, 0x01), + + /* Write Register */ + [12] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_4PAD, 0x66, kFLEXSPI_Command_DDR, kFLEXSPI_4PAD, 0x00), + [13] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_4PAD, 16, kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_4PAD, 16), + [14] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_4PAD, 0x01, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00), + + /* Read ID */ + [16] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_4PAD, 0xE0, kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_4PAD, 16), + [17] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_4PAD, 16, kFLEXSPI_Command_DUMMY_RWDS_DDR, kFLEXSPI_4PAD, 0x08), + [18] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_DDR, kFLEXSPI_4PAD, 0x01, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00), + }; + + flexspi_config_t config; +#if BOARD_ENABLE_PSRAM_CACHE + cache64_config_t cacheCfg; +#endif + status_t status = kStatus_Success; + + if (!BOARD_IS_XIP()) /* FlexSPI not initialized */ + { + CLOCK_EnableClock(kCLOCK_Flexspi); + RESET_ClearPeripheralReset(kFLEXSPI_RST_SHIFT_RSTn); + BOARD_SetFlexspiClock(FLEXSPI, 5U, 1U); + + /* Get FLEXSPI default settings and configure the flexspi. */ + FLEXSPI_GetDefaultConfig(&config); + + /* Init FLEXSPI. */ + config.rxSampleClock = kFLEXSPI_ReadSampleClkExternalInputFromDqsPad; + config.rxSampleClockPortB = kFLEXSPI_ReadSampleClkExternalInputFromDqsPad; + config.rxSampleClockDiff = true; + /*Set AHB buffer size for reading data through AHB bus. */ + config.ahbConfig.enableAHBPrefetch = true; + config.ahbConfig.enableAHBBufferable = true; + config.ahbConfig.enableAHBCachable = true; + config.ahbConfig.enableReadAddressOpt = true; + for (uint8_t i = 1; i < FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 1; i++) + { + config.ahbConfig.buffer[i].bufferSize = 0; + } + /* FlexSPI has total 1KB RX buffer. + * Set DMA0 master to use AHB Rx Buffer0. + */ + config.ahbConfig.buffer[0].masterIndex = 10; /* GDMA */ + config.ahbConfig.buffer[0].bufferSize = 512; /* Allocate 512B bytes for DMA0 */ + config.ahbConfig.buffer[0].enablePrefetch = true; + config.ahbConfig.buffer[0].priority = 0; + /* All other masters use last buffer with 512B bytes. */ + config.ahbConfig.buffer[FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 1].bufferSize = 512; +#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN) + config.enableCombination = false; +#endif + FLEXSPI_Init(BOARD_FLEXSPI_PSRAM, &config); + } + + /* Configure flash settings according to serial flash feature. */ + FLEXSPI_SetFlashConfig(BOARD_FLEXSPI_PSRAM, &deviceconfig, kFLEXSPI_PortB1); + + /* Update bottom LUT table (44-63). */ + FLEXSPI_UpdateLUT(BOARD_FLEXSPI_PSRAM, 44U, customLUT, ARRAY_SIZE(customLUT)); + + /* Do software reset. */ + FLEXSPI_SoftwareReset(BOARD_FLEXSPI_PSRAM); + + /* Read identification: the Manufacturer ID of ISSI's PSRAM(IS66/67WVQ8M4DALL) is 0x03U */ + uint16_t identification = 0x00U; + uint16_t registerVal = 0x00U; + status = flexspi_hyper_ram_read_id(BOARD_FLEXSPI_PSRAM, &identification); + if ((status != kStatus_Success) || (identification & 0x03U) != 0x03U) + { + status = kStatus_Fail; + } + + /* Read configuration register: the default setting is 0xF052(see table 6.1 Configuration Register in + PSRAM's(IS66/67WVQ8M4DALL) datasheet), which Latency code(CR[7:4]) is 0101b, which supported max frequency is + 200MHz.*/ + status = flexspi_hyper_ram_read_register(BOARD_FLEXSPI_PSRAM, 0x04U << 9, ®isterVal); + if ((status != kStatus_Success) || registerVal != 0xF052) + { + status = kStatus_Fail; + } + + /* Initial access latency configuration, which is located in bit3 of CR. */ + registerVal |= 0x01UL << 3; + + /* Write configuration register: */ + status = flexspi_hyper_ram_write_register(BOARD_FLEXSPI_PSRAM, 0x04U << 9, ®isterVal); + if ((status != kStatus_Success) || registerVal != 0xF05A) + { + status = kStatus_Fail; + } + + /* Reset */ + registerVal = 0x00U; + + /* Read configuration register: changes default Variable Latency into Fixed Latency: 0xF05A. + Note: FlexSPI only supports fixed latency mode for ISSI's psram. */ + status = flexspi_hyper_ram_read_register(BOARD_FLEXSPI_PSRAM, 0x04U << 9, ®isterVal); + if ((status != kStatus_Success) || registerVal != 0xF05A) + { + status = kStatus_Fail; + } + +#if BOARD_ENABLE_PSRAM_CACHE + CACHE64_GetDefaultConfig(&cacheCfg); + /* Suppose: + Flash on PC bus starting from 0x08000000, controlled by cache 0. + PSRAM on PS bus starting from 0x28000000, controlled by cache 1. + */ + CACHE64_Init(CACHE64_POLSEL1, &cacheCfg); + CACHE64_EnableWriteBuffer(CACHE64_CTRL1, true); + CACHE64_EnableCache(CACHE64_CTRL1); +#endif + + return status; +} + +void BOARD_InitSleepPinConfig(void) +{ + int32_t i; + + /* Set all non-AON pins output low level in sleep mode. */ + for (i = 0; i < 22; i++) + { + IO_MUX_SetPinOutLevelInSleep(i, IO_MUX_SleepPinLevelLow); + } + for (i = 28; i < 64; i++) + { + IO_MUX_SetPinOutLevelInSleep(i, IO_MUX_SleepPinLevelLow); + } + + /* Set RF_CNTL 0-3 output low level in sleep mode. */ + for (i = 0; i < 4; i++) + { + IO_MUX_SetRfPinOutLevelInSleep(i, IO_MUX_SleepPinLevelLow); + } +} + +void BOARD_DeinitFlash(FLEXSPI_Type * base) +{ + /* Enable FLEXSPI clock again */ + CLKCTL0->PSCCTL0_SET = CLKCTL0_PSCCTL0_SET_FLEXSPI0_MASK; + + /* Enable FLEXSPI module */ + base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK; + + /* Wait until FLEXSPI is not busy */ + while (!((base->STS0 & FLEXSPI_STS0_ARBIDLE_MASK) && (base->STS0 & FLEXSPI_STS0_SEQIDLE_MASK))) + { + } + /* Disable module during the reset procedure */ + base->MCR0 |= FLEXSPI_MCR0_MDIS_MASK; +} + +void BOARD_InitFlash(FLEXSPI_Type * base) +{ + uint32_t status; + uint32_t lastStatus; + uint32_t retry; + + /* Loopback from DQS pad can maximize RD board flash speed. */ + if ((base->MCR0 & FLEXSPI_MCR0_RXCLKSRC_MASK) != FLEXSPI_MCR0_RXCLKSRC(1)) + { + base->MCR0 = (base->MCR0 & ~FLEXSPI_MCR0_RXCLKSRC_MASK) | FLEXSPI_MCR0_RXCLKSRC(1); + } + /* If serial root clock is >= 100 MHz, DLLEN set to 1, OVRDEN set to 0, then SLVDLYTARGET setting of 0x0 is + * recommended. */ + base->DLLCR[0] = 0x1U; + + /* Enable FLEXSPI module */ + base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK; + + base->MCR0 |= FLEXSPI_MCR0_SWRESET_MASK; + while (base->MCR0 & FLEXSPI_MCR0_SWRESET_MASK) + { + } + + /* Need to wait DLL locked if DLL enabled */ + if (0U != (base->DLLCR[0] & FLEXSPI_DLLCR_DLLEN_MASK)) + { + lastStatus = base->STS2; + retry = BOARD_FLEXSPI_DLL_LOCK_RETRY; + /* Wait slave delay line locked and slave reference delay line locked. */ + do + { + status = base->STS2; + if ((status & (FLEXSPI_STS2_AREFLOCK_MASK | FLEXSPI_STS2_ASLVLOCK_MASK)) == + (FLEXSPI_STS2_AREFLOCK_MASK | FLEXSPI_STS2_ASLVLOCK_MASK)) + { + /* Locked */ + retry = 100; + break; + } + else if (status == lastStatus) + { + /* Same delay cell number in calibration */ + retry--; + } + else + { + retry = BOARD_FLEXSPI_DLL_LOCK_RETRY; + lastStatus = status; + } + } while (retry > 0); + /* According to ERR011377, need to delay at least 100 NOPs to ensure the DLL is locked. */ + for (; retry > 0U; retry--) + { + __NOP(); + } + } +} + +/* BOARD_SetFlexspiClock run in RAM used to configure FlexSPI clock source and divider when XIP. */ +void BOARD_SetFlexspiClock(FLEXSPI_Type * base, uint32_t src, uint32_t divider) +{ + if ((CLKCTL0->FLEXSPIFCLKSEL != CLKCTL0_FLEXSPIFCLKSEL_SEL(src)) || + ((CLKCTL0->FLEXSPIFCLKDIV & CLKCTL0_FLEXSPIFCLKDIV_DIV_MASK) != (divider - 1))) + { + /* Always deinit FLEXSPI and init FLEXSPI for the flash to make sure the flash works correctly after the + FLEXSPI root clock changed as the default FLEXSPI configuration may does not work for the new root clock + frequency. */ + BOARD_DeinitFlash(base); + + /* Disable clock before changing clock source */ + CLKCTL0->PSCCTL0_CLR = CLKCTL0_PSCCTL0_CLR_FLEXSPI0_MASK; + /* Update flexspi clock. */ + CLKCTL0->FLEXSPIFCLKSEL = CLKCTL0_FLEXSPIFCLKSEL_SEL(src); + CLKCTL0->FLEXSPIFCLKDIV |= CLKCTL0_FLEXSPIFCLKDIV_RESET_MASK; /* Reset the divider counter */ + CLKCTL0->FLEXSPIFCLKDIV = CLKCTL0_FLEXSPIFCLKDIV_DIV(divider - 1); + while ((CLKCTL0->FLEXSPIFCLKDIV) & CLKCTL0_FLEXSPIFCLKDIV_REQFLAG_MASK) + { + } + /* Enable FLEXSPI clock again */ + CLKCTL0->PSCCTL0_SET = CLKCTL0_PSCCTL0_SET_FLEXSPI0_MASK; + + BOARD_InitFlash(base); + } +} + +/* This function is used to change FlexSPI clock to a stable source before clock sources(Such as PLL and Main clock) + * updating in case XIP(execute code on FLEXSPI memory.) */ +void BOARD_FlexspiClockSafeConfig(void) +{ + /* Move FLEXSPI clock source to T3 256m / 2 to avoid instruction/data fetch issue in XIP when + * updating PLL and main clock. + */ + BOARD_SetFlexspiClock(FLEXSPI, 6U, 2U); +} + +void BOARD_CLIAttachClk(void) +{ + /* attach FRG3 clock to FLEXCOMM3 (debug console) */ + CLOCK_SetFRGClock(BOARD_CLI_FRG_CLK); + CLOCK_AttachClk(BOARD_CLI_CLK_ATTACH); +} diff --git a/examples/platform/nxp/rt/rw61x/board/board.h b/examples/platform/nxp/rt/rw61x/board/board.h new file mode 100644 index 00000000000000..d24ffc3c347dbe --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/board/board.h @@ -0,0 +1,173 @@ +/* + * Copyright 2021-2023 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +#include "clock_config.h" +#include "fsl_common.h" +#include "fsl_gpio.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/*! @brief The board name */ +#define BOARD_NAME "RD-RW61X-BGA" + +#ifndef DEBUG_CONSOLE_UART_INDEX +#define DEBUG_CONSOLE_UART_INDEX 3 +#endif + +/*! @brief Macro to judge XIP */ +#define BOARD_IS_XIP() \ + ((((uint32_t) BOARD_InitDebugConsole >= 0x08000000U) && ((uint32_t) BOARD_InitDebugConsole < 0x10000000U)) || \ + (((uint32_t) BOARD_InitDebugConsole >= 0x18000000U) && ((uint32_t) BOARD_InitDebugConsole < 0x20000000U))) + +/*! @brief The UART to use for debug messages. */ +#define BOARD_DEBUG_UART_TYPE kSerialPort_Uart +#if DEBUG_CONSOLE_UART_INDEX == 0 +#define BOARD_DEBUG_UART_BASEADDR (uint32_t) FLEXCOMM0 +#define BOARD_DEBUG_UART_INSTANCE 0U +#define BOARD_DEBUG_UART USART0 +#define BOARD_DEBUG_UART_CLK_FREQ CLOCK_GetFlexCommClkFreq(0) +#define BOARD_DEBUG_UART_FRG_CLK \ + (&(const clock_frg_clk_config_t){ 0, kCLOCK_FrgPllDiv, 255, 0 }) /*!< Select FRG0 mux as frg_pll \ + */ +#define BOARD_DEBUG_UART_CLK_ATTACH kFRG_to_FLEXCOMM0 +#define BOARD_DEBUG_UART_RST kFC0_RST_SHIFT_RSTn +#define BOARD_DEBUG_UART_CLKSRC kCLOCK_Flexcomm0 +#define BOARD_UART_IRQ_HANDLER FLEXCOMM0_IRQHandler +#define BOARD_UART_IRQ FLEXCOMM0_IRQn +#elif DEBUG_CONSOLE_UART_INDEX == 3 +#define BOARD_DEBUG_UART_BASEADDR (uint32_t) FLEXCOMM3 +#define BOARD_DEBUG_UART_INSTANCE 3U +#define BOARD_DEBUG_UART USART3 +#define BOARD_DEBUG_UART_CLK_FREQ CLOCK_GetFlexCommClkFreq(3) +#define BOARD_DEBUG_UART_FRG_CLK \ + (&(const clock_frg_clk_config_t){ 3, kCLOCK_FrgPllDiv, 255, 0 }) /*!< Select FRG3 mux as frg_pll \ + */ +#define BOARD_DEBUG_UART_CLK_ATTACH kFRG_to_FLEXCOMM3 +#define BOARD_DEBUG_UART_RST kFC3_RST_SHIFT_RSTn +#define BOARD_DEBUG_UART_CLKSRC kCLOCK_Flexcomm3 +#define BOARD_UART_IRQ_HANDLER FLEXCOMM3_IRQHandler +#define BOARD_UART_IRQ FLEXCOMM3_IRQn +#else +#error "UART not supported" +#endif + +#ifndef BOARD_DEBUG_UART_BAUDRATE +#define BOARD_DEBUG_UART_BAUDRATE 115200 +#endif /* BOARD_DEBUG_UART_BAUDRATE */ + +#define BOARD_FLEXSPI_PSRAM FLEXSPI +#ifndef BOARD_ENABLE_PSRAM_CACHE +#define BOARD_ENABLE_PSRAM_CACHE 1 +#endif + +/* Board I2C for codec */ +#define BOARD_CODEC_I2C_BASEADDR I2C2 +#define BOARD_CODEC_I2C_CLOCK_FREQ CLOCK_GetFlexCommClkFreq(2U) +#define BOARD_CODEC_I2C_INSTANCE 2 +#define BOARD_CODEC_I2C_SDA_PORT 0 +#define BOARD_CODEC_I2C_SCL_PORT 0 +#define BOARD_CODEC_I2C_SDA_PIN 16 +#define BOARD_CODEC_I2C_SCL_PIN 17 + +/* Board led color mapping */ +#define LOGIC_LED_ON 1U +#define LOGIC_LED_OFF 0U + +/* A fake led on GPIO header */ +#ifndef BOARD_LED_BLUE_GPIO +#define BOARD_LED_BLUE_GPIO GPIO +#endif +#define BOARD_LED_BLUE_GPIO_PORT 0U +#ifndef BOARD_LED_BLUE_GPIO_PIN +#define BOARD_LED_BLUE_GPIO_PIN 2U +#endif + +#define LED_BLUE_INIT(output) \ + GPIO_PinInit(BOARD_LED_BLUE_GPIO, BOARD_LED_BLUE_GPIO_PORT, BOARD_LED_BLUE_GPIO_PIN, \ + &(gpio_pin_config_t){ kGPIO_DigitalOutput, (output) }) /*!< Enable target LED_BLUE */ +#define LED_BLUE_ON() \ + GPIO_PortSet(BOARD_LED_BLUE_GPIO, BOARD_LED_BLUE_GPIO_PORT, 1U << BOARD_LED_BLUE_GPIO_PIN) /*!< Turn on target LED_BLUE */ +#define LED_BLUE_OFF() \ + GPIO_PortClear(BOARD_LED_BLUE_GPIO, BOARD_LED_BLUE_GPIO_PORT, 1U << BOARD_LED_BLUE_GPIO_PIN) /*!< Turn off target LED_BLUE */ +#define LED_BLUE_TOGGLE() \ + GPIO_PortToggle(BOARD_LED_BLUE_GPIO, BOARD_LED_BLUE_GPIO_PORT, 1U << BOARD_LED_BLUE_GPIO_PIN) /*!< Toggle on target LED_BLUE \ + */ + +/* Board SW PIN */ +#ifndef BOARD_SW1_GPIO +#define BOARD_SW1_GPIO GPIO +#endif +#define BOARD_SW1_GPIO_PORT 0U +#ifndef BOARD_SW1_GPIO_PIN +#define BOARD_SW1_GPIO_PIN 13U +#endif + +#ifndef BOARD_SW2_GPIO +#define BOARD_SW2_GPIO GPIO +#endif +#define BOARD_SW2_GPIO_PORT 0U +#ifndef BOARD_SW2_GPIO_PIN +#define BOARD_SW2_GPIO_PIN 14U +#endif + +#ifndef BOARD_SW3_GPIO +#define BOARD_SW3_GPIO GPIO +#endif +#define BOARD_SW3_GPIO_PORT 0U +#ifndef BOARD_SW3_GPIO_PIN +#define BOARD_SW3_GPIO_PIN 24U +#endif + +#ifndef BOARD_SW4_GPIO +#define BOARD_SW4_GPIO GPIO +#endif +#define BOARD_SW4_GPIO_PORT 0U +#ifndef BOARD_SW4_GPIO_PIN +#define BOARD_SW4_GPIO_PIN 25U +#endif + +#define BOARD_ENET0_PHY_ADDRESS (0x02U) + +/*! @brief The USIM SMARTCARD PHY configuration. */ +#define BOARD_SMARTCARD_MODULE (USIM) /*!< SMARTCARD communicational module instance */ +#define BOARD_SMARTCARD_MODULE_IRQ (USIM_IRQn) /*!< SMARTCARD communicational module IRQ handler */ +#define BOARD_SMARTCARD_CLOCK_MODULE_CLK_FREQ (CLOCK_GetUsimClkFreq()) +#define BOARD_SMARTCARD_CLOCK_VALUE (4000000U) /*!< SMARTCARD clock frequency (4Mhz) */ +#define BOARD_SMARTCARD_IRQ_PORT (0) +#define BOARD_SMARTCARD_IRQ_PIN (19) +#define BOARD_SMARTCARD_TS_TIMER_IRQ (CTIMER0_IRQn) + +/* CLI clock config */ +#define BOARD_CLI_FRG_CLK (&(const clock_frg_clk_config_t){ 3, kCLOCK_FrgPllDiv, 255, 0 }) /*!< Select FRG3 mux as frg_pll */ +#define BOARD_CLI_CLK_ATTACH kFRG_to_FLEXCOMM3 + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus */ + +/******************************************************************************* + * API + ******************************************************************************/ + +void BOARD_InitDebugConsole(void); +status_t BOARD_InitPsRam(void); +void BOARD_InitSleepPinConfig(void); +void BOARD_FlexspiClockSafeConfig(void); +void BOARD_CLIAttachClk(void); +AT_QUICKACCESS_SECTION_CODE(void BOARD_SetFlexspiClock(FLEXSPI_Type * base, uint32_t src, uint32_t divider)); +AT_QUICKACCESS_SECTION_CODE(void BOARD_DeinitFlash(FLEXSPI_Type * base)); +AT_QUICKACCESS_SECTION_CODE(void BOARD_InitFlash(FLEXSPI_Type * base)); + +#if defined(__cplusplus) +} +#endif /* __cplusplus */ + +#endif /* _BOARD_H_ */ diff --git a/examples/platform/nxp/rt/rw61x/board/clock_config.c b/examples/platform/nxp/rt/rw61x/board/clock_config.c new file mode 100644 index 00000000000000..5713fa2a9eeb03 --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/board/clock_config.c @@ -0,0 +1,254 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "clock_config.h" +#include "board.h" +#include "fsl_clock.h" +#include "fsl_power.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * Variables + ******************************************************************************/ +const clock_avpll_config_t g_avpllConfig_BOARD_BootClockRUN = { .ch1Freq = kCLOCK_AvPllChFreq12p288m, + .ch2Freq = kCLOCK_AvPllChFreq64m, + .enableCali = true }; + +/*FUNCTION********************************************************************** + * + * Function Name : BOARD_FlexspiClockSafeConfig + * Description : FLEXSPI clock source safe configuration weak function. + * Called before clock source(Such as PLL, Main clock) configuration. + * Note : Users need override this function to change FLEXSPI clock source to stable source when executing + * code on FLEXSPI memory(XIP). If XIP, the function should runs in RAM and move the FLEXSPI clock + *source to an stable clock to avoid instruction/data fetch issue during clock updating. + *END**************************************************************************/ +__attribute__((weak)) void BOARD_FlexspiClockSafeConfig(void) {} + +/*FUNCTION********************************************************************** + * + * Function Name : BOARD_SetFlexspiClock + * Description : This function should be overridden if executing code on FLEXSPI memory(XIP). + * To Change FLEXSPI clock, should move to run from RAM and then configure FLEXSPI clock source. + * After the clock is changed and stable, move back to run on FLEXSPI. + * Param base : FLEXSPI peripheral base address. + * Param src : FLEXSPI clock source. + * Param divider : FLEXSPI clock divider. + *END**************************************************************************/ +__attribute__((weak)) void BOARD_SetFlexspiClock(FLEXSPI_Type * base, uint32_t src, uint32_t divider) +{ + CLKCTL0->FLEXSPIFCLKSEL = CLKCTL0_FLEXSPIFCLKSEL_SEL(src); + CLKCTL0->FLEXSPIFCLKDIV |= CLKCTL0_FLEXSPIFCLKDIV_RESET_MASK; /* Reset the divider counter */ + CLKCTL0->FLEXSPIFCLKDIV = CLKCTL0_FLEXSPIFCLKDIV_DIV(divider - 1); + while ((CLKCTL0->FLEXSPIFCLKDIV) & CLKCTL0_FLEXSPIFCLKDIV_REQFLAG_MASK) + { + } +} + +/******************************************************************************* + ************************ BOARD_InitBootClocks function ************************ + ******************************************************************************/ +void BOARD_InitBootClocks(void) +{ + BOARD_BootClockRUN(); +} + +/******************************************************************************* + ********************** Configuration BOARD_BootClockRUN *********************** + ******************************************************************************/ +/******************************************************************************* + * Variables for BOARD_BootClockRUN configuration + ******************************************************************************/ + +/******************************************************************************* + * Code for BOARD_BootClockRUN configuration + ******************************************************************************/ +void BOARD_BootClockRUN(void) +{ + if ((PMU->CAU_SLP_CTRL & PMU_CAU_SLP_CTRL_SOC_SLP_RDY_MASK) == 0U) + { + /* LPOSC not enabled, enable it */ + CLOCK_EnableClock(kCLOCK_RefClkCauSlp); + } + if ((SYSCTL2->SOURCE_CLK_GATE & SYSCTL2_SOURCE_CLK_GATE_REFCLK_SYS_CG_MASK) != 0U) + { + /* REFCLK_SYS not enabled, enable it */ + CLOCK_EnableClock(kCLOCK_RefClkSys); + } + + /* Initialize T3 clocks and t3pll_mci_48_60m_irc configured to 48.3MHz */ + CLOCK_InitT3RefClk(kCLOCK_T3MciIrc48m); + /* Enable FFRO */ + CLOCK_EnableClock(kCLOCK_T3PllMciIrcClk); + /* Enable T3 256M clock and SFRO */ + CLOCK_EnableClock(kCLOCK_T3PllMci256mClk); + + if (BOARD_IS_XIP()) + { + /* Call function BOARD_FlexspiClockSafeConfig() to move FlexSPI clock to a stable clock source to avoid + instruction/data fetch issue when updating PLL and Main clock if XIP(execute code on FLEXSPI memory). */ + BOARD_FlexspiClockSafeConfig(); + } + + /* First let M33 run on SOSC */ + CLOCK_AttachClk(kSYSOSC_to_MAIN_CLK); + CLOCK_SetClkDiv(kCLOCK_DivSysCpuAhbClk, 1); + + /* tcpu_mci_clk configured to 260MHz, tcpu_mci_flexspi_clk 312MHz. */ + CLOCK_InitTcpuRefClk(3120000000UL, kCLOCK_TcpuFlexspiDiv10); + /* Enable tcpu_mci_clk 260MHz. Keep tcpu_mci_flexspi_clk gated. */ + CLOCK_EnableClock(kCLOCK_TcpuMciClk); + + /* tddr_mci_flexspi_clk 320MHz */ + CLOCK_InitTddrRefClk(kCLOCK_TddrFlexspiDiv10); + CLOCK_EnableClock(kCLOCK_TddrMciFlexspiClk); /* 320MHz */ + + /* Enable AUX0 PLL to 260MHz. */ + CLOCK_SetClkDiv(kCLOCK_DivAux0PllClk, 1U); + + /* Init AVPLL and enable both channels. */ + CLOCK_InitAvPll(&g_avpllConfig_BOARD_BootClockRUN); + CLOCK_SetClkDiv(kCLOCK_DivAudioPllClk, 1U); + + /* Configure MainPll to 260MHz, then let CM33 run on Main PLL. */ + CLOCK_SetClkDiv(kCLOCK_DivSysCpuAhbClk, 1U); + CLOCK_SetClkDiv(kCLOCK_DivMainPllClk, 1U); + CLOCK_AttachClk(kMAIN_PLL_to_MAIN_CLK); + + /* Set SYSTICKFCLKDIV divider to value 1 */ + CLOCK_SetClkDiv(kCLOCK_DivSystickClk, 1U); + CLOCK_AttachClk(kSYSTICK_DIV_to_SYSTICK_CLK); + + if (BOARD_IS_XIP()) + { + /* Call function BOARD_SetFlexspiClock() to set clock source to aux0_pll_clk. */ + BOARD_SetFlexspiClock(FLEXSPI, 2U, 2U); + } + + /* Set PLL FRG clock to 20MHz. */ + CLOCK_SetClkDiv(kCLOCK_DivPllFrgClk, 13U); + + /* Measure main_clk on CLKOUT. Set CLKOUTFCLKDIV divider to value 100 */ + CLOCK_AttachClk(kMAIN_CLK_to_CLKOUT); + SOCCTRL->TST_TSTBUS_CTRL2 = + (SOCCTRL->TST_TSTBUS_CTRL2 & ~(SOCCIU_TST_TSTBUS_CTRL2_CLK_OUT_PAGE_SEL_MASK | SOCCIU_TST_TSTBUS_CTRL2_CLK_OUT_SEL_MASK)) | + SOCCIU_TST_TSTBUS_CTRL2_CLK_OUT_PAGE_SEL(3) | SOCCIU_TST_TSTBUS_CTRL2_CLK_OUT_SEL(14); + CLOCK_SetClkDiv(kCLOCK_DivClockOut, 100U); + + /* Set SystemCoreClock variable. */ + SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK; +} + +/******************************************************************************* + ********************** Configuration BOARD_BootClockLPR *********************** + ******************************************************************************/ +/******************************************************************************* + * Variables for BOARD_BootClockLPR configuration + ******************************************************************************/ + +/******************************************************************************* + * Code for BOARD_BootClockLPR configuration + ******************************************************************************/ +void BOARD_BootClockLPR(void) +{ + CLOCK_DisableClock(kCLOCK_Pkc); + CLOCK_DisableClock(kCLOCK_Els); + CLOCK_DisableClock(kCLOCK_ElsApb); + CLOCK_DisableClock(kCLOCK_Otp); + CLOCK_DisableClock(kCLOCK_Wwdt0); + CLOCK_DisableClock(kCLOCK_Flexcomm0); + CLOCK_DisableClock(kCLOCK_Flexcomm2); + CLOCK_DisableClock(kCLOCK_Flexcomm3); + CLOCK_DisableClock(kCLOCK_Crc); + CLOCK_DisableClock(kCLOCK_Itrc); + + RESET_SetPeripheralReset(kPKC_RST_SHIFT_RSTn); + // RESET_SetPeripheralReset(kELS_RST_SHIFT_RSTn); + RESET_SetPeripheralReset(kELS_APB_RST_SHIFT_RSTn); + RESET_SetPeripheralReset(kELS_GDET_REF_RST_SHIFT_RSTn); + RESET_SetPeripheralReset(kOTP_RST_SHIFT_RSTn); + RESET_SetPeripheralReset(kWWDT_RST_SHIFT_RSTn); + RESET_SetPeripheralReset(kFC0_RST_SHIFT_RSTn); + RESET_SetPeripheralReset(kFC2_RST_SHIFT_RSTn); + RESET_SetPeripheralReset(kFC3_RST_SHIFT_RSTn); + RESET_SetPeripheralReset(kCRC_RST_SHIFT_RSTn); + + if ((PMU->CAU_SLP_CTRL & PMU_CAU_SLP_CTRL_SOC_SLP_RDY_MASK) == 0U) + { + /* LPOSC not enabled, enable it */ + CLOCK_EnableClock(kCLOCK_RefClkCauSlp); + } + if ((SYSCTL2->SOURCE_CLK_GATE & SYSCTL2_SOURCE_CLK_GATE_REFCLK_SYS_CG_MASK) != 0U) + { + /* REFCLK_SYS not enabled, enable it */ + CLOCK_EnableClock(kCLOCK_RefClkSys); + } + + if (BOARD_IS_XIP()) + { + /* Initialize T3 clocks and t3pll_mci_48_60m_irc configured to 48.3MHz */ + CLOCK_InitT3RefClk(kCLOCK_T3MciIrc48m); + /* Enable T3 256M clock and SFRO */ + CLOCK_EnableClock(kCLOCK_T3PllMci256mClk); + + /* Call function BOARD_FlexspiClockSafeConfig() to move FlexSPI clock to a stable clock source to avoid + instruction/data fetch issue when updating PLL and Main clock if XIP(execute code on FLEXSPI memory). */ + BOARD_FlexspiClockSafeConfig(); + } + else + { + RESET_ClearPeripheralReset(kFLEXSPI_RST_SHIFT_RSTn); + BOARD_DeinitFlash(FLEXSPI); + CLOCK_AttachClk(kNONE_to_FLEXSPI_CLK); + CLOCK_DisableClock(kCLOCK_Flexspi); + RESET_SetPeripheralReset(kFLEXSPI_RST_SHIFT_RSTn); + } + + /* Deinitialize TDDR clocks */ + CLOCK_DeinitTddrRefClk(); + + /* First let M33 run on SOSC */ + CLOCK_AttachClk(kSYSOSC_to_MAIN_CLK); + CLOCK_SetClkDiv(kCLOCK_DivSysCpuAhbClk, 1); + + /* tcpu_mci_clk configured to 260MHz, tcpu_mci_flexspi_clk 312MHz. */ + CLOCK_InitTcpuRefClk(3120000000UL, kCLOCK_TcpuFlexspiDiv10); + /* Enable tcpu_mci_clk 260MHz. Keep tcpu_mci_flexspi_clk gated. */ + CLOCK_EnableClock(kCLOCK_TcpuMciClk); + + /* Enable AUX0 PLL to 260MHz. */ + CLOCK_SetClkDiv(kCLOCK_DivAux0PllClk, 1U); + + /* Configure MainPll to 260MHz, then let CM33 run on Main PLL. */ + CLOCK_SetClkDiv(kCLOCK_DivSysCpuAhbClk, 1U); + CLOCK_SetClkDiv(kCLOCK_DivMainPllClk, 1U); + CLOCK_AttachClk(kMAIN_PLL_to_MAIN_CLK); + + /* Set SYSTICKFCLKDIV divider to value 1 */ + CLOCK_SetClkDiv(kCLOCK_DivSystickClk, 1U); + CLOCK_AttachClk(kSYSTICK_DIV_to_SYSTICK_CLK); + + if (BOARD_IS_XIP()) + { + /* Call function BOARD_SetFlexspiClock() to set clock source to aux0_pll_clk. */ + BOARD_SetFlexspiClock(FLEXSPI, 2U, 2U); + } + + /* Set PLL FRG clock to 20MHz. */ + CLOCK_SetClkDiv(kCLOCK_DivPllFrgClk, 13U); + + /* Deinitialize T3 clocks */ + CLOCK_DeinitT3RefClk(); + + /* Deinitialize AVPLL clocks */ + CLOCK_DeinitAvPll(); + + /* Set SystemCoreClock variable. */ + SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK; +} diff --git a/examples/platform/nxp/rt/rw61x/board/clock_config.h b/examples/platform/nxp/rt/rw61x/board/clock_config.h new file mode 100644 index 00000000000000..e5ecfed533844d --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/board/clock_config.h @@ -0,0 +1,65 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CLOCK_CONFIG_H_ +#define _CLOCK_CONFIG_H_ + +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + ************************ BOARD_InitBootClocks function ************************ + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes default configuration of clocks. + * + */ +void BOARD_InitBootClocks(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ********************** Configuration BOARD_BootClockRUN *********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockRUN configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKRUN_CORE_CLOCK 260000000U /*!< Core clock frequency: 260000000Hz */ + +/******************************************************************************* + * API for BOARD_BootClockRUN configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockRUN(void); + +/*! + * @brief This function executes configuration of clocks for low power run. + * + */ +void BOARD_BootClockLPR(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +#endif /* _CLOCK_CONFIG_H_ */ diff --git a/examples/platform/nxp/rt/rw61x/board/hardware_init.c b/examples/platform/nxp/rt/rw61x/board/hardware_init.c new file mode 100644 index 00000000000000..1d7963d6ddb7e1 --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/board/hardware_init.c @@ -0,0 +1,33 @@ +/* + * Copyright 2020, 2023 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*${header:start}*/ +#include "board.h" +#include "clock_config.h" +#include "fsl_device_registers.h" +#include "pin_mux.h" +/*${header:end}*/ + +static gpio_pin_config_t pinConfig = { + kGPIO_DigitalOutput, + 0, +}; + +/*${function:start}*/ +void BOARD_InitHardware(void) +{ + BOARD_InitBootPins(); + BOARD_InitBootClocks(); + BOARD_InitDebugConsole(); + + CLOCK_EnableClock(kCLOCK_Flexspi); + RESET_ClearPeripheralReset(kFLEXSPI_RST_SHIFT_RSTn); + + /* Use aux0_pll_clk / 2 */ + BOARD_SetFlexspiClock(FLEXSPI, 2U, 2U); +} +/*${function:end}*/ diff --git a/examples/platform/nxp/rt/rw61x/board/peripherals.c b/examples/platform/nxp/rt/rw61x/board/peripherals.c new file mode 100644 index 00000000000000..5fc55eee46fdc4 --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/board/peripherals.c @@ -0,0 +1,149 @@ +/*********************************************************************************************************************** + * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ + +/* clang-format off */ +/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!GlobalInfo +product: Peripherals v11.0 +processor: MIMXRT1062xxxxA +package_id: MIMXRT1062DVL6A +mcu_data: ksdk2_0 +processor_version: 11.0.1 +board: MIMXRT1060-EVKB +functionalGroups: +- name: BOARD_InitPeripherals + UUID: 96c1cec6-3bd3-47a2-8301-f38e4b0dd25f + called_from_default_init: true + selectedCore: core0 + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ + +/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +component: +- type: 'system' +- type_id: 'system' +- global_system_definitions: + - user_definitions: 'extern uint32_t NV_STORAGE_START_ADDRESS_OFFSET[];\nextern uint32_t NV_STORAGE_MAX_SECTORS[];\n\n\n#define LITTLEFS_START_ADDR (uint32_t)(NV_STORAGE_START_ADDRESS_OFFSET)\n' + - user_includes: '\n' + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ + +/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +component: +- type: 'uart_cmsis_common' +- type_id: 'uart_cmsis_common_9cb8e302497aa696fdbb5a4fd622c2a8' +- global_USART_CMSIS_common: + - quick_selection: 'default' + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ + +/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +component: +- type: 'gpio_adapter_common' +- type_id: 'gpio_adapter_common_57579b9ac814fe26bf95df0a384c36b6' +- global_gpio_adapter_common: + - quick_selection: 'default' + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ +/* clang-format on */ + +/*********************************************************************************************************************** + * Included files + **********************************************************************************************************************/ +#include "peripherals.h" + +/*********************************************************************************************************************** + * BOARD_InitPeripherals functional group + **********************************************************************************************************************/ +/*********************************************************************************************************************** + * LittleFS initialization code + **********************************************************************************************************************/ +/* clang-format off */ +/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +instance: +- name: 'LittleFS' +- type: 'littlefs' +- mode: 'general' +- custom_name_enabled: 'false' +- type_id: 'littlefs_7e89bf6c938031bfd17176a3aacf1bc3' +- functional_group: 'BOARD_InitPeripherals' +- config_sets: + - general_config: + - moduleInclude: 'fwk_platform_flash.h' + - lfsConfig: + - enableUserContext: 'true' + - userContext: + - contextVar: '(void*)&LittleFS_ctx' + - contextDef: 'extern struct lfs_mflash_ctx LittleFS_ctx;' + - userCallbacks: + - read: 'lfs_mflash_read' + - prog: 'lfs_mflash_prog' + - erase: 'lfs_mflash_erase' + - sync: 'lfs_mflash_sync' + - lock: 'lfs_mutex_lock' + - unlock: 'lfs_mutex_unlock' + - readSize: '16' + - progSize: '256' + - blockSize: '4096' + - firstBlock: '(uint32_t)(NV_STORAGE_START_ADDRESS_OFFSET)' + - blockCount: '(uint32_t)(NV_STORAGE_MAX_SECTORS)' + - blockCycles: '100' + - cacheSize: '256' + - lookaheadSize: '16' + - enableReadBuff: 'false' + - readBuffer: + - customBuffer: 'false' + - enableProgBuff: 'false' + - progBuffer: + - customBuffer: 'false' + - enableLookaheadBuff: 'false' + - lookaheadBuffer: + - customBuffer: 'false' + - enableOptionalSizes: 'false' + - optionalSizes: + - name_max: '255' + - file_max: '0x7FFFFFFF' + - attr_max: '1022' + - metadata_max: '4096' + - initLFS: 'false' + - initConfig: + - lfsObj: 'LittleFS_system' + - mountLFS: 'disable' + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ +/* clang-format on */ +/* LittleFS context */ +extern struct lfs_mflash_ctx LittleFS_ctx; +const struct lfs_config LittleFS_config = { .context = (void *) &LittleFS_ctx, + .read = lfs_mflash_read, + .prog = lfs_mflash_prog, + .erase = lfs_mflash_erase, + .sync = lfs_mflash_sync, +#ifdef LFS_THREADSAFE + .lock = lfs_mutex_lock, + .unlock = lfs_mutex_unlock, +#endif + .read_size = LITTLEFS_READ_SIZE, + .prog_size = LITTLEFS_PROG_SIZE, + .block_size = LITTLEFS_BLOCK_SIZE, + .block_count = LITTLEFS_BLOCK_COUNT, + .block_cycles = LITTLEFS_BLOCK_CYCLES, + .cache_size = LITTLEFS_CACHE_SIZE, + .lookahead_size = LITTLEFS_LOOKAHEAD_SIZE }; + +/* Empty initialization function (commented out) +static void LittleFS_init(void) { +} */ + +/*********************************************************************************************************************** + * Initialization functions + **********************************************************************************************************************/ +void BOARD_InitPeripherals(void) +{ + /* Initialize components */ +} + +/*********************************************************************************************************************** + * BOARD_InitBootPeripherals function + **********************************************************************************************************************/ +void BOARD_InitBootPeripherals(void) +{ + BOARD_InitPeripherals(); +} diff --git a/examples/platform/nxp/rt/rw61x/board/peripherals.h b/examples/platform/nxp/rt/rw61x/board/peripherals.h new file mode 100644 index 00000000000000..6c50bc87364ccf --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/board/peripherals.h @@ -0,0 +1,102 @@ +/*********************************************************************************************************************** + * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ + +#ifndef _PERIPHERALS_H_ +#define _PERIPHERALS_H_ + +#define CHIP_PLAT_NO_NVM 0 +#define CHIP_PLAT_NVM_FWK 1 +#define CHIP_PLAT_LITTLEFS 2 +#define CHIP_PLAT_KEY_STORAGE 3 + +#ifndef CHIP_PLAT_NVM_SUPPORT +#define CHIP_PLAT_NVM_SUPPORT CHIP_PLAT_NO_NVM +#endif + +/*********************************************************************************************************************** + * Included files + **********************************************************************************************************************/ +#include "fsl_common.h" + +#if (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_NVM_FWK || CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_LITTLEFS) +#include "fwk_platform_flash.h" +#elif (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_KEY_STORAGE) +#include "fwk_lfs_mflash.h" +#endif + +#include "lfs.h" + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus */ + +/*********************************************************************************************************************** + * User definitions + **********************************************************************************************************************/ +extern uint32_t NV_STORAGE_START_ADDRESS_OFFSET[]; +extern uint32_t NV_STORAGE_MAX_SECTORS[]; + +#define LITTLEFS_START_ADDR (uint32_t)(NV_STORAGE_START_ADDRESS_OFFSET) + +/*********************************************************************************************************************** + * Definitions + **********************************************************************************************************************/ +/* Definitions for BOARD_InitPeripherals functional group */ +/* Maximum block read size definition */ +#define LITTLEFS_READ_SIZE 16 +/* Maximum block program size definition */ +#define LITTLEFS_PROG_SIZE 256 +/* Erasable block size definition */ +#define LITTLEFS_BLOCK_SIZE 4096 +/* Block count definition */ +#define LITTLEFS_BLOCK_COUNT (uint32_t)(NV_STORAGE_MAX_SECTORS) +/* Block cycles definition */ +#define LITTLEFS_BLOCK_CYCLES 100 +/* Minimum block cache size definition */ +#define LITTLEFS_CACHE_SIZE 256 +/* Minimum lookahead buffer size definition */ +#define LITTLEFS_LOOKAHEAD_SIZE 16 +/* Block starting address definition */ +#define LITTLEFS_START_ADDR (uint32_t)(NV_STORAGE_START_ADDRESS_OFFSET) + +/*********************************************************************************************************************** + * Global variables + **********************************************************************************************************************/ +/* LittleFS configuration */ +extern const struct lfs_config LittleFS_config; + +/*********************************************************************************************************************** + * Callback functions + **********************************************************************************************************************/ +/* LittleFS read a block region callback*/ +extern int lfs_mflash_read(const struct lfs_config *, lfs_block_t, lfs_off_t, void *, lfs_size_t); +/* LittleFS program a block region callback*/ +extern int lfs_mflash_prog(const struct lfs_config *, lfs_block_t, lfs_off_t, const void *, lfs_size_t); +/* LittleFS erase a block callback*/ +extern int lfs_mflash_erase(const struct lfs_config *, lfs_block_t); +/* LittleFS state sync callback*/ +extern int lfs_mflash_sync(const struct lfs_config *); +/* LittleFS state lock callback*/ +extern int lfs_mutex_lock(const struct lfs_config *); +/* LittleFS state unlock callback*/ +extern int lfs_mutex_unlock(const struct lfs_config *); + +/*********************************************************************************************************************** + * Initialization functions + **********************************************************************************************************************/ + +void BOARD_InitPeripherals(void); + +/*********************************************************************************************************************** + * BOARD_InitBootPeripherals function + **********************************************************************************************************************/ + +void BOARD_InitBootPeripherals(void); + +#if defined(__cplusplus) +} +#endif + +#endif /* _PERIPHERALS_H_ */ diff --git a/examples/platform/nxp/rt/rw61x/board/pin_mux.c b/examples/platform/nxp/rt/rw61x/board/pin_mux.c new file mode 100644 index 00000000000000..8ab48ff62e8d0f --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/board/pin_mux.c @@ -0,0 +1,39 @@ +/* + * Copyright 2021, 2023 NXP. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "pin_mux.h" +#include "fsl_common.h" +#include "fsl_io_mux.h" + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitBootPins + * Description : Calls initialization functions. + * + * END ****************************************************************************************************************/ +void BOARD_InitBootPins(void) +{ + BOARD_InitPins(); +} + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +void BOARD_InitPins(void) +{ /*!< Function assigned for the core: Cortex-M33[cm33] */ + IO_MUX_SetPinMux(IO_MUX_FC3_USART_DATA); + IO_MUX_SetPinMux(IO_MUX_GPIO25); + /* FLEXCOMM0 TX for logging*/ + IO_MUX_SetPinMux(IO_MUX_FC0_USART_DATA); +} + +/*********************************************************************************************************************** + * EOF + **********************************************************************************************************************/ diff --git a/examples/platform/nxp/rt/rw61x/board/pin_mux.h b/examples/platform/nxp/rt/rw61x/board/pin_mux.h new file mode 100644 index 00000000000000..d01bc202b03184 --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/board/pin_mux.h @@ -0,0 +1,51 @@ +/* + * Copyright 2021 NXP. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _PIN_MUX_H_ +#define _PIN_MUX_H_ + +/*********************************************************************************************************************** + * Definitions + **********************************************************************************************************************/ + +/*! + * @addtogroup pin_mux + * @{ + */ + +/*********************************************************************************************************************** + * API + **********************************************************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @brief Calls initialization functions. + * + */ +void BOARD_InitBootPins(void); + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitPins(void); /*!< Function assigned for the core: Cortex-M4[cm4] */ + +#if defined(__cplusplus) +} +#endif + +/*! + * @} + */ +#endif /* _PIN_MUX_H_ */ + +/*********************************************************************************************************************** + * EOF + **********************************************************************************************************************/ diff --git a/examples/platform/nxp/rt/rw61x/doc/images/mcu-set.PNG b/examples/platform/nxp/rt/rw61x/doc/images/mcu-set.PNG new file mode 100644 index 0000000000000000000000000000000000000000..1904593a66a8a4bdce86e22c20665289e05937d8 GIT binary patch literal 153442 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%0A?sTw^(Eg%=u!QD{%14#vmaQ_ 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
%9owS2geUBHJ`<_i2>yJ@cJ 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%0DK@A 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 literal 0 HcmV?d00001 diff --git a/examples/platform/nxp/rt/rw61x/doc/images/mcuboot_demo.PNG b/examples/platform/nxp/rt/rw61x/doc/images/mcuboot_demo.PNG new file mode 100644 index 0000000000000000000000000000000000000000..c22b1c772b7c41ee59e6522fcac4c5e2d0e9288e GIT binary patch literal 84377 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

u-Im-Jf+ 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 literal 0 HcmV?d00001 diff --git a/examples/platform/nxp/rt/rw61x/doc/images/mcuboot_monolithic_app.PNG b/examples/platform/nxp/rt/rw61x/doc/images/mcuboot_monolithic_app.PNG new file mode 100644 index 0000000000000000000000000000000000000000..8c9953c4a2c76290818c265d46d7439ee3c70206 GIT binary patch literal 122627 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�^S)OXieWzO33AFYRg1LtUEtPQ_xszsn4kXbZ>b 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%0A5BZ_ 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.y@JqGhzIs0l!@cOUHiLsD@(|q0!pgu)i9{ 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 OQ;=1W$+`Z(<9`4wcXuoR literal 0 HcmV?d00001 diff --git a/examples/platform/nxp/rt/rw61x/doc/images/mcux-sdk-download.PNG b/examples/platform/nxp/rt/rw61x/doc/images/mcux-sdk-download.PNG new file mode 100644 index 0000000000000000000000000000000000000000..c6afd18b6beb0b4de9655ee0d5e920dfb53ea294 GIT binary patch literal 110232 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

~xmlG23>WU6;JnEqD)@091Vq&BzzKqyWh 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%0D@`yclHz}234pfL!&RuOadpn@4WkeoyG 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

cq2UV^&S?gCK|IE0a)aaC&#s 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 literal 0 HcmV?d00001 diff --git a/examples/thermostat/nxp/zap/BUILD.gn b/examples/thermostat/nxp/zap/BUILD.gn new file mode 100644 index 00000000000000..976cd78f2e1a79 --- /dev/null +++ b/examples/thermostat/nxp/zap/BUILD.gn @@ -0,0 +1,34 @@ +# 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/chip.gni") + +import("${chip_root}/src/app/chip_data_model.gni") + +import("${chip_root}/src/platform/device.gni") + +chip_data_model("zap") { + if (chip_enable_wifi) { + # zap config for matter-over-wifi + zap_file = "thermostat_matter_wifi.zap" + } else { + # zap config for matter-over-thread + zap_file = "thermostat_matter_thread.zap" + } + + # Defining zap_pregenerated_dir is required by chip_data_model.gni in order to build IMClusterCommandHandler.cpp + zap_pregenerated_dir = "" + is_server = true +} diff --git a/examples/thermostat/nxp/zap/thermostat_matter_thread.matter b/examples/thermostat/nxp/zap/thermostat_matter_thread.matter new file mode 100644 index 00000000000000..08f30267c794a4 --- /dev/null +++ b/examples/thermostat/nxp/zap/thermostat_matter_thread.matter @@ -0,0 +1,2116 @@ +// This IDL was generated automatically by ZAP. +// It is for view/code review purposes only. + +/** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ +client cluster Identify = 3 { + enum EffectIdentifierEnum : ENUM8 { + kBlink = 0; + kBreathe = 1; + kOkay = 2; + kChannelChange = 11; + kFinishEffect = 254; + kStopEffect = 255; + } + + enum EffectVariantEnum : ENUM8 { + kDefault = 0; + } + + enum IdentifyTypeEnum : ENUM8 { + kNone = 0; + kLightOutput = 1; + kVisibleIndicator = 2; + kAudibleBeep = 3; + kDisplay = 4; + kActuator = 5; + } + + attribute int16u identifyTime = 0; + readonly attribute IdentifyTypeEnum identifyType = 1; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct IdentifyRequest { + INT16U identifyTime = 0; + } + + request struct TriggerEffectRequest { + EffectIdentifierEnum effectIdentifier = 0; + EffectVariantEnum effectVariant = 1; + } + + /** Command description for Identify */ + command access(invoke: manage) Identify(IdentifyRequest): DefaultSuccess = 0; + /** Command description for TriggerEffect */ + command access(invoke: manage) TriggerEffect(TriggerEffectRequest): DefaultSuccess = 64; +} + +/** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ +server cluster Identify = 3 { + enum EffectIdentifierEnum : ENUM8 { + kBlink = 0; + kBreathe = 1; + kOkay = 2; + kChannelChange = 11; + kFinishEffect = 254; + kStopEffect = 255; + } + + enum EffectVariantEnum : ENUM8 { + kDefault = 0; + } + + enum IdentifyTypeEnum : ENUM8 { + kNone = 0; + kLightOutput = 1; + kVisibleIndicator = 2; + kAudibleBeep = 3; + kDisplay = 4; + kActuator = 5; + } + + attribute int16u identifyTime = 0; + readonly attribute IdentifyTypeEnum identifyType = 1; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct IdentifyRequest { + INT16U identifyTime = 0; + } + + command access(invoke: manage) Identify(IdentifyRequest): DefaultSuccess = 0; +} + +/** Attributes and commands for group configuration and manipulation. */ +server cluster Groups = 4 { + bitmap Feature : BITMAP32 { + kGroupNames = 0x1; + } + + bitmap NameSupportBitmap : BITMAP8 { + kGroupNames = 0x80; + } + + readonly attribute NameSupportBitmap nameSupport = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct AddGroupRequest { + group_id groupID = 0; + CHAR_STRING groupName = 1; + } + + request struct ViewGroupRequest { + group_id groupID = 0; + } + + request struct GetGroupMembershipRequest { + group_id groupList[] = 0; + } + + request struct RemoveGroupRequest { + group_id groupID = 0; + } + + request struct AddGroupIfIdentifyingRequest { + group_id groupID = 0; + CHAR_STRING groupName = 1; + } + + response struct AddGroupResponse = 0 { + ENUM8 status = 0; + group_id groupID = 1; + } + + response struct ViewGroupResponse = 1 { + ENUM8 status = 0; + group_id groupID = 1; + CHAR_STRING groupName = 2; + } + + response struct GetGroupMembershipResponse = 2 { + nullable INT8U capacity = 0; + group_id groupList[] = 1; + } + + response struct RemoveGroupResponse = 3 { + ENUM8 status = 0; + group_id groupID = 1; + } + + fabric command access(invoke: manage) AddGroup(AddGroupRequest): AddGroupResponse = 0; + fabric command ViewGroup(ViewGroupRequest): ViewGroupResponse = 1; + fabric command GetGroupMembership(GetGroupMembershipRequest): GetGroupMembershipResponse = 2; + fabric command access(invoke: manage) RemoveGroup(RemoveGroupRequest): RemoveGroupResponse = 3; + fabric command access(invoke: manage) RemoveAllGroups(): DefaultSuccess = 4; + fabric command access(invoke: manage) AddGroupIfIdentifying(AddGroupIfIdentifyingRequest): DefaultSuccess = 5; +} + +/** Attributes and commands for scene configuration and manipulation. */ +server cluster Scenes = 5 { + bitmap Feature : BITMAP32 { + kSceneNames = 0x1; + kExplicit = 0x2; + kTableSize = 0x4; + kFabricScenes = 0x8; + } + + bitmap ScenesCopyMode : BITMAP8 { + kCopyAllScenes = 0x1; + } + + struct AttributeValuePair { + attrib_id attributeID = 0; + int32u attributeValue = 1; + } + + struct ExtensionFieldSet { + cluster_id clusterID = 0; + AttributeValuePair attributeValueList[] = 1; + } + + readonly attribute int8u sceneCount = 0; + readonly attribute int8u currentScene = 1; + readonly attribute group_id currentGroup = 2; + readonly attribute boolean sceneValid = 3; + readonly attribute bitmap8 nameSupport = 4; + readonly attribute int16u sceneTableSize = 6; + readonly attribute int8u remainingCapacity = 7; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct AddSceneRequest { + group_id groupID = 0; + INT8U sceneID = 1; + INT16U transitionTime = 2; + CHAR_STRING sceneName = 3; + ExtensionFieldSet extensionFieldSets[] = 4; + } + + request struct ViewSceneRequest { + group_id groupID = 0; + INT8U sceneID = 1; + } + + request struct RemoveSceneRequest { + group_id groupID = 0; + INT8U sceneID = 1; + } + + request struct RemoveAllScenesRequest { + group_id groupID = 0; + } + + request struct StoreSceneRequest { + group_id groupID = 0; + INT8U sceneID = 1; + } + + request struct RecallSceneRequest { + group_id groupID = 0; + INT8U sceneID = 1; + optional nullable INT16U transitionTime = 2; + } + + request struct GetSceneMembershipRequest { + group_id groupID = 0; + } + + response struct AddSceneResponse = 0 { + status status = 0; + group_id groupID = 1; + INT8U sceneID = 2; + } + + response struct ViewSceneResponse = 1 { + status status = 0; + group_id groupID = 1; + INT8U sceneID = 2; + optional INT16U transitionTime = 3; + optional CHAR_STRING sceneName = 4; + optional ExtensionFieldSet extensionFieldSets[] = 5; + } + + response struct RemoveSceneResponse = 2 { + status status = 0; + group_id groupID = 1; + INT8U sceneID = 2; + } + + response struct RemoveAllScenesResponse = 3 { + status status = 0; + group_id groupID = 1; + } + + response struct StoreSceneResponse = 4 { + status status = 0; + group_id groupID = 1; + INT8U sceneID = 2; + } + + response struct GetSceneMembershipResponse = 6 { + status status = 0; + nullable INT8U capacity = 1; + group_id groupID = 2; + optional INT8U sceneList[] = 3; + } + + fabric command access(invoke: manage) AddScene(AddSceneRequest): AddSceneResponse = 0; + fabric command ViewScene(ViewSceneRequest): ViewSceneResponse = 1; + fabric command access(invoke: manage) RemoveScene(RemoveSceneRequest): RemoveSceneResponse = 2; + fabric command access(invoke: manage) RemoveAllScenes(RemoveAllScenesRequest): RemoveAllScenesResponse = 3; + fabric command access(invoke: manage) StoreScene(StoreSceneRequest): StoreSceneResponse = 4; + fabric command RecallScene(RecallSceneRequest): DefaultSuccess = 5; + fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6; +} + +/** The Descriptor Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for describing a node, its endpoints and clusters. */ +server cluster Descriptor = 29 { + bitmap Feature : BITMAP32 { + kTagList = 0x1; + } + + struct DeviceTypeStruct { + devtype_id deviceType = 0; + int16u revision = 1; + } + + struct SemanticTagStruct { + nullable vendor_id mfgCode = 0; + enum8 namespaceID = 1; + enum8 tag = 2; + optional nullable char_string label = 3; + } + + readonly attribute DeviceTypeStruct deviceTypeList[] = 0; + readonly attribute CLUSTER_ID serverList[] = 1; + readonly attribute CLUSTER_ID clientList[] = 2; + readonly attribute ENDPOINT_NO partsList[] = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** The Binding Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for supporting the binding table. */ +server cluster Binding = 30 { + fabric_scoped struct TargetStruct { + optional node_id node = 1; + optional group_id group = 2; + optional endpoint_no endpoint = 3; + optional cluster_id cluster = 4; + fabric_idx fabricIndex = 254; + } + + attribute TargetStruct binding[] = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** The Access Control Cluster exposes a data model view of a + Node's Access Control List (ACL), which codifies the rules used to manage + and enforce Access Control for the Node's endpoints and their associated + cluster instances. */ +server cluster AccessControl = 31 { + enum AccessControlEntryAuthModeEnum : ENUM8 { + kPASE = 1; + kCASE = 2; + kGroup = 3; + } + + enum AccessControlEntryPrivilegeEnum : ENUM8 { + kView = 1; + kProxyView = 2; + kOperate = 3; + kManage = 4; + kAdminister = 5; + } + + enum ChangeTypeEnum : ENUM8 { + kChanged = 0; + kAdded = 1; + kRemoved = 2; + } + + struct AccessControlTargetStruct { + nullable cluster_id cluster = 0; + nullable endpoint_no endpoint = 1; + nullable devtype_id deviceType = 2; + } + + fabric_scoped struct AccessControlEntryStruct { + fabric_sensitive AccessControlEntryPrivilegeEnum privilege = 1; + fabric_sensitive AccessControlEntryAuthModeEnum authMode = 2; + nullable fabric_sensitive int64u subjects[] = 3; + nullable fabric_sensitive AccessControlTargetStruct targets[] = 4; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct AccessControlExtensionStruct { + fabric_sensitive octet_string<128> data = 1; + fabric_idx fabricIndex = 254; + } + + fabric_sensitive info event access(read: administer) AccessControlEntryChanged = 0 { + nullable node_id adminNodeID = 1; + nullable INT16U adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable AccessControlEntryStruct latestValue = 4; + fabric_idx fabricIndex = 254; + } + + fabric_sensitive info event access(read: administer) AccessControlExtensionChanged = 1 { + nullable node_id adminNodeID = 1; + nullable INT16U adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable AccessControlExtensionStruct latestValue = 4; + fabric_idx fabricIndex = 254; + } + + attribute access(read: administer, write: administer) AccessControlEntryStruct acl[] = 0; + attribute access(read: administer, write: administer) AccessControlExtensionStruct extension[] = 1; + readonly attribute int16u subjectsPerAccessControlEntry = 2; + readonly attribute int16u targetsPerAccessControlEntry = 3; + readonly attribute int16u accessControlEntriesPerFabric = 4; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** This cluster provides attributes and events for determining basic information about Nodes, which supports both + Commissioning and operational determination of Node characteristics, such as Vendor ID, Product ID and serial number, + which apply to the whole Node. Also allows setting user device information such as location. */ +server cluster BasicInformation = 40 { + enum ColorEnum : ENUM8 { + kBlack = 0; + kNavy = 1; + kGreen = 2; + kTeal = 3; + kMaroon = 4; + kPurple = 5; + kOlive = 6; + kGray = 7; + kBlue = 8; + kLime = 9; + kAqua = 10; + kRed = 11; + kFuchsia = 12; + kYellow = 13; + kWhite = 14; + kNickel = 15; + kChrome = 16; + kBrass = 17; + kCopper = 18; + kSilver = 19; + kGold = 20; + } + + enum ProductFinishEnum : ENUM8 { + kOther = 0; + kMatte = 1; + kSatin = 2; + kPolished = 3; + kRugged = 4; + kFabric = 5; + } + + struct CapabilityMinimaStruct { + int16u caseSessionsPerFabric = 0; + int16u subscriptionsPerFabric = 1; + } + + struct ProductAppearanceStruct { + ProductFinishEnum finish = 0; + nullable ColorEnum primaryColor = 1; + } + + critical event StartUp = 0 { + INT32U softwareVersion = 0; + } + + critical event ShutDown = 1 { + } + + info event Leave = 2 { + fabric_idx fabricIndex = 0; + } + + info event ReachableChanged = 3 { + boolean reachableNewValue = 0; + } + + readonly attribute int16u dataModelRevision = 0; + readonly attribute char_string<32> vendorName = 1; + readonly attribute vendor_id vendorID = 2; + readonly attribute char_string<32> productName = 3; + readonly attribute int16u productID = 4; + attribute access(write: manage) char_string<32> nodeLabel = 5; + attribute access(write: administer) char_string<2> location = 6; + readonly attribute int16u hardwareVersion = 7; + readonly attribute char_string<64> hardwareVersionString = 8; + readonly attribute int32u softwareVersion = 9; + readonly attribute char_string<64> softwareVersionString = 10; + readonly attribute char_string<16> manufacturingDate = 11; + readonly attribute char_string<32> partNumber = 12; + readonly attribute long_char_string<256> productURL = 13; + readonly attribute char_string<64> productLabel = 14; + readonly attribute char_string<32> serialNumber = 15; + attribute access(write: manage) boolean localConfigDisabled = 16; + readonly attribute boolean reachable = 17; + readonly attribute char_string<32> uniqueID = 18; + readonly attribute CapabilityMinimaStruct capabilityMinima = 19; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Provides an interface for providing OTA software updates */ +client cluster OtaSoftwareUpdateProvider = 41 { + enum OTAApplyUpdateAction : ENUM8 { + kProceed = 0; + kAwaitNextAction = 1; + kDiscontinue = 2; + } + + enum OTADownloadProtocol : ENUM8 { + kBDXSynchronous = 0; + kBDXAsynchronous = 1; + kHTTPS = 2; + kVendorSpecific = 3; + } + + enum OTAQueryStatus : ENUM8 { + kUpdateAvailable = 0; + kBusy = 1; + kNotAvailable = 2; + kDownloadProtocolNotSupported = 3; + } + + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct QueryImageRequest { + vendor_id vendorID = 0; + INT16U productID = 1; + INT32U softwareVersion = 2; + OTADownloadProtocol protocolsSupported[] = 3; + optional INT16U hardwareVersion = 4; + optional CHAR_STRING<2> location = 5; + optional BOOLEAN requestorCanConsent = 6; + optional OCTET_STRING<512> metadataForProvider = 7; + } + + response struct QueryImageResponse = 1 { + OTAQueryStatus status = 0; + optional INT32U delayedActionTime = 1; + optional CHAR_STRING<256> imageURI = 2; + optional INT32U softwareVersion = 3; + optional CHAR_STRING<64> softwareVersionString = 4; + optional OCTET_STRING<32> updateToken = 5; + optional BOOLEAN userConsentNeeded = 6; + optional OCTET_STRING<512> metadataForRequestor = 7; + } + + request struct ApplyUpdateRequestRequest { + OCTET_STRING<32> updateToken = 0; + INT32U newVersion = 1; + } + + response struct ApplyUpdateResponse = 3 { + OTAApplyUpdateAction action = 0; + INT32U delayedActionTime = 1; + } + + request struct NotifyUpdateAppliedRequest { + OCTET_STRING<32> updateToken = 0; + INT32U softwareVersion = 1; + } + + /** Determine availability of a new Software Image */ + command QueryImage(QueryImageRequest): QueryImageResponse = 0; + /** Determine next action to take for a downloaded Software Image */ + command ApplyUpdateRequest(ApplyUpdateRequestRequest): ApplyUpdateResponse = 2; + /** Notify OTA Provider that an update was applied */ + command NotifyUpdateApplied(NotifyUpdateAppliedRequest): DefaultSuccess = 4; +} + +/** Provides an interface for downloading and applying OTA software updates */ +server cluster OtaSoftwareUpdateRequestor = 42 { + enum OTAAnnouncementReason : ENUM8 { + kSimpleAnnouncement = 0; + kUpdateAvailable = 1; + kUrgentUpdateAvailable = 2; + } + + enum OTAChangeReasonEnum : ENUM8 { + kUnknown = 0; + kSuccess = 1; + kFailure = 2; + kTimeOut = 3; + kDelayByProvider = 4; + } + + enum OTAUpdateStateEnum : ENUM8 { + kUnknown = 0; + kIdle = 1; + kQuerying = 2; + kDelayedOnQuery = 3; + kDownloading = 4; + kApplying = 5; + kDelayedOnApply = 6; + kRollingBack = 7; + kDelayedOnUserConsent = 8; + } + + fabric_scoped struct ProviderLocation { + node_id providerNodeID = 1; + endpoint_no endpoint = 2; + fabric_idx fabricIndex = 254; + } + + info event StateTransition = 0 { + OTAUpdateStateEnum previousState = 0; + OTAUpdateStateEnum newState = 1; + OTAChangeReasonEnum reason = 2; + nullable INT32U targetSoftwareVersion = 3; + } + + critical event VersionApplied = 1 { + INT32U softwareVersion = 0; + INT16U productID = 1; + } + + info event DownloadError = 2 { + INT32U softwareVersion = 0; + INT64U bytesDownloaded = 1; + nullable INT8U progressPercent = 2; + nullable INT64S platformCode = 3; + } + + attribute ProviderLocation defaultOTAProviders[] = 0; + readonly attribute boolean updatePossible = 1; + readonly attribute OTAUpdateStateEnum updateState = 2; + readonly attribute nullable int8u updateStateProgress = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct AnnounceOTAProviderRequest { + node_id providerNodeID = 0; + vendor_id vendorID = 1; + OTAAnnouncementReason announcementReason = 2; + optional OCTET_STRING<512> metadataForNode = 3; + endpoint_no endpoint = 4; + } + + command AnnounceOTAProvider(AnnounceOTAProviderRequest): DefaultSuccess = 0; +} + +/** Nodes should be expected to be deployed to any and all regions of the world. These global regions + may have differing common languages, units of measurements, and numerical formatting + standards. As such, Nodes that visually or audibly convey information need a mechanism by which + they can be configured to use a user’s preferred language, units, etc */ +server cluster LocalizationConfiguration = 43 { + attribute char_string<35> activeLocale = 0; + readonly attribute CHAR_STRING supportedLocales[] = 1; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Nodes should be expected to be deployed to any and all regions of the world. These global regions + may have differing preferences for how dates and times are conveyed. As such, Nodes that visually + or audibly convey time information need a mechanism by which they can be configured to use a + user’s preferred format. */ +server cluster TimeFormatLocalization = 44 { + enum CalendarTypeEnum : ENUM8 { + kBuddhist = 0; + kChinese = 1; + kCoptic = 2; + kEthiopian = 3; + kGregorian = 4; + kHebrew = 5; + kIndian = 6; + kIslamic = 7; + kJapanese = 8; + kKorean = 9; + kPersian = 10; + kTaiwanese = 11; + } + + enum HourFormatEnum : ENUM8 { + k12hr = 0; + k24hr = 1; + } + + bitmap Feature : BITMAP32 { + kCalendarFormat = 0x1; + } + + attribute HourFormatEnum hourFormat = 0; + attribute CalendarTypeEnum activeCalendarType = 1; + readonly attribute CalendarTypeEnum supportedCalendarTypes[] = 2; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Nodes should be expected to be deployed to any and all regions of the world. These global regions + may have differing preferences for the units in which values are conveyed in communication to a + user. As such, Nodes that visually or audibly convey measurable values to the user need a + mechanism by which they can be configured to use a user’s preferred unit. */ +server cluster UnitLocalization = 45 { + enum TempUnitEnum : ENUM8 { + kFahrenheit = 0; + kCelsius = 1; + kKelvin = 2; + } + + bitmap Feature : BITMAP32 { + kTemperatureUnit = 0x1; + } + + attribute TempUnitEnum temperatureUnit = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** This cluster is used to describe the configuration and capabilities of a physical power source that provides power to the Node. */ +server cluster PowerSource = 47 { + enum BatApprovedChemistryEnum : ENUM16 { + kUnspecified = 0; + kAlkaline = 1; + kLithiumCarbonFluoride = 2; + kLithiumChromiumOxide = 3; + kLithiumCopperOxide = 4; + kLithiumIronDisulfide = 5; + kLithiumManganeseDioxide = 6; + kLithiumThionylChloride = 7; + kMagnesium = 8; + kMercuryOxide = 9; + kNickelOxyhydride = 10; + kSilverOxide = 11; + kZincAir = 12; + kZincCarbon = 13; + kZincChloride = 14; + kZincManganeseDioxide = 15; + kLeadAcid = 16; + kLithiumCobaltOxide = 17; + kLithiumIon = 18; + kLithiumIonPolymer = 19; + kLithiumIronPhosphate = 20; + kLithiumSulfur = 21; + kLithiumTitanate = 22; + kNickelCadmium = 23; + kNickelHydrogen = 24; + kNickelIron = 25; + kNickelMetalHydride = 26; + kNickelZinc = 27; + kSilverZinc = 28; + kSodiumIon = 29; + kSodiumSulfur = 30; + kZincBromide = 31; + kZincCerium = 32; + } + + enum BatChargeFaultEnum : ENUM8 { + kUnspecified = 0; + kAmbientTooHot = 1; + kAmbientTooCold = 2; + kBatteryTooHot = 3; + kBatteryTooCold = 4; + kBatteryAbsent = 5; + kBatteryOverVoltage = 6; + kBatteryUnderVoltage = 7; + kChargerOverVoltage = 8; + kChargerUnderVoltage = 9; + kSafetyTimeout = 10; + } + + enum BatChargeLevelEnum : ENUM8 { + kOK = 0; + kWarning = 1; + kCritical = 2; + } + + enum BatChargeStateEnum : ENUM8 { + kUnknown = 0; + kIsCharging = 1; + kIsAtFullCharge = 2; + kIsNotCharging = 3; + } + + enum BatCommonDesignationEnum : ENUM16 { + kUnspecified = 0; + kAAA = 1; + kAA = 2; + kC = 3; + kD = 4; + k4v5 = 5; + k6v0 = 6; + k9v0 = 7; + k12AA = 8; + kAAAA = 9; + kA = 10; + kB = 11; + kF = 12; + kN = 13; + kNo6 = 14; + kSubC = 15; + kA23 = 16; + kA27 = 17; + kBA5800 = 18; + kDuplex = 19; + k4SR44 = 20; + k523 = 21; + k531 = 22; + k15v0 = 23; + k22v5 = 24; + k30v0 = 25; + k45v0 = 26; + k67v5 = 27; + kJ = 28; + kCR123A = 29; + kCR2 = 30; + k2CR5 = 31; + kCRP2 = 32; + kCRV3 = 33; + kSR41 = 34; + kSR43 = 35; + kSR44 = 36; + kSR45 = 37; + kSR48 = 38; + kSR54 = 39; + kSR55 = 40; + kSR57 = 41; + kSR58 = 42; + kSR59 = 43; + kSR60 = 44; + kSR63 = 45; + kSR64 = 46; + kSR65 = 47; + kSR66 = 48; + kSR67 = 49; + kSR68 = 50; + kSR69 = 51; + kSR516 = 52; + kSR731 = 53; + kSR712 = 54; + kLR932 = 55; + kA5 = 56; + kA10 = 57; + kA13 = 58; + kA312 = 59; + kA675 = 60; + kAC41E = 61; + k10180 = 62; + k10280 = 63; + k10440 = 64; + k14250 = 65; + k14430 = 66; + k14500 = 67; + k14650 = 68; + k15270 = 69; + k16340 = 70; + kRCR123A = 71; + k17500 = 72; + k17670 = 73; + k18350 = 74; + k18500 = 75; + k18650 = 76; + k19670 = 77; + k25500 = 78; + k26650 = 79; + k32600 = 80; + } + + enum BatFaultEnum : ENUM8 { + kUnspecified = 0; + kOverTemp = 1; + kUnderTemp = 2; + } + + enum BatReplaceabilityEnum : ENUM8 { + kUnspecified = 0; + kNotReplaceable = 1; + kUserReplaceable = 2; + kFactoryReplaceable = 3; + } + + enum PowerSourceStatusEnum : ENUM8 { + kUnspecified = 0; + kActive = 1; + kStandby = 2; + kUnavailable = 3; + } + + enum WiredCurrentTypeEnum : ENUM8 { + kAC = 0; + kDC = 1; + } + + enum WiredFaultEnum : ENUM8 { + kUnspecified = 0; + kOverVoltage = 1; + kUnderVoltage = 2; + } + + bitmap Feature : BITMAP32 { + kWired = 0x1; + kBattery = 0x2; + kRechargeable = 0x4; + kReplaceable = 0x8; + } + + struct BatChargeFaultChangeType { + BatChargeFaultEnum current[] = 0; + BatChargeFaultEnum previous[] = 1; + } + + struct BatFaultChangeType { + BatFaultEnum current[] = 0; + BatFaultEnum previous[] = 1; + } + + struct WiredFaultChangeType { + WiredFaultEnum current[] = 0; + WiredFaultEnum previous[] = 1; + } + + info event WiredFaultChange = 0 { + WiredFaultEnum current[] = 0; + WiredFaultEnum previous[] = 1; + } + + info event BatFaultChange = 1 { + BatFaultEnum current[] = 0; + BatFaultEnum previous[] = 1; + } + + info event BatChargeFaultChange = 2 { + BatChargeFaultEnum current[] = 0; + BatChargeFaultEnum previous[] = 1; + } + + readonly attribute PowerSourceStatusEnum status = 0; + readonly attribute int8u order = 1; + readonly attribute char_string<60> description = 2; + readonly attribute WiredCurrentTypeEnum wiredCurrentType = 5; + readonly attribute endpoint_no endpointList[] = 31; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** This cluster is used to manage global aspects of the Commissioning flow. */ +server cluster GeneralCommissioning = 48 { + enum CommissioningErrorEnum : ENUM8 { + kOK = 0; + kValueOutsideRange = 1; + kInvalidAuthentication = 2; + kNoFailSafe = 3; + kBusyWithOtherAdmin = 4; + } + + enum RegulatoryLocationTypeEnum : ENUM8 { + kIndoor = 0; + kOutdoor = 1; + kIndoorOutdoor = 2; + } + + struct BasicCommissioningInfo { + int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; + } + + attribute access(write: administer) int64u breadcrumb = 0; + readonly attribute BasicCommissioningInfo basicCommissioningInfo = 1; + readonly attribute RegulatoryLocationTypeEnum regulatoryConfig = 2; + readonly attribute RegulatoryLocationTypeEnum locationCapability = 3; + readonly attribute boolean supportsConcurrentConnection = 4; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct ArmFailSafeRequest { + INT16U expiryLengthSeconds = 0; + INT64U breadcrumb = 1; + } + + request struct SetRegulatoryConfigRequest { + RegulatoryLocationTypeEnum newRegulatoryConfig = 0; + CHAR_STRING countryCode = 1; + INT64U breadcrumb = 2; + } + + response struct ArmFailSafeResponse = 1 { + CommissioningErrorEnum errorCode = 0; + CHAR_STRING debugText = 1; + } + + response struct SetRegulatoryConfigResponse = 3 { + CommissioningErrorEnum errorCode = 0; + CHAR_STRING debugText = 1; + } + + response struct CommissioningCompleteResponse = 5 { + CommissioningErrorEnum errorCode = 0; + CHAR_STRING debugText = 1; + } + + command access(invoke: administer) ArmFailSafe(ArmFailSafeRequest): ArmFailSafeResponse = 0; + command access(invoke: administer) SetRegulatoryConfig(SetRegulatoryConfigRequest): SetRegulatoryConfigResponse = 2; + fabric command access(invoke: administer) CommissioningComplete(): CommissioningCompleteResponse = 4; +} + +/** Functionality to configure, enable, disable network credentials and access on a Matter device. */ +server cluster NetworkCommissioning = 49 { + enum NetworkCommissioningStatusEnum : ENUM8 { + kSuccess = 0; + kOutOfRange = 1; + kBoundsExceeded = 2; + kNetworkIDNotFound = 3; + kDuplicateNetworkID = 4; + kNetworkNotFound = 5; + kRegulatoryError = 6; + kAuthFailure = 7; + kUnsupportedSecurity = 8; + kOtherConnectionFailure = 9; + kIPV6Failed = 10; + kIPBindFailed = 11; + kUnknownError = 12; + } + + enum WiFiBandEnum : ENUM8 { + k2G4 = 0; + k3G65 = 1; + k5G = 2; + k6G = 3; + k60G = 4; + k1G = 5; + } + + bitmap Feature : BITMAP32 { + kWiFiNetworkInterface = 0x1; + kThreadNetworkInterface = 0x2; + kEthernetNetworkInterface = 0x4; + } + + bitmap WiFiSecurityBitmap : BITMAP8 { + kUnencrypted = 0x1; + kWEP = 0x2; + kWPAPersonal = 0x4; + kWPA2Personal = 0x8; + kWPA3Personal = 0x10; + } + + struct NetworkInfoStruct { + octet_string<32> networkID = 0; + boolean connected = 1; + } + + struct ThreadInterfaceScanResultStruct { + int16u panId = 0; + int64u extendedPanId = 1; + char_string<16> networkName = 2; + int16u channel = 3; + int8u version = 4; + octet_string<8> extendedAddress = 5; + int8s rssi = 6; + int8u lqi = 7; + } + + struct WiFiInterfaceScanResultStruct { + WiFiSecurityBitmap security = 0; + octet_string<32> ssid = 1; + octet_string<6> bssid = 2; + int16u channel = 3; + WiFiBandEnum wiFiBand = 4; + int8s rssi = 5; + } + + readonly attribute access(read: administer) int8u maxNetworks = 0; + readonly attribute access(read: administer) NetworkInfoStruct networks[] = 1; + readonly attribute int8u scanMaxTimeSeconds = 2; + readonly attribute int8u connectMaxTimeSeconds = 3; + attribute access(write: administer) boolean interfaceEnabled = 4; + readonly attribute access(read: administer) nullable NetworkCommissioningStatusEnum lastNetworkingStatus = 5; + readonly attribute access(read: administer) nullable octet_string<32> lastNetworkID = 6; + readonly attribute access(read: administer) nullable int32s lastConnectErrorValue = 7; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct ScanNetworksRequest { + optional nullable OCTET_STRING<32> ssid = 0; + optional INT64U breadcrumb = 1; + } + + request struct AddOrUpdateWiFiNetworkRequest { + OCTET_STRING<32> ssid = 0; + OCTET_STRING<64> credentials = 1; + optional INT64U breadcrumb = 2; + } + + request struct AddOrUpdateThreadNetworkRequest { + OCTET_STRING<254> operationalDataset = 0; + optional INT64U breadcrumb = 1; + } + + request struct RemoveNetworkRequest { + OCTET_STRING<32> networkID = 0; + optional INT64U breadcrumb = 1; + } + + request struct ConnectNetworkRequest { + OCTET_STRING<32> networkID = 0; + optional INT64U breadcrumb = 1; + } + + request struct ReorderNetworkRequest { + OCTET_STRING<32> networkID = 0; + INT8U networkIndex = 1; + optional INT64U breadcrumb = 2; + } + + response struct ScanNetworksResponse = 1 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional CHAR_STRING debugText = 1; + optional WiFiInterfaceScanResultStruct wiFiScanResults[] = 2; + optional ThreadInterfaceScanResultStruct threadScanResults[] = 3; + } + + response struct NetworkConfigResponse = 5 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional CHAR_STRING<512> debugText = 1; + optional INT8U networkIndex = 2; + } + + response struct ConnectNetworkResponse = 7 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional CHAR_STRING debugText = 1; + nullable INT32S errorValue = 2; + } + + command access(invoke: administer) ScanNetworks(ScanNetworksRequest): ScanNetworksResponse = 0; + command access(invoke: administer) AddOrUpdateWiFiNetwork(AddOrUpdateWiFiNetworkRequest): NetworkConfigResponse = 2; + command access(invoke: administer) AddOrUpdateThreadNetwork(AddOrUpdateThreadNetworkRequest): NetworkConfigResponse = 3; + command access(invoke: administer) RemoveNetwork(RemoveNetworkRequest): NetworkConfigResponse = 4; + command access(invoke: administer) ConnectNetwork(ConnectNetworkRequest): ConnectNetworkResponse = 6; + command access(invoke: administer) ReorderNetwork(ReorderNetworkRequest): NetworkConfigResponse = 8; +} + +/** The General Diagnostics Cluster, along with other diagnostics clusters, provide a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems. */ +server cluster GeneralDiagnostics = 51 { + enum BootReasonEnum : ENUM8 { + kUnspecified = 0; + kPowerOnReboot = 1; + kBrownOutReset = 2; + kSoftwareWatchdogReset = 3; + kHardwareWatchdogReset = 4; + kSoftwareUpdateCompleted = 5; + kSoftwareReset = 6; + } + + enum HardwareFaultEnum : ENUM8 { + kUnspecified = 0; + kRadio = 1; + kSensor = 2; + kResettableOverTemp = 3; + kNonResettableOverTemp = 4; + kPowerSource = 5; + kVisualDisplayFault = 6; + kAudioOutputFault = 7; + kUserInterfaceFault = 8; + kNonVolatileMemoryError = 9; + kTamperDetected = 10; + } + + enum InterfaceTypeEnum : ENUM8 { + kUnspecified = 0; + kWiFi = 1; + kEthernet = 2; + kCellular = 3; + kThread = 4; + } + + enum NetworkFaultEnum : ENUM8 { + kUnspecified = 0; + kHardwareFailure = 1; + kNetworkJammed = 2; + kConnectionFailed = 3; + } + + enum RadioFaultEnum : ENUM8 { + kUnspecified = 0; + kWiFiFault = 1; + kCellularFault = 2; + kThreadFault = 3; + kNFCFault = 4; + kBLEFault = 5; + kEthernetFault = 6; + } + + struct NetworkInterface { + char_string<32> name = 0; + boolean isOperational = 1; + nullable boolean offPremiseServicesReachableIPv4 = 2; + nullable boolean offPremiseServicesReachableIPv6 = 3; + octet_string<8> hardwareAddress = 4; + octet_string IPv4Addresses[] = 5; + octet_string IPv6Addresses[] = 6; + InterfaceTypeEnum type = 7; + } + + critical event HardwareFaultChange = 0 { + HardwareFaultEnum current[] = 0; + HardwareFaultEnum previous[] = 1; + } + + critical event RadioFaultChange = 1 { + RadioFaultEnum current[] = 0; + RadioFaultEnum previous[] = 1; + } + + critical event NetworkFaultChange = 2 { + NetworkFaultEnum current[] = 0; + NetworkFaultEnum previous[] = 1; + } + + critical event BootReason = 3 { + BootReasonEnum bootReason = 0; + } + + readonly attribute NetworkInterface networkInterfaces[] = 0; + readonly attribute int16u rebootCount = 1; + readonly attribute int64u upTime = 2; + readonly attribute int32u totalOperationalHours = 3; + readonly attribute BootReasonEnum bootReason = 4; + readonly attribute HardwareFaultEnum activeHardwareFaults[] = 5; + readonly attribute RadioFaultEnum activeRadioFaults[] = 6; + readonly attribute NetworkFaultEnum activeNetworkFaults[] = 7; + readonly attribute boolean testEventTriggersEnabled = 8; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct TestEventTriggerRequest { + OCTET_STRING<16> enableKey = 0; + INT64U eventTrigger = 1; + } + + command access(invoke: manage) TestEventTrigger(TestEventTriggerRequest): DefaultSuccess = 0; +} + +/** The Thread Network Diagnostics Cluster provides a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems */ +server cluster ThreadNetworkDiagnostics = 53 { + enum ConnectionStatusEnum : ENUM8 { + kConnected = 0; + kNotConnected = 1; + } + + enum NetworkFaultEnum : ENUM8 { + kUnspecified = 0; + kLinkDown = 1; + kHardwareFailure = 2; + kNetworkJammed = 3; + } + + enum RoutingRoleEnum : ENUM8 { + kUnspecified = 0; + kUnassigned = 1; + kSleepyEndDevice = 2; + kEndDevice = 3; + kREED = 4; + kRouter = 5; + kLeader = 6; + } + + bitmap Feature : BITMAP32 { + kPacketCounts = 0x1; + kErrorCounts = 0x2; + kMLECounts = 0x4; + kMACCounts = 0x8; + } + + struct NeighborTableStruct { + int64u extAddress = 0; + int32u age = 1; + int16u rloc16 = 2; + int32u linkFrameCounter = 3; + int32u mleFrameCounter = 4; + int8u lqi = 5; + nullable int8s averageRssi = 6; + nullable int8s lastRssi = 7; + int8u frameErrorRate = 8; + int8u messageErrorRate = 9; + boolean rxOnWhenIdle = 10; + boolean fullThreadDevice = 11; + boolean fullNetworkData = 12; + boolean isChild = 13; + } + + struct OperationalDatasetComponents { + boolean activeTimestampPresent = 0; + boolean pendingTimestampPresent = 1; + boolean masterKeyPresent = 2; + boolean networkNamePresent = 3; + boolean extendedPanIdPresent = 4; + boolean meshLocalPrefixPresent = 5; + boolean delayPresent = 6; + boolean panIdPresent = 7; + boolean channelPresent = 8; + boolean pskcPresent = 9; + boolean securityPolicyPresent = 10; + boolean channelMaskPresent = 11; + } + + struct RouteTableStruct { + int64u extAddress = 0; + int16u rloc16 = 1; + int8u routerId = 2; + int8u nextHop = 3; + int8u pathCost = 4; + int8u LQIIn = 5; + int8u LQIOut = 6; + int8u age = 7; + boolean allocated = 8; + boolean linkEstablished = 9; + } + + struct SecurityPolicy { + int16u rotationTime = 0; + int16u flags = 1; + } + + info event ConnectionStatus = 0 { + ConnectionStatusEnum connectionStatus = 0; + } + + info event NetworkFaultChange = 1 { + NetworkFaultEnum current[] = 0; + NetworkFaultEnum previous[] = 1; + } + + readonly attribute nullable int16u channel = 0; + readonly attribute nullable RoutingRoleEnum routingRole = 1; + readonly attribute nullable char_string<16> networkName = 2; + readonly attribute nullable int16u panId = 3; + readonly attribute nullable int64u extendedPanId = 4; + readonly attribute nullable octet_string<17> meshLocalPrefix = 5; + readonly attribute int64u overrunCount = 6; + readonly attribute NeighborTableStruct neighborTable[] = 7; + readonly attribute RouteTableStruct routeTable[] = 8; + readonly attribute nullable int32u partitionId = 9; + readonly attribute nullable int8u weighting = 10; + readonly attribute nullable int8u dataVersion = 11; + readonly attribute nullable int8u stableDataVersion = 12; + readonly attribute nullable int8u leaderRouterId = 13; + readonly attribute int16u detachedRoleCount = 14; + readonly attribute int16u childRoleCount = 15; + readonly attribute int16u routerRoleCount = 16; + readonly attribute int16u leaderRoleCount = 17; + readonly attribute int16u attachAttemptCount = 18; + readonly attribute int16u partitionIdChangeCount = 19; + readonly attribute int16u betterPartitionAttachAttemptCount = 20; + readonly attribute int16u parentChangeCount = 21; + readonly attribute int32u txTotalCount = 22; + readonly attribute int32u txUnicastCount = 23; + readonly attribute int32u txBroadcastCount = 24; + readonly attribute int32u txAckRequestedCount = 25; + readonly attribute int32u txAckedCount = 26; + readonly attribute int32u txNoAckRequestedCount = 27; + readonly attribute int32u txDataCount = 28; + readonly attribute int32u txDataPollCount = 29; + readonly attribute int32u txBeaconCount = 30; + readonly attribute int32u txBeaconRequestCount = 31; + readonly attribute int32u txOtherCount = 32; + readonly attribute int32u txRetryCount = 33; + readonly attribute int32u txDirectMaxRetryExpiryCount = 34; + readonly attribute int32u txIndirectMaxRetryExpiryCount = 35; + readonly attribute int32u txErrCcaCount = 36; + readonly attribute int32u txErrAbortCount = 37; + readonly attribute int32u txErrBusyChannelCount = 38; + readonly attribute int32u rxTotalCount = 39; + readonly attribute int32u rxUnicastCount = 40; + readonly attribute int32u rxBroadcastCount = 41; + readonly attribute int32u rxDataCount = 42; + readonly attribute int32u rxDataPollCount = 43; + readonly attribute int32u rxBeaconCount = 44; + readonly attribute int32u rxBeaconRequestCount = 45; + readonly attribute int32u rxOtherCount = 46; + readonly attribute int32u rxAddressFilteredCount = 47; + readonly attribute int32u rxDestAddrFilteredCount = 48; + readonly attribute int32u rxDuplicatedCount = 49; + readonly attribute int32u rxErrNoFrameCount = 50; + readonly attribute int32u rxErrUnknownNeighborCount = 51; + readonly attribute int32u rxErrInvalidSrcAddrCount = 52; + readonly attribute int32u rxErrSecCount = 53; + readonly attribute int32u rxErrFcsCount = 54; + readonly attribute int32u rxErrOtherCount = 55; + readonly attribute nullable int64u activeTimestamp = 56; + readonly attribute nullable int64u pendingTimestamp = 57; + readonly attribute nullable int32u delay = 58; + readonly attribute nullable SecurityPolicy securityPolicy = 59; + readonly attribute nullable octet_string<4> channelPage0Mask = 60; + readonly attribute nullable OperationalDatasetComponents operationalDatasetComponents = 61; + readonly attribute NetworkFaultEnum activeNetworkFaultsList[] = 62; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + command ResetCounts(): DefaultSuccess = 0; +} + +/** Commands to trigger a Node to allow a new Administrator to commission it. */ +server cluster AdministratorCommissioning = 60 { + enum CommissioningWindowStatusEnum : ENUM8 { + kWindowNotOpen = 0; + kEnhancedWindowOpen = 1; + kBasicWindowOpen = 2; + } + + enum StatusCode : ENUM8 { + kBusy = 2; + kPAKEParameterError = 3; + kWindowNotOpen = 4; + } + + readonly attribute CommissioningWindowStatusEnum windowStatus = 0; + readonly attribute nullable fabric_idx adminFabricIndex = 1; + readonly attribute nullable int16u adminVendorId = 2; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct OpenCommissioningWindowRequest { + INT16U commissioningTimeout = 0; + OCTET_STRING PAKEPasscodeVerifier = 1; + INT16U discriminator = 2; + INT32U iterations = 3; + OCTET_STRING salt = 4; + } + + request struct OpenBasicCommissioningWindowRequest { + INT16U commissioningTimeout = 0; + } + + timed command access(invoke: administer) OpenCommissioningWindow(OpenCommissioningWindowRequest): DefaultSuccess = 0; + timed command access(invoke: administer) OpenBasicCommissioningWindow(OpenBasicCommissioningWindowRequest): DefaultSuccess = 1; + timed command access(invoke: administer) RevokeCommissioning(): DefaultSuccess = 2; +} + +/** This cluster is used to add or remove Operational Credentials on a Commissionee or Node, as well as manage the associated Fabrics. */ +server cluster OperationalCredentials = 62 { + enum CertificateChainTypeEnum : ENUM8 { + kDACCertificate = 1; + kPAICertificate = 2; + } + + enum NodeOperationalCertStatusEnum : ENUM8 { + kOK = 0; + kInvalidPublicKey = 1; + kInvalidNodeOpId = 2; + kInvalidNOC = 3; + kMissingCsr = 4; + kTableFull = 5; + kInvalidAdminSubject = 6; + kFabricConflict = 9; + kLabelConflict = 10; + kInvalidFabricIndex = 11; + } + + fabric_scoped struct FabricDescriptorStruct { + octet_string<65> rootPublicKey = 1; + vendor_id vendorID = 2; + fabric_id fabricID = 3; + node_id nodeID = 4; + char_string<32> label = 5; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct NOCStruct { + fabric_sensitive octet_string noc = 1; + nullable fabric_sensitive octet_string icac = 2; + fabric_idx fabricIndex = 254; + } + + readonly attribute access(read: administer) NOCStruct NOCs[] = 0; + readonly attribute FabricDescriptorStruct fabrics[] = 1; + readonly attribute int8u supportedFabrics = 2; + readonly attribute int8u commissionedFabrics = 3; + readonly attribute OCTET_STRING trustedRootCertificates[] = 4; + readonly attribute int8u currentFabricIndex = 5; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct AttestationRequestRequest { + OCTET_STRING attestationNonce = 0; + } + + request struct CertificateChainRequestRequest { + CertificateChainTypeEnum certificateType = 0; + } + + request struct CSRRequestRequest { + OCTET_STRING CSRNonce = 0; + optional boolean isForUpdateNOC = 1; + } + + request struct AddNOCRequest { + OCTET_STRING NOCValue = 0; + optional OCTET_STRING ICACValue = 1; + OCTET_STRING IPKValue = 2; + Int64u caseAdminSubject = 3; + VENDOR_ID adminVendorId = 4; + } + + request struct UpdateNOCRequest { + OCTET_STRING NOCValue = 0; + optional OCTET_STRING ICACValue = 1; + } + + request struct UpdateFabricLabelRequest { + CHAR_STRING<32> label = 0; + } + + request struct RemoveFabricRequest { + fabric_idx fabricIndex = 0; + } + + request struct AddTrustedRootCertificateRequest { + OCTET_STRING rootCACertificate = 0; + } + + response struct AttestationResponse = 1 { + OCTET_STRING attestationElements = 0; + OCTET_STRING attestationSignature = 1; + } + + response struct CertificateChainResponse = 3 { + OCTET_STRING certificate = 0; + } + + response struct CSRResponse = 5 { + OCTET_STRING NOCSRElements = 0; + OCTET_STRING attestationSignature = 1; + } + + response struct NOCResponse = 8 { + NodeOperationalCertStatusEnum statusCode = 0; + optional fabric_idx fabricIndex = 1; + optional CHAR_STRING debugText = 2; + } + + command access(invoke: administer) AttestationRequest(AttestationRequestRequest): AttestationResponse = 0; + command access(invoke: administer) CertificateChainRequest(CertificateChainRequestRequest): CertificateChainResponse = 2; + command access(invoke: administer) CSRRequest(CSRRequestRequest): CSRResponse = 4; + command access(invoke: administer) AddNOC(AddNOCRequest): NOCResponse = 6; + fabric command access(invoke: administer) UpdateNOC(UpdateNOCRequest): NOCResponse = 7; + fabric command access(invoke: administer) UpdateFabricLabel(UpdateFabricLabelRequest): NOCResponse = 9; + command access(invoke: administer) RemoveFabric(RemoveFabricRequest): NOCResponse = 10; + command access(invoke: administer) AddTrustedRootCertificate(AddTrustedRootCertificateRequest): DefaultSuccess = 11; +} + +/** The Group Key Management Cluster is the mechanism by which group keys are managed. */ +server cluster GroupKeyManagement = 63 { + enum GroupKeySecurityPolicyEnum : ENUM8 { + kTrustFirst = 0; + kCacheAndSync = 1; + } + + bitmap Feature : BITMAP32 { + kCacheAndSync = 0x1; + } + + fabric_scoped struct GroupInfoMapStruct { + group_id groupId = 1; + endpoint_no endpoints[] = 2; + optional char_string<16> groupName = 3; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct GroupKeyMapStruct { + group_id groupId = 1; + int16u groupKeySetID = 2; + fabric_idx fabricIndex = 254; + } + + struct GroupKeySetStruct { + int16u groupKeySetID = 0; + GroupKeySecurityPolicyEnum groupKeySecurityPolicy = 1; + nullable octet_string<16> epochKey0 = 2; + nullable epoch_us epochStartTime0 = 3; + nullable octet_string<16> epochKey1 = 4; + nullable epoch_us epochStartTime1 = 5; + nullable octet_string<16> epochKey2 = 6; + nullable epoch_us epochStartTime2 = 7; + } + + attribute access(write: manage) GroupKeyMapStruct groupKeyMap[] = 0; + readonly attribute GroupInfoMapStruct groupTable[] = 1; + readonly attribute int16u maxGroupsPerFabric = 2; + readonly attribute int16u maxGroupKeysPerFabric = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct KeySetWriteRequest { + GroupKeySetStruct groupKeySet = 0; + } + + request struct KeySetReadRequest { + INT16U groupKeySetID = 0; + } + + request struct KeySetRemoveRequest { + INT16U groupKeySetID = 0; + } + + response struct KeySetReadResponse = 2 { + GroupKeySetStruct groupKeySet = 0; + } + + response struct KeySetReadAllIndicesResponse = 5 { + INT16U groupKeySetIDs[] = 0; + } + + fabric command access(invoke: administer) KeySetWrite(KeySetWriteRequest): DefaultSuccess = 0; + fabric command access(invoke: administer) KeySetRead(KeySetReadRequest): KeySetReadResponse = 1; + fabric command access(invoke: administer) KeySetRemove(KeySetRemoveRequest): DefaultSuccess = 3; + fabric command access(invoke: administer) KeySetReadAllIndices(): KeySetReadAllIndicesResponse = 4; +} + +/** The Fixed Label Cluster provides a feature for the device to tag an endpoint with zero or more read only +labels. */ +server cluster FixedLabel = 64 { + struct LabelStruct { + char_string<16> label = 0; + char_string<16> value = 1; + } + + readonly attribute LabelStruct labelList[] = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** The User Label Cluster provides a feature to tag an endpoint with zero or more labels. */ +server cluster UserLabel = 65 { + struct LabelStruct { + char_string<16> label = 0; + char_string<16> value = 1; + } + + attribute access(write: manage) LabelStruct labelList[] = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** An interface for configuring and controlling the functionality of a thermostat. */ +server cluster Thermostat = 513 { + enum SetpointAdjustMode : ENUM8 { + kHeat = 0; + kCool = 1; + kBoth = 2; + } + + enum ThermostatControlSequence : ENUM8 { + kCoolingOnly = 0; + kCoolingWithReheat = 1; + kHeatingOnly = 2; + kHeatingWithReheat = 3; + kCoolingAndHeating = 4; + kCoolingAndHeatingWithReheat = 5; + } + + enum ThermostatRunningMode : ENUM8 { + kOff = 0; + kCool = 3; + kHeat = 4; + } + + enum ThermostatSystemMode : ENUM8 { + kOff = 0; + kAuto = 1; + kCool = 3; + kHeat = 4; + kEmergencyHeat = 5; + kPrecooling = 6; + kFanOnly = 7; + kDry = 8; + kSleep = 9; + } + + bitmap DayOfWeek : BITMAP8 { + kSunday = 0x1; + kMonday = 0x2; + kTuesday = 0x4; + kWednesday = 0x8; + kThursday = 0x10; + kFriday = 0x20; + kSaturday = 0x40; + kAway = 0x80; + } + + bitmap Feature : BITMAP32 { + kHeating = 0x1; + kCooling = 0x2; + kOccupancy = 0x4; + kScheduleConfiguration = 0x8; + kSetback = 0x10; + kAutoMode = 0x20; + kLocalTemperatureNotExposed = 0x40; + } + + bitmap ModeForSequence : BITMAP8 { + kHeatSetpointPresent = 0x1; + kCoolSetpointPresent = 0x2; + } + + struct ThermostatScheduleTransition { + int16u transitionTime = 0; + nullable int16s heatSetpoint = 1; + nullable int16s coolSetpoint = 2; + } + + readonly attribute nullable int16s localTemperature = 0; + readonly attribute int16s absMinHeatSetpointLimit = 3; + readonly attribute int16s absMaxHeatSetpointLimit = 4; + readonly attribute int16s absMinCoolSetpointLimit = 5; + readonly attribute int16s absMaxCoolSetpointLimit = 6; + attribute access(write: manage) bitmap8 HVACSystemTypeConfiguration = 9; + attribute int16s occupiedCoolingSetpoint = 17; + attribute int16s occupiedHeatingSetpoint = 18; + attribute access(write: manage) int16s minHeatSetpointLimit = 21; + attribute access(write: manage) int16s maxHeatSetpointLimit = 22; + attribute access(write: manage) int16s minCoolSetpointLimit = 23; + attribute access(write: manage) int16s maxCoolSetpointLimit = 24; + attribute access(write: manage) int8s minSetpointDeadBand = 25; + attribute access(write: manage) ThermostatControlSequence controlSequenceOfOperation = 27; + attribute access(write: manage) enum8 systemMode = 28; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct SetpointRaiseLowerRequest { + SetpointAdjustMode mode = 0; + INT8S amount = 1; + } + + command SetpointRaiseLower(SetpointRaiseLowerRequest): DefaultSuccess = 0; +} + +endpoint 0 { + device type ma_rootdevice = 22, version 1; + + binding cluster OtaSoftwareUpdateProvider; + + server cluster Identify { + ram attribute identifyTime default = 0x0000; + ram attribute identifyType default = 0x00; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 4; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + ram attribute featureMap default = 0; + callback attribute clusterRevision default = 1; + } + + server cluster AccessControl { + emits event AccessControlEntryChanged; + emits event AccessControlExtensionChanged; + callback attribute acl; + callback attribute extension; + callback attribute subjectsPerAccessControlEntry default = 4; + callback attribute targetsPerAccessControlEntry default = 3; + callback attribute accessControlEntriesPerFabric default = 3; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster BasicInformation { + emits event StartUp; + emits event ShutDown; + emits event Leave; + callback attribute dataModelRevision default = 10; + callback attribute vendorName; + callback attribute vendorID; + callback attribute productName; + callback attribute productID; + persist attribute nodeLabel; + callback attribute location default = "XX"; + callback attribute hardwareVersion default = 0; + callback attribute hardwareVersionString; + callback attribute softwareVersion default = 0; + callback attribute softwareVersionString; + callback attribute manufacturingDate default = "20210614123456ZZ"; + callback attribute partNumber; + callback attribute productURL; + callback attribute productLabel; + callback attribute serialNumber; + persist attribute localConfigDisabled default = 0; + ram attribute reachable default = 1; + callback attribute uniqueID; + callback attribute capabilityMinima; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster OtaSoftwareUpdateRequestor { + callback attribute defaultOTAProviders default = 0; + ram attribute updatePossible default = 1; + ram attribute updateState default = 0; + ram attribute updateStateProgress default = 0; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster LocalizationConfiguration { + persist attribute activeLocale default = "en-US"; + callback attribute supportedLocales; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster TimeFormatLocalization { + persist attribute hourFormat default = 0; + persist attribute activeCalendarType default = 0; + callback attribute supportedCalendarTypes; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster UnitLocalization { + persist attribute temperatureUnit default = 0; + ram attribute featureMap default = 0x1; + ram attribute clusterRevision default = 1; + } + + server cluster GeneralCommissioning { + ram attribute breadcrumb default = 0x0000000000000000; + callback attribute basicCommissioningInfo; + callback attribute regulatoryConfig default = 0; + callback attribute locationCapability default = 0; + callback attribute supportsConcurrentConnection default = 1; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster NetworkCommissioning { + ram attribute maxNetworks; + callback attribute networks; + ram attribute scanMaxTimeSeconds; + ram attribute connectMaxTimeSeconds; + ram attribute interfaceEnabled; + ram attribute lastNetworkingStatus; + ram attribute lastNetworkID; + ram attribute lastConnectErrorValue; + ram attribute featureMap default = 2; + ram attribute clusterRevision default = 1; + } + + server cluster GeneralDiagnostics { + emits event BootReason; + callback attribute networkInterfaces; + callback attribute rebootCount default = 0x0000; + callback attribute upTime default = 0x0000000000000000; + callback attribute totalOperationalHours default = 0x00000000; + callback attribute bootReason; + callback attribute activeHardwareFaults; + callback attribute activeRadioFaults; + callback attribute activeNetworkFaults; + callback attribute testEventTriggersEnabled default = false; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster ThreadNetworkDiagnostics { + callback attribute channel; + callback attribute routingRole; + callback attribute networkName default = "0"; + callback attribute panId default = 0x0000; + callback attribute extendedPanId default = 0x0000000000000000; + callback attribute meshLocalPrefix; + callback attribute overrunCount default = 0x0000000000000000; + callback attribute neighborTable; + callback attribute routeTable; + callback attribute partitionId; + callback attribute weighting; + callback attribute dataVersion; + callback attribute stableDataVersion; + callback attribute leaderRouterId; + callback attribute detachedRoleCount default = 0x0000; + callback attribute childRoleCount default = 0x0000; + callback attribute routerRoleCount default = 0x0000; + callback attribute leaderRoleCount default = 0x0000; + callback attribute attachAttemptCount default = 0x0000; + callback attribute partitionIdChangeCount default = 0x0000; + callback attribute betterPartitionAttachAttemptCount default = 0x0000; + callback attribute parentChangeCount default = 0x0000; + callback attribute txTotalCount default = 0x0000; + callback attribute txUnicastCount default = 0x0000; + callback attribute txBroadcastCount default = 0x0000; + callback attribute txAckRequestedCount default = 0x0000; + callback attribute txAckedCount default = 0x0000; + callback attribute txNoAckRequestedCount default = 0x0000; + callback attribute txDataCount default = 0x0000; + callback attribute txDataPollCount default = 0x0000; + callback attribute txBeaconCount default = 0x0000; + callback attribute txBeaconRequestCount default = 0x0000; + callback attribute txOtherCount default = 0x0000; + callback attribute txRetryCount default = 0x0000; + callback attribute txDirectMaxRetryExpiryCount default = 0x0000; + callback attribute txIndirectMaxRetryExpiryCount default = 0x0000; + callback attribute txErrCcaCount default = 0x0000; + callback attribute txErrAbortCount default = 0x0000; + callback attribute txErrBusyChannelCount default = 0x0000; + callback attribute rxTotalCount default = 0x0000; + callback attribute rxUnicastCount default = 0x0000; + callback attribute rxBroadcastCount default = 0x0000; + callback attribute rxDataCount default = 0x0000; + callback attribute rxDataPollCount default = 0x0000; + callback attribute rxBeaconCount default = 0x0000; + callback attribute rxBeaconRequestCount default = 0x0000; + callback attribute rxOtherCount default = 0x0000; + callback attribute rxAddressFilteredCount default = 0x0000; + callback attribute rxDestAddrFilteredCount default = 0x0000; + callback attribute rxDuplicatedCount default = 0x0000; + callback attribute rxErrNoFrameCount default = 0x0000; + callback attribute rxErrUnknownNeighborCount default = 0x0000; + callback attribute rxErrInvalidSrcAddrCount default = 0x0000; + callback attribute rxErrSecCount default = 0x0000; + callback attribute rxErrFcsCount default = 0x0000; + callback attribute rxErrOtherCount default = 0x0000; + callback attribute activeTimestamp default = 0x0000000000000000; + callback attribute pendingTimestamp default = 0x0000000000000000; + callback attribute delay default = 0x0000; + callback attribute securityPolicy; + callback attribute channelPage0Mask default = "0x0000"; + callback attribute operationalDatasetComponents; + callback attribute activeNetworkFaultsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0x000F; + ram attribute clusterRevision default = 1; + } + + server cluster AdministratorCommissioning { + callback attribute windowStatus default = 0; + callback attribute adminFabricIndex default = 1; + callback attribute adminVendorId default = 0; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster OperationalCredentials { + callback attribute NOCs; + callback attribute fabrics; + callback attribute supportedFabrics; + callback attribute commissionedFabrics; + callback attribute trustedRootCertificates; + callback attribute currentFabricIndex; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster GroupKeyManagement { + callback attribute groupKeyMap; + callback attribute groupTable; + callback attribute maxGroupsPerFabric; + callback attribute maxGroupKeysPerFabric; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } +} +endpoint 1 { + device type ma_thermostat = 769, version 1; + + binding cluster Identify; + + server cluster Identify { + ram attribute identifyTime default = 0x0000; + ram attribute identifyType default = 0x0; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 4; + } + + server cluster Groups { + ram attribute nameSupport; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 4; + } + + server cluster Scenes { + callback attribute sceneCount default = 0x00; + ram attribute currentScene default = 0x00; + ram attribute currentGroup default = 0x0000; + ram attribute sceneValid default = 0x00; + ram attribute nameSupport; + ram attribute sceneTableSize; + callback attribute remainingCapacity; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 4; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + ram attribute featureMap default = 0; + callback attribute clusterRevision default = 1; + } + + server cluster Binding { + callback attribute binding; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster PowerSource { + ram attribute status; + ram attribute order; + ram attribute description; + ram attribute wiredCurrentType; + callback attribute endpointList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 1; + ram attribute clusterRevision default = 1; + } + + server cluster FixedLabel { + callback attribute labelList; + callback attribute eventList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster UserLabel { + callback attribute labelList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster Thermostat { + ram attribute localTemperature; + ram attribute absMinHeatSetpointLimit default = 700; + ram attribute absMaxHeatSetpointLimit default = 3000; + ram attribute absMinCoolSetpointLimit default = 1600; + ram attribute absMaxCoolSetpointLimit default = 3200; + ram attribute HVACSystemTypeConfiguration; + persist attribute occupiedCoolingSetpoint default = 0x0A28; + persist attribute occupiedHeatingSetpoint default = 0x07D0; + ram attribute minHeatSetpointLimit default = 700; + ram attribute maxHeatSetpointLimit default = 3000; + ram attribute minCoolSetpointLimit default = 1600; + ram attribute maxCoolSetpointLimit default = 3200; + ram attribute minSetpointDeadBand default = 0x19; + ram attribute controlSequenceOfOperation default = 0x04; + persist attribute systemMode default = 0x01; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0x3; + ram attribute clusterRevision default = 5; + } +} + + diff --git a/examples/thermostat/nxp/zap/thermostat_matter_thread.zap b/examples/thermostat/nxp/zap/thermostat_matter_thread.zap new file mode 100644 index 00000000000000..3b1033c6a4d4f8 --- /dev/null +++ b/examples/thermostat/nxp/zap/thermostat_matter_thread.zap @@ -0,0 +1,16543 @@ +{ + "featureLevel": 98, + "creator": "zap", + "keyValuePairs": [ + { + "key": "commandDiscovery", + "value": "1" + }, + { + "key": "defaultResponsePolicy", + "value": "always" + }, + { + "key": "manufacturerCodes", + "value": "0x1002" + } + ], + "package": [ + { + "pathRelativity": "relativeToZap", + "path": "../../../../src/app/zap-templates/zcl/zcl.json", + "type": "zcl-properties", + "category": "matter", + "version": 1, + "description": "Matter SDK ZCL data" + }, + { + "pathRelativity": "relativeToZap", + "path": "../../../../src/app/zap-templates/app-templates.json", + "type": "gen-templates-json", + "version": "chip-v1" + } + ], + "endpointTypes": [ + { + "id": 1, + "name": "MA-rootdevice", + "deviceTypeRef": { + "code": 22, + "profileId": 259, + "label": "MA-rootdevice", + "name": "MA-rootdevice" + }, + "deviceTypes": [ + { + "code": 22, + "profileId": 259, + "label": "MA-rootdevice", + "name": "MA-rootdevice" + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 22 + ], + "deviceTypeName": "MA-rootdevice", + "deviceTypeCode": 22, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddGroup", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewGroup", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetGroupMembership", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveGroup", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveAllGroups", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddGroupIfIdentifying", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "AddGroupResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewGroupResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetGroupMembershipResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveGroupResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "NameSupport", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "NameSupportBitmap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddScene", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewScene", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveScene", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveAllScenes", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StoreScene", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RecallScene", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetSceneMembership", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "AddSceneResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewSceneResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveSceneResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveAllScenesResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StoreSceneResponse", + "code": 4, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetSceneMembershipResponse", + "code": 6, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "SceneCount", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentScene", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentGroup", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "group_id", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SceneValid", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NameSupport", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/Off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Off", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "On", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Toggle", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/Off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "OnOff", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "MoveToLevel", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Move", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Step", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Stop", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToLevelWithOnOff", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveWithOnOff", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepWithOnOff", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StopWithOnOff", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "CurrentLevel", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "Binding", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Access Control", + "code": 31, + "mfgCode": null, + "define": "ACCESS_CONTROL_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "Access Control", + "code": 31, + "mfgCode": null, + "define": "ACCESS_CONTROL_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "ACL", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Extension", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SubjectsPerAccessControlEntry", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TargetsPerAccessControlEntry", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AccessControlEntriesPerFabric", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "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": "", + "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": "AccessControlEntryChanged", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "AccessControlExtensionChanged", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Basic Information", + "code": 40, + "mfgCode": null, + "define": "BASIC_INFORMATION_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Basic Information", + "code": 40, + "mfgCode": null, + "define": "BASIC_INFORMATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DataModelRevision", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "10", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorName", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorID", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductName", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductID", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NodeLabel", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Location", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "XX", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersion", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersionString", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersion", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersionString", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ManufacturingDate", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "20210614123456ZZ", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartNumber", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductURL", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "long_char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductLabel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SerialNumber", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LocalConfigDisabled", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Reachable", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UniqueID", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CapabilityMinima", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "CapabilityMinimaStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "StartUp", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "ShutDown", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "Leave", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "OTA Software Update Provider", + "code": 41, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_PROVIDER_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "QueryImage", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ApplyUpdateRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "NotifyUpdateApplied", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Provider", + "code": 41, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_PROVIDER_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "QueryImageResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ApplyUpdateResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Requestor", + "code": 42, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_REQUESTOR_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AnnounceOTAProvider", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "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": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Requestor", + "code": 42, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_REQUESTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DefaultOTAProviders", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "UpdatePossible", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "UpdateState", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "OTAUpdateStateEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "UpdateStateProgress", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "Localization Configuration", + "code": 43, + "mfgCode": null, + "define": "LOCALIZATION_CONFIGURATION_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "Localization Configuration", + "code": 43, + "mfgCode": null, + "define": "LOCALIZATION_CONFIGURATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "ActiveLocale", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "en-US", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportedLocales", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "Time Format Localization", + "code": 44, + "mfgCode": null, + "define": "TIME_FORMAT_LOCALIZATION_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "Time Format Localization", + "code": 44, + "mfgCode": null, + "define": "TIME_FORMAT_LOCALIZATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "HourFormat", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "HourFormatEnum", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveCalendarType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "CalendarTypeEnum", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportedCalendarTypes", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "Unit Localization", + "code": 45, + "mfgCode": null, + "define": "UNIT_LOCALIZATION_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "Unit Localization", + "code": 45, + "mfgCode": null, + "define": "UNIT_LOCALIZATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "TemperatureUnit", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "TempUnitEnum", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x1", + "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": "Power Source", + "code": 47, + "mfgCode": null, + "define": "POWER_SOURCE_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "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": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Power Source", + "code": 47, + "mfgCode": null, + "define": "POWER_SOURCE_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "Status", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "PowerSourceStatusEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Order", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Description", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredAssessedInputVoltage", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredAssessedInputFrequency", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredCurrentType", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "WiredCurrentTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredAssessedCurrent", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredNominalVoltage", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredMaximumCurrent", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredPresent", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveWiredFaults", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatVoltage", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatPercentRemaining", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatTimeRemaining", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatChargeLevel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "BatChargeLevelEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplacementNeeded", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplaceability", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "BatReplaceabilityEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatPresent", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveBatFaults", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplacementDescription", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatCommonDesignation", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "BatCommonDesignationEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatANSIDesignation", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatIECDesignation", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatApprovedChemistry", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "BatApprovedChemistryEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatCapacity", + "code": 24, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatQuantity", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatChargeState", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "BatChargeStateEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatTimeToFullCharge", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatFunctionalWhileCharging", + "code": 28, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatChargingCurrent", + "code": 29, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveBatChargeFaults", + "code": 30, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "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": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ArmFailSafe", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetRegulatoryConfig", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "CommissioningComplete", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ArmFailSafeResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetRegulatoryConfigResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "CommissioningCompleteResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "Breadcrumb", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BasicCommissioningInfo", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "BasicCommissioningInfo", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RegulatoryConfig", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationTypeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LocationCapability", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationTypeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportsConcurrentConnection", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ScanNetworks", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddOrUpdateWiFiNetwork", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "AddOrUpdateThreadNetwork", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveNetwork", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ConnectNetwork", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ReorderNetwork", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ScanNetworksResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "NetworkConfigResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ConnectNetworkResponse", + "code": 7, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "MaxNetworks", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Networks", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ScanMaxTimeSeconds", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ConnectMaxTimeSeconds", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "InterfaceEnabled", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkingStatus", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "NetworkCommissioningStatusEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkID", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastConnectErrorValue", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "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": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RetrieveLogsResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "TestEventTrigger", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "NetworkInterfaces", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RebootCount", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UpTime", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TotalOperationalHours", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BootReason", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "BootReasonEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveHardwareFaults", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveRadioFaults", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveNetworkFaults", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TestEventTriggersEnabled", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "false", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "BootReason", + "code": 3, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Software Diagnostics", + "code": 52, + "mfgCode": null, + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetWatermarks", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Software Diagnostics", + "code": 52, + "mfgCode": null, + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "ThreadMetrics", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapFree", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapUsed", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapHighWatermark", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Thread Network Diagnostics", + "code": 53, + "mfgCode": null, + "define": "THREAD_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetCounts", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ] + }, + { + "name": "Thread Network Diagnostics", + "code": 53, + "mfgCode": null, + "define": "THREAD_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Channel", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RoutingRole", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "RoutingRoleEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NetworkName", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PanId", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ExtendedPanId", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MeshLocalPrefix", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OverrunCount", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NeighborTable", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RouteTable", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartitionId", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Weighting", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DataVersion", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "StableDataVersion", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LeaderRouterId", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DetachedRoleCount", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ChildRoleCount", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RouterRoleCount", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LeaderRoleCount", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "AttachAttemptCount", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartitionIdChangeCount", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BetterPartitionAttachAttemptCount", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ParentChangeCount", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxTotalCount", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxUnicastCount", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBroadcastCount", + "code": 24, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxAckRequestedCount", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxAckedCount", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxNoAckRequestedCount", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDataCount", + "code": 28, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDataPollCount", + "code": 29, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBeaconCount", + "code": 30, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBeaconRequestCount", + "code": 31, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxOtherCount", + "code": 32, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxRetryCount", + "code": 33, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDirectMaxRetryExpiryCount", + "code": 34, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxIndirectMaxRetryExpiryCount", + "code": 35, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrCcaCount", + "code": 36, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrAbortCount", + "code": 37, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrBusyChannelCount", + "code": 38, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxTotalCount", + "code": 39, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxUnicastCount", + "code": 40, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBroadcastCount", + "code": 41, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDataCount", + "code": 42, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDataPollCount", + "code": 43, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBeaconCount", + "code": 44, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBeaconRequestCount", + "code": 45, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxOtherCount", + "code": 46, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxAddressFilteredCount", + "code": 47, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDestAddrFilteredCount", + "code": 48, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDuplicatedCount", + "code": 49, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrNoFrameCount", + "code": 50, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrUnknownNeighborCount", + "code": 51, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrInvalidSrcAddrCount", + "code": 52, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrSecCount", + "code": 53, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrFcsCount", + "code": 54, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrOtherCount", + "code": 55, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ActiveTimestamp", + "code": 56, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PendingTimestamp", + "code": 57, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Delay", + "code": 58, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SecurityPolicy", + "code": 59, + "mfgCode": null, + "side": "server", + "type": "SecurityPolicy", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ChannelPage0Mask", + "code": 60, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OperationalDatasetComponents", + "code": 61, + "mfgCode": null, + "side": "server", + "type": "OperationalDatasetComponents", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ActiveNetworkFaultsList", + "code": 62, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x000F", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "WiFi Network Diagnostics", + "code": 54, + "mfgCode": null, + "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "WiFi Network Diagnostics", + "code": 54, + "mfgCode": null, + "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "BSSID", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SecurityType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "SecurityTypeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "WiFiVersion", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "WiFiVersionEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ChannelNumber", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RSSI", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int8s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BeaconLostCount", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BeaconRxCount", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PacketMulticastRxCount", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PacketMulticastTxCount", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PacketUnicastRxCount", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PacketUnicastTxCount", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentMaxRate", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OverrunCount", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Ethernet Network Diagnostics", + "code": 55, + "mfgCode": null, + "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetCounts", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Ethernet Network Diagnostics", + "code": 55, + "mfgCode": null, + "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "PHYRate", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "PHYRateEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FullDuplex", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PacketRxCount", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PacketTxCount", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrCount", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CollisionCount", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OverrunCount", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CarrierDetect", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TimeSinceReset", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Switch", + "code": 59, + "mfgCode": null, + "define": "SWITCH_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Switch", + "code": 59, + "mfgCode": null, + "define": "SWITCH_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "NumberOfPositions", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentPosition", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MultiPressMax", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Administrator Commissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Administrator Commissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "WindowStatus", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "CommissioningWindowStatusEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminFabricIndex", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "fabric_idx", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminVendorId", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Operational Credentials", + "code": 62, + "mfgCode": null, + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AttestationRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "CertificateChainRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "CSRRequest", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "AddNOC", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "UpdateNOC", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "UpdateFabricLabel", + "code": 9, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveFabric", + "code": 10, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddTrustedRootCertificate", + "code": 11, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Operational Credentials", + "code": 62, + "mfgCode": null, + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AttestationResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "CertificateChainResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "CSRResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "NOCResponse", + "code": 8, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "NOCs", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Fabrics", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SupportedFabrics", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CommissionedFabrics", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TrustedRootCertificates", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentFabricIndex", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "KeySetWrite", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetRead", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetRemove", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetReadAllIndices", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "KeySetReadResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "KeySetReadAllIndicesResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "GroupKeyMap", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GroupTable", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxGroupsPerFabric", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxGroupKeysPerFabric", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "LabelList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "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": "User Label", + "code": 65, + "mfgCode": null, + "define": "USER_LABEL_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "User Label", + "code": 65, + "mfgCode": null, + "define": "USER_LABEL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "LabelList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "Door Lock", + "code": 257, + "mfgCode": null, + "define": "DOOR_LOCK_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "LockDoor", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "UnlockDoor", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "UnlockWithTimeout", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetWeekDaySchedule", + "code": 11, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetWeekDaySchedule", + "code": 12, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearWeekDaySchedule", + "code": 13, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetYearDaySchedule", + "code": 14, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetYearDaySchedule", + "code": 15, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearYearDaySchedule", + "code": 16, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetHolidaySchedule", + "code": 17, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetHolidaySchedule", + "code": 18, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearHolidaySchedule", + "code": 19, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "6", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Door Lock", + "code": 257, + "mfgCode": null, + "define": "DOOR_LOCK_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "LockState", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "DlLockState", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LockType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "DlLockType", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ActuatorEnabled", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DoorState", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "DoorStateEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Language", + "code": 33, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LEDSettings", + "code": 34, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "AutoRelockTime", + "code": 35, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoundVolume", + "code": 36, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OperatingMode", + "code": 37, + "mfgCode": null, + "side": "server", + "type": "OperatingModeEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DefaultConfigurationRegister", + "code": 39, + "mfgCode": null, + "side": "server", + "type": "DlDefaultConfigurationRegister", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnableLocalProgramming", + "code": 40, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnableOneTouchLocking", + "code": 41, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnableInsideStatusLED", + "code": 42, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnablePrivacyModeButton", + "code": 43, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "WrongCodeEntryLimit", + "code": 48, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UserCodeTemporaryDisableTime", + "code": 49, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SendPINOverTheAir", + "code": 50, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RequirePINforRemoteOperation", + "code": 51, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "6", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Barrier Control", + "code": 259, + "mfgCode": null, + "define": "BARRIER_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "BarrierControlGoToPercent", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "BarrierControlStop", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Barrier Control", + "code": 259, + "mfgCode": null, + "define": "BARRIER_CONTROL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "barrier moving state", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "barrier safety status", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "bitmap16", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "barrier capabilities", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "barrier position", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Color Control", + "code": 768, + "mfgCode": null, + "define": "COLOR_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "MoveToHue", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveHue", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepHue", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToSaturation", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveSaturation", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepSaturation", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToHueAndSaturation", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToColor", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveColor", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepColor", + "code": 9, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToColorTemperature", + "code": 10, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StopMoveStep", + "code": 71, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveColorTemperature", + "code": 75, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepColorTemperature", + "code": 76, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Color Control", + "code": 768, + "mfgCode": null, + "define": "COLOR_CONTROL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "CurrentHue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentSaturation", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RemainingTime", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentX", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x616B", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentY", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x607D", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DriftCompensation", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CompensationText", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorTemperatureMireds", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00FA", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorMode", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Options", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NumberOfPrimaries", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary1X", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary1Y", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary1Intensity", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary2X", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary2Y", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary2Intensity", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary3X", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary3Y", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary3Intensity", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary4X", + "code": 32, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary4Y", + "code": 33, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary4Intensity", + "code": 34, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary5X", + "code": 36, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary5Y", + "code": 37, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary5Intensity", + "code": 38, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary6X", + "code": 40, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary6Y", + "code": 41, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary6Intensity", + "code": 42, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "WhitePointX", + "code": 48, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "WhitePointY", + "code": 49, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointRX", + "code": 50, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointRY", + "code": 51, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointRIntensity", + "code": 52, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointGX", + "code": 54, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointGY", + "code": 55, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointGIntensity", + "code": 56, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointBX", + "code": 58, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointBY", + "code": 59, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointBIntensity", + "code": 60, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnhancedCurrentHue", + "code": 16384, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnhancedColorMode", + "code": 16385, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorLoopActive", + "code": 16386, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorLoopDirection", + "code": 16387, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorLoopTime", + "code": 16388, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0019", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorCapabilities", + "code": 16394, + "mfgCode": null, + "side": "server", + "type": "bitmap16", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorTempPhysicalMinMireds", + "code": 16395, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorTempPhysicalMaxMireds", + "code": 16396, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFEFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CoupleColorTempToLevelMinMireds", + "code": 16397, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "StartUpColorTemperatureMireds", + "code": 16400, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Temperature Measurement", + "code": 1026, + "mfgCode": null, + "define": "TEMPERATURE_MEASUREMENT_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Temperature Measurement", + "code": 1026, + "mfgCode": null, + "define": "TEMPERATURE_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x8000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x8000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x8000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Relative Humidity Measurement", + "code": 1029, + "mfgCode": null, + "define": "RELATIVE_HUMIDITY_MEASUREMENT_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Relative Humidity Measurement", + "code": 1029, + "mfgCode": null, + "define": "RELATIVE_HUMIDITY_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Unit Testing", + "code": 4294048773, + "mfgCode": null, + "define": "UNIT_TESTING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Test", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "TestNotHandled", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "TestSpecific", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Unit Testing", + "code": 4294048773, + "mfgCode": null, + "define": "UNIT_TESTING_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "TestSpecificResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "boolean", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "false", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "bitmap8", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "Bitmap8MaskMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "bitmap16", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "Bitmap16MaskMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "bitmap32", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "Bitmap32MaskMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "bitmap64", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "Bitmap64MaskMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int8u", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int16u", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int32u", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int64u", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int8s", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "int8s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int16s", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int32s", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int32s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int64s", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "int64s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "enum8", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "enum16", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "enum16", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "octet_string", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "list_int8u", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "list_octet_string", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "list_struct_octet_string", + "code": 28, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 2, + "name": "MA-thermostat", + "deviceTypeRef": { + "code": 769, + "profileId": 259, + "label": "MA-thermostat", + "name": "MA-thermostat" + }, + "deviceTypes": [ + { + "code": 769, + "profileId": 259, + "label": "MA-thermostat", + "name": "MA-thermostat" + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 769 + ], + "deviceTypeName": "MA-thermostat", + "deviceTypeCode": 769, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddGroup", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewGroup", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetGroupMembership", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveGroup", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveAllGroups", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddGroupIfIdentifying", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AddGroupResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewGroupResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetGroupMembershipResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveGroupResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "NameSupport", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "NameSupportBitmap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddScene", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewScene", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveScene", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveAllScenes", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StoreScene", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RecallScene", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetSceneMembership", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AddSceneResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewSceneResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveSceneResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveAllScenesResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StoreSceneResponse", + "code": 4, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetSceneMembershipResponse", + "code": 6, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "SceneCount", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentScene", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentGroup", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "group_id", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SceneValid", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NameSupport", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SceneTableSize", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RemainingCapacity", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/Off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Off", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "On", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Toggle", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/Off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "OnOff", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GlobalSceneControl", + "code": 16384, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OnTime", + "code": 16385, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OffWaitTime", + "code": 16386, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "StartUpOnOff", + "code": 16387, + "mfgCode": null, + "side": "server", + "type": "StartUpOnOffEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "MoveToLevel", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Move", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Step", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Stop", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToLevelWithOnOff", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveWithOnOff", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepWithOnOff", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StopWithOnOff", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "CurrentLevel", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RemainingTime", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinLevel", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxLevel", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFE", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentFrequency", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinFrequency", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxFrequency", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Options", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "LevelControlOptions", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OnOffTransitionTime", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OnLevel", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFE", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OnTransitionTime", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OffTransitionTime", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "DefaultMoveRate", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "StartUpCurrentLevel", + "code": 16384, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "255", + "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": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Binary Input (Basic)", + "code": 15, + "mfgCode": null, + "define": "BINARY_INPUT_BASIC_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Binary Input (Basic)", + "code": 15, + "mfgCode": null, + "define": "BINARY_INPUT_BASIC_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "out of service", + "code": 81, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "present value", + "code": 85, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "status flags", + "code": 111, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Binding", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "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": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Basic Information", + "code": 40, + "mfgCode": null, + "define": "BASIC_INFORMATION_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Basic Information", + "code": 40, + "mfgCode": null, + "define": "BASIC_INFORMATION_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "DataModelRevision", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "10", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorName", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorID", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductName", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductID", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NodeLabel", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Location", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "XX", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersion", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersionString", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersion", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersionString", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ManufacturingDate", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "20210614123456ZZ", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartNumber", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductURL", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "long_char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductLabel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SerialNumber", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LocalConfigDisabled", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Reachable", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UniqueID", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CapabilityMinima", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "CapabilityMinimaStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Provider", + "code": 41, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_PROVIDER_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "QueryImage", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ApplyUpdateRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Provider", + "code": 41, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_PROVIDER_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "ApplyUpdateResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Requestor", + "code": 42, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_REQUESTOR_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Requestor", + "code": 42, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_REQUESTOR_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Power Source", + "code": 47, + "mfgCode": null, + "define": "POWER_SOURCE_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "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": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Power Source", + "code": 47, + "mfgCode": null, + "define": "POWER_SOURCE_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Status", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "PowerSourceStatusEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Order", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Description", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredAssessedInputVoltage", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredAssessedInputFrequency", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredCurrentType", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "WiredCurrentTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredAssessedCurrent", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredNominalVoltage", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredMaximumCurrent", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredPresent", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveWiredFaults", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatVoltage", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatPercentRemaining", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatTimeRemaining", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatChargeLevel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "BatChargeLevelEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplacementNeeded", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplaceability", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "BatReplaceabilityEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatPresent", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveBatFaults", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplacementDescription", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatCommonDesignation", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "BatCommonDesignationEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatANSIDesignation", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatIECDesignation", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatApprovedChemistry", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "BatApprovedChemistryEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatCapacity", + "code": 24, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatQuantity", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatChargeState", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "BatChargeStateEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatTimeToFullCharge", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatFunctionalWhileCharging", + "code": 28, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatChargingCurrent", + "code": 29, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveBatChargeFaults", + "code": 30, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EndpointList", + "code": 31, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "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": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ArmFailSafe", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetRegulatoryConfig", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "ArmFailSafeResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetRegulatoryConfigResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "Breadcrumb", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "o", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BasicCommissioningInfo", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "BasicCommissioningInfo", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SupportsConcurrentConnection", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ScanNetworks", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddOrUpdateWiFiNetwork", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveNetwork", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ConnectNetwork", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ReorderNetwork", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "ScanNetworksResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "NetworkConfigResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ConnectNetworkResponse", + "code": 7, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Switch", + "code": 59, + "mfgCode": null, + "define": "SWITCH_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Switch", + "code": 59, + "mfgCode": null, + "define": "SWITCH_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "NumberOfPositions", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentPosition", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MultiPressMax", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "GroupKeyMap", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GroupTable", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "LabelList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "User Label", + "code": 65, + "mfgCode": null, + "define": "USER_LABEL_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "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": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "User Label", + "code": 65, + "mfgCode": null, + "define": "USER_LABEL_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "LabelList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "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": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "Door Lock", + "code": 257, + "mfgCode": null, + "define": "DOOR_LOCK_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "LockDoor", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "UnlockDoor", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "UnlockWithTimeout", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetWeekDaySchedule", + "code": 11, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetWeekDaySchedule", + "code": 12, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearWeekDaySchedule", + "code": 13, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetYearDaySchedule", + "code": 14, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetYearDaySchedule", + "code": 15, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearYearDaySchedule", + "code": 16, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetHolidaySchedule", + "code": 17, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetHolidaySchedule", + "code": 18, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearHolidaySchedule", + "code": 19, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "6", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Door Lock", + "code": 257, + "mfgCode": null, + "define": "DOOR_LOCK_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "LockState", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "DlLockState", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LockType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "DlLockType", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ActuatorEnabled", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DoorState", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "DoorStateEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Language", + "code": 33, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LEDSettings", + "code": 34, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "AutoRelockTime", + "code": 35, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoundVolume", + "code": 36, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OperatingMode", + "code": 37, + "mfgCode": null, + "side": "server", + "type": "OperatingModeEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DefaultConfigurationRegister", + "code": 39, + "mfgCode": null, + "side": "server", + "type": "DlDefaultConfigurationRegister", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnableLocalProgramming", + "code": 40, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnableOneTouchLocking", + "code": 41, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnableInsideStatusLED", + "code": 42, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnablePrivacyModeButton", + "code": 43, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "WrongCodeEntryLimit", + "code": 48, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UserCodeTemporaryDisableTime", + "code": 49, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SendPINOverTheAir", + "code": 50, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RequirePINforRemoteOperation", + "code": 51, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "6", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Window Covering", + "code": 258, + "mfgCode": null, + "define": "WINDOW_COVERING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "UpOrOpen", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 0 + }, + { + "name": "DownOrClose", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 0 + }, + { + "name": "StopMotion", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 0 + }, + { + "name": "GoToLiftValue", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 0 + }, + { + "name": "GoToLiftPercentage", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 0 + }, + { + "name": "GoToTiltValue", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 0 + }, + { + "name": "GoToTiltPercentage", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Window Covering", + "code": 258, + "mfgCode": null, + "define": "WINDOW_COVERING_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "Type", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "Type", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentPositionLift", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentPositionTilt", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ConfigStatus", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "ConfigStatus", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x03", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentPositionLiftPercentage", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "Percent", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 100, + "reportableChange": 0 + }, + { + "name": "CurrentPositionTiltPercentage", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "Percent", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 100, + "reportableChange": 0 + }, + { + "name": "OperationalStatus", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "OperationalStatus", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 127, + "reportableChange": 0 + }, + { + "name": "TargetPositionLiftPercent100ths", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "Percent100ths", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 10000, + "reportableChange": 0 + }, + { + "name": "TargetPositionTiltPercent100ths", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "Percent100ths", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 10000, + "reportableChange": 0 + }, + { + "name": "EndProductType", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "EndProductType", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentPositionLiftPercent100ths", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "Percent100ths", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 10000, + "reportableChange": 0 + }, + { + "name": "CurrentPositionTiltPercent100ths", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "Percent100ths", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 10000, + "reportableChange": 0 + }, + { + "name": "InstalledOpenLimitLift", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "InstalledClosedLimitLift", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "InstalledOpenLimitTilt", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "InstalledClosedLimitTilt", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Mode", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "Mode", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 15, + "reportableChange": 0 + }, + { + "name": "SafetyStatus", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "SafetyStatus", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Barrier Control", + "code": 259, + "mfgCode": null, + "define": "BARRIER_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "BarrierControlGoToPercent", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "BarrierControlStop", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Barrier Control", + "code": 259, + "mfgCode": null, + "define": "BARRIER_CONTROL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "barrier moving state", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "barrier safety status", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "bitmap16", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "barrier capabilities", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "barrier position", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Pump Configuration and Control", + "code": 512, + "mfgCode": null, + "define": "PUMP_CONFIGURATION_AND_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Pump Configuration and Control", + "code": 512, + "mfgCode": null, + "define": "PUMP_CONFIGURATION_AND_CONTROL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "MaxPressure", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxSpeed", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxFlow", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PumpStatus", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "PumpStatusBitmap", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EffectiveOperationMode", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "OperationModeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EffectiveControlMode", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "ControlModeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Capacity", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OperationMode", + "code": 32, + "mfgCode": null, + "side": "server", + "type": "OperationModeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Thermostat", + "code": 513, + "mfgCode": null, + "define": "THERMOSTAT_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "SetpointRaiseLower", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetWeeklySchedule", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "GetWeeklySchedule", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ClearWeeklySchedule", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Thermostat", + "code": 513, + "mfgCode": null, + "define": "THERMOSTAT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "GetWeeklyScheduleResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "LocalTemperature", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "AbsMinHeatSetpointLimit", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "700", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "AbsMaxHeatSetpointLimit", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "AbsMinCoolSetpointLimit", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1600", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "AbsMaxCoolSetpointLimit", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3200", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PICoolingDemand", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PIHeatingDemand", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HVACSystemTypeConfiguration", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OccupiedCoolingSetpoint", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0A28", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OccupiedHeatingSetpoint", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x07D0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinHeatSetpointLimit", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "700", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxHeatSetpointLimit", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinCoolSetpointLimit", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1600", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxCoolSetpointLimit", + "code": 24, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3200", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinSetpointDeadBand", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int8s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x19", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ControlSequenceOfOperation", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "ThermostatControlSequence", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x04", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SystemMode", + "code": 28, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "StartOfWeek", + "code": 32, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NumberOfWeeklyTransitions", + "code": 33, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "7", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NumberOfDailyTransitions", + "code": 34, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "0x3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Thermostat User Interface Configuration", + "code": 516, + "mfgCode": null, + "define": "THERMOSTAT_USER_INTERFACE_CONFIGURATION_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "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": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Thermostat User Interface Configuration", + "code": 516, + "mfgCode": null, + "define": "THERMOSTAT_USER_INTERFACE_CONFIGURATION_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "TemperatureDisplayMode", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "KeypadLockout", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ScheduleProgrammingVisibility", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 0, + "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": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "Color Control", + "code": 768, + "mfgCode": null, + "define": "COLOR_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "MoveToHue", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveHue", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepHue", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToSaturation", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveSaturation", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepSaturation", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToHueAndSaturation", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToColor", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveColor", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepColor", + "code": 9, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToColorTemperature", + "code": 10, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StopMoveStep", + "code": 71, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveColorTemperature", + "code": 75, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepColorTemperature", + "code": 76, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Color Control", + "code": 768, + "mfgCode": null, + "define": "COLOR_CONTROL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "CurrentHue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentSaturation", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RemainingTime", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentX", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x616B", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentY", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x607D", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DriftCompensation", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CompensationText", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorTemperatureMireds", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00FA", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorMode", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Options", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NumberOfPrimaries", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary1X", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary1Y", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary1Intensity", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary2X", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary2Y", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary2Intensity", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary3X", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary3Y", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary3Intensity", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary4X", + "code": 32, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary4Y", + "code": 33, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary4Intensity", + "code": 34, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary5X", + "code": 36, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary5Y", + "code": 37, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary5Intensity", + "code": 38, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary6X", + "code": 40, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary6Y", + "code": 41, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary6Intensity", + "code": 42, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "WhitePointX", + "code": 48, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "WhitePointY", + "code": 49, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointRX", + "code": 50, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointRY", + "code": 51, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointRIntensity", + "code": 52, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointGX", + "code": 54, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointGY", + "code": 55, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointGIntensity", + "code": 56, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointBX", + "code": 58, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointBY", + "code": 59, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointBIntensity", + "code": 60, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnhancedCurrentHue", + "code": 16384, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnhancedColorMode", + "code": 16385, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorLoopActive", + "code": 16386, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorLoopDirection", + "code": 16387, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorLoopTime", + "code": 16388, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0019", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorCapabilities", + "code": 16394, + "mfgCode": null, + "side": "server", + "type": "bitmap16", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorTempPhysicalMinMireds", + "code": 16395, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorTempPhysicalMaxMireds", + "code": 16396, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFEFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CoupleColorTempToLevelMinMireds", + "code": 16397, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "StartUpColorTemperatureMireds", + "code": 16400, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Temperature Measurement", + "code": 1026, + "mfgCode": null, + "define": "TEMPERATURE_MEASUREMENT_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Temperature Measurement", + "code": 1026, + "mfgCode": null, + "define": "TEMPERATURE_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x8000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x8000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x8000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Pressure Measurement", + "code": 1027, + "mfgCode": null, + "define": "PRESSURE_MEASUREMENT_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Pressure Measurement", + "code": 1027, + "mfgCode": null, + "define": "PRESSURE_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ScaledValue", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ScaledTolerance", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Flow Measurement", + "code": 1028, + "mfgCode": null, + "define": "FLOW_MEASUREMENT_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Flow Measurement", + "code": 1028, + "mfgCode": null, + "define": "FLOW_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Relative Humidity Measurement", + "code": 1029, + "mfgCode": null, + "define": "RELATIVE_HUMIDITY_MEASUREMENT_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Relative Humidity Measurement", + "code": 1029, + "mfgCode": null, + "define": "RELATIVE_HUMIDITY_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Wake on LAN", + "code": 1283, + "mfgCode": null, + "define": "WAKE_ON_LAN_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Wake on LAN", + "code": 1283, + "mfgCode": null, + "define": "WAKE_ON_LAN_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "MACAddress", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Channel", + "code": 1284, + "mfgCode": null, + "define": "CHANNEL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ChangeChannel", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ChangeChannelByNumber", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Channel", + "code": 1284, + "mfgCode": null, + "define": "CHANNEL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "ChannelList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Lineup", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "LineupInfoStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentChannel", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "ChannelInfoStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Target Navigator", + "code": 1285, + "mfgCode": null, + "define": "TARGET_NAVIGATOR_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "NavigateTarget", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Target Navigator", + "code": 1285, + "mfgCode": null, + "define": "TARGET_NAVIGATOR_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "TargetList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Media Playback", + "code": 1286, + "mfgCode": null, + "define": "MEDIA_PLAYBACK_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Play", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "Pause", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "Stop", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "StartOver", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "Previous", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "Next", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "Rewind", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "FastForward", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "SkipForward", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "SkipBackward", + "code": 9, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Media Playback", + "code": 1286, + "mfgCode": null, + "define": "MEDIA_PLAYBACK_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Media Input", + "code": 1287, + "mfgCode": null, + "define": "MEDIA_INPUT_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "SelectInput", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ShowInputStatus", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "HideInputStatus", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RenameInput", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Media Input", + "code": 1287, + "mfgCode": null, + "define": "MEDIA_INPUT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "InputList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Low Power", + "code": 1288, + "mfgCode": null, + "define": "LOW_POWER_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Sleep", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Low Power", + "code": 1288, + "mfgCode": null, + "define": "LOW_POWER_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Keypad Input", + "code": 1289, + "mfgCode": null, + "define": "KEYPAD_INPUT_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "SendKey", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Keypad Input", + "code": 1289, + "mfgCode": null, + "define": "KEYPAD_INPUT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Content Launcher", + "code": 1290, + "mfgCode": null, + "define": "CONTENT_LAUNCHER_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "LaunchContent", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "LaunchURL", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Content Launcher", + "code": 1290, + "mfgCode": null, + "define": "CONTENT_LAUNCHER_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "AcceptHeader", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SupportedStreamingProtocols", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Audio Output", + "code": 1291, + "mfgCode": null, + "define": "AUDIO_OUTPUT_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "SelectOutput", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RenameOutput", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Audio Output", + "code": 1291, + "mfgCode": null, + "define": "AUDIO_OUTPUT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "OutputList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Application Launcher", + "code": 1292, + "mfgCode": null, + "define": "APPLICATION_LAUNCHER_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "LaunchApp", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Application Launcher", + "code": 1292, + "mfgCode": null, + "define": "APPLICATION_LAUNCHER_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "CatalogList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Application Basic", + "code": 1293, + "mfgCode": null, + "define": "APPLICATION_BASIC_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Application Basic", + "code": 1293, + "mfgCode": null, + "define": "APPLICATION_BASIC_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "VendorName", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorID", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ApplicationName", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductID", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Status", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "ApplicationStatusEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ApplicationVersion", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Account Login", + "code": 1294, + "mfgCode": null, + "define": "ACCOUNT_LOGIN_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "GetSetupPIN", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Account Login", + "code": 1294, + "mfgCode": null, + "define": "ACCOUNT_LOGIN_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Unit Testing", + "code": 4294048773, + "mfgCode": null, + "define": "UNIT_TESTING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Test", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "TestNotHandled", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Unit Testing", + "code": 4294048773, + "mfgCode": null, + "define": "UNIT_TESTING_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "TestSpecificResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "boolean", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "false", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "bitmap8", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "Bitmap8MaskMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "bitmap16", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "Bitmap16MaskMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "bitmap32", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "Bitmap32MaskMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "bitmap64", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "Bitmap64MaskMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int8u", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int16u", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int32u", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int64u", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int8s", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "int8s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int16s", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int32s", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int32s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int64s", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "int64s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "enum8", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "enum16", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "enum16", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "octet_string", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "list_int8u", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "list_octet_string", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "list_struct_octet_string", + "code": 28, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "long_octet_string", + "code": 29, + "mfgCode": null, + "side": "server", + "type": "long_octet_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + } + ] + } + ], + "endpoints": [ + { + "endpointTypeName": "MA-rootdevice", + "endpointTypeIndex": 0, + "profileId": 259, + "endpointId": 0, + "networkId": 0 + }, + { + "endpointTypeName": "MA-thermostat", + "endpointTypeIndex": 1, + "profileId": 259, + "endpointId": 1, + "networkId": 0 + } + ], + "log": [] +} \ No newline at end of file diff --git a/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter b/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter new file mode 100644 index 00000000000000..6ab8da13eedb56 --- /dev/null +++ b/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter @@ -0,0 +1,1972 @@ +// This IDL was generated automatically by ZAP. +// It is for view/code review purposes only. + +/** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ +client cluster Identify = 3 { + enum EffectIdentifierEnum : ENUM8 { + kBlink = 0; + kBreathe = 1; + kOkay = 2; + kChannelChange = 11; + kFinishEffect = 254; + kStopEffect = 255; + } + + enum EffectVariantEnum : ENUM8 { + kDefault = 0; + } + + enum IdentifyTypeEnum : ENUM8 { + kNone = 0; + kLightOutput = 1; + kVisibleIndicator = 2; + kAudibleBeep = 3; + kDisplay = 4; + kActuator = 5; + } + + attribute int16u identifyTime = 0; + readonly attribute IdentifyTypeEnum identifyType = 1; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct IdentifyRequest { + INT16U identifyTime = 0; + } + + request struct TriggerEffectRequest { + EffectIdentifierEnum effectIdentifier = 0; + EffectVariantEnum effectVariant = 1; + } + + /** Command description for Identify */ + command access(invoke: manage) Identify(IdentifyRequest): DefaultSuccess = 0; + /** Command description for TriggerEffect */ + command access(invoke: manage) TriggerEffect(TriggerEffectRequest): DefaultSuccess = 64; +} + +/** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ +server cluster Identify = 3 { + enum EffectIdentifierEnum : ENUM8 { + kBlink = 0; + kBreathe = 1; + kOkay = 2; + kChannelChange = 11; + kFinishEffect = 254; + kStopEffect = 255; + } + + enum EffectVariantEnum : ENUM8 { + kDefault = 0; + } + + enum IdentifyTypeEnum : ENUM8 { + kNone = 0; + kLightOutput = 1; + kVisibleIndicator = 2; + kAudibleBeep = 3; + kDisplay = 4; + kActuator = 5; + } + + attribute int16u identifyTime = 0; + readonly attribute IdentifyTypeEnum identifyType = 1; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct IdentifyRequest { + INT16U identifyTime = 0; + } + + command access(invoke: manage) Identify(IdentifyRequest): DefaultSuccess = 0; +} + +/** Attributes and commands for group configuration and manipulation. */ +server cluster Groups = 4 { + bitmap Feature : BITMAP32 { + kGroupNames = 0x1; + } + + bitmap NameSupportBitmap : BITMAP8 { + kGroupNames = 0x80; + } + + readonly attribute NameSupportBitmap nameSupport = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct AddGroupRequest { + group_id groupID = 0; + CHAR_STRING groupName = 1; + } + + request struct ViewGroupRequest { + group_id groupID = 0; + } + + request struct GetGroupMembershipRequest { + group_id groupList[] = 0; + } + + request struct RemoveGroupRequest { + group_id groupID = 0; + } + + request struct AddGroupIfIdentifyingRequest { + group_id groupID = 0; + CHAR_STRING groupName = 1; + } + + response struct AddGroupResponse = 0 { + ENUM8 status = 0; + group_id groupID = 1; + } + + response struct ViewGroupResponse = 1 { + ENUM8 status = 0; + group_id groupID = 1; + CHAR_STRING groupName = 2; + } + + response struct GetGroupMembershipResponse = 2 { + nullable INT8U capacity = 0; + group_id groupList[] = 1; + } + + response struct RemoveGroupResponse = 3 { + ENUM8 status = 0; + group_id groupID = 1; + } + + fabric command access(invoke: manage) AddGroup(AddGroupRequest): AddGroupResponse = 0; + fabric command ViewGroup(ViewGroupRequest): ViewGroupResponse = 1; + fabric command GetGroupMembership(GetGroupMembershipRequest): GetGroupMembershipResponse = 2; + fabric command access(invoke: manage) RemoveGroup(RemoveGroupRequest): RemoveGroupResponse = 3; + fabric command access(invoke: manage) RemoveAllGroups(): DefaultSuccess = 4; + fabric command access(invoke: manage) AddGroupIfIdentifying(AddGroupIfIdentifyingRequest): DefaultSuccess = 5; +} + +/** Attributes and commands for scene configuration and manipulation. */ +server cluster Scenes = 5 { + bitmap Feature : BITMAP32 { + kSceneNames = 0x1; + kExplicit = 0x2; + kTableSize = 0x4; + kFabricScenes = 0x8; + } + + bitmap ScenesCopyMode : BITMAP8 { + kCopyAllScenes = 0x1; + } + + struct AttributeValuePair { + attrib_id attributeID = 0; + int32u attributeValue = 1; + } + + struct ExtensionFieldSet { + cluster_id clusterID = 0; + AttributeValuePair attributeValueList[] = 1; + } + + readonly attribute int8u sceneCount = 0; + readonly attribute int8u currentScene = 1; + readonly attribute group_id currentGroup = 2; + readonly attribute boolean sceneValid = 3; + readonly attribute bitmap8 nameSupport = 4; + readonly attribute int16u sceneTableSize = 6; + readonly attribute int8u remainingCapacity = 7; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct AddSceneRequest { + group_id groupID = 0; + INT8U sceneID = 1; + INT16U transitionTime = 2; + CHAR_STRING sceneName = 3; + ExtensionFieldSet extensionFieldSets[] = 4; + } + + request struct ViewSceneRequest { + group_id groupID = 0; + INT8U sceneID = 1; + } + + request struct RemoveSceneRequest { + group_id groupID = 0; + INT8U sceneID = 1; + } + + request struct RemoveAllScenesRequest { + group_id groupID = 0; + } + + request struct StoreSceneRequest { + group_id groupID = 0; + INT8U sceneID = 1; + } + + request struct RecallSceneRequest { + group_id groupID = 0; + INT8U sceneID = 1; + optional nullable INT16U transitionTime = 2; + } + + request struct GetSceneMembershipRequest { + group_id groupID = 0; + } + + response struct AddSceneResponse = 0 { + status status = 0; + group_id groupID = 1; + INT8U sceneID = 2; + } + + response struct ViewSceneResponse = 1 { + status status = 0; + group_id groupID = 1; + INT8U sceneID = 2; + optional INT16U transitionTime = 3; + optional CHAR_STRING sceneName = 4; + optional ExtensionFieldSet extensionFieldSets[] = 5; + } + + response struct RemoveSceneResponse = 2 { + status status = 0; + group_id groupID = 1; + INT8U sceneID = 2; + } + + response struct RemoveAllScenesResponse = 3 { + status status = 0; + group_id groupID = 1; + } + + response struct StoreSceneResponse = 4 { + status status = 0; + group_id groupID = 1; + INT8U sceneID = 2; + } + + response struct GetSceneMembershipResponse = 6 { + status status = 0; + nullable INT8U capacity = 1; + group_id groupID = 2; + optional INT8U sceneList[] = 3; + } + + fabric command access(invoke: manage) AddScene(AddSceneRequest): AddSceneResponse = 0; + fabric command ViewScene(ViewSceneRequest): ViewSceneResponse = 1; + fabric command access(invoke: manage) RemoveScene(RemoveSceneRequest): RemoveSceneResponse = 2; + fabric command access(invoke: manage) RemoveAllScenes(RemoveAllScenesRequest): RemoveAllScenesResponse = 3; + fabric command access(invoke: manage) StoreScene(StoreSceneRequest): StoreSceneResponse = 4; + fabric command RecallScene(RecallSceneRequest): DefaultSuccess = 5; + fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6; +} + +/** The Descriptor Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for describing a node, its endpoints and clusters. */ +server cluster Descriptor = 29 { + bitmap Feature : BITMAP32 { + kTagList = 0x1; + } + + struct DeviceTypeStruct { + devtype_id deviceType = 0; + int16u revision = 1; + } + + struct SemanticTagStruct { + nullable vendor_id mfgCode = 0; + enum8 namespaceID = 1; + enum8 tag = 2; + optional nullable char_string label = 3; + } + + readonly attribute DeviceTypeStruct deviceTypeList[] = 0; + readonly attribute CLUSTER_ID serverList[] = 1; + readonly attribute CLUSTER_ID clientList[] = 2; + readonly attribute ENDPOINT_NO partsList[] = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** The Binding Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for supporting the binding table. */ +server cluster Binding = 30 { + fabric_scoped struct TargetStruct { + optional node_id node = 1; + optional group_id group = 2; + optional endpoint_no endpoint = 3; + optional cluster_id cluster = 4; + fabric_idx fabricIndex = 254; + } + + attribute TargetStruct binding[] = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** The Access Control Cluster exposes a data model view of a + Node's Access Control List (ACL), which codifies the rules used to manage + and enforce Access Control for the Node's endpoints and their associated + cluster instances. */ +server cluster AccessControl = 31 { + enum AccessControlEntryAuthModeEnum : ENUM8 { + kPASE = 1; + kCASE = 2; + kGroup = 3; + } + + enum AccessControlEntryPrivilegeEnum : ENUM8 { + kView = 1; + kProxyView = 2; + kOperate = 3; + kManage = 4; + kAdminister = 5; + } + + enum ChangeTypeEnum : ENUM8 { + kChanged = 0; + kAdded = 1; + kRemoved = 2; + } + + struct AccessControlTargetStruct { + nullable cluster_id cluster = 0; + nullable endpoint_no endpoint = 1; + nullable devtype_id deviceType = 2; + } + + fabric_scoped struct AccessControlEntryStruct { + fabric_sensitive AccessControlEntryPrivilegeEnum privilege = 1; + fabric_sensitive AccessControlEntryAuthModeEnum authMode = 2; + nullable fabric_sensitive int64u subjects[] = 3; + nullable fabric_sensitive AccessControlTargetStruct targets[] = 4; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct AccessControlExtensionStruct { + fabric_sensitive octet_string<128> data = 1; + fabric_idx fabricIndex = 254; + } + + fabric_sensitive info event access(read: administer) AccessControlEntryChanged = 0 { + nullable node_id adminNodeID = 1; + nullable INT16U adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable AccessControlEntryStruct latestValue = 4; + fabric_idx fabricIndex = 254; + } + + fabric_sensitive info event access(read: administer) AccessControlExtensionChanged = 1 { + nullable node_id adminNodeID = 1; + nullable INT16U adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable AccessControlExtensionStruct latestValue = 4; + fabric_idx fabricIndex = 254; + } + + attribute access(read: administer, write: administer) AccessControlEntryStruct acl[] = 0; + attribute access(read: administer, write: administer) AccessControlExtensionStruct extension[] = 1; + readonly attribute int16u subjectsPerAccessControlEntry = 2; + readonly attribute int16u targetsPerAccessControlEntry = 3; + readonly attribute int16u accessControlEntriesPerFabric = 4; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** This cluster provides attributes and events for determining basic information about Nodes, which supports both + Commissioning and operational determination of Node characteristics, such as Vendor ID, Product ID and serial number, + which apply to the whole Node. Also allows setting user device information such as location. */ +server cluster BasicInformation = 40 { + enum ColorEnum : ENUM8 { + kBlack = 0; + kNavy = 1; + kGreen = 2; + kTeal = 3; + kMaroon = 4; + kPurple = 5; + kOlive = 6; + kGray = 7; + kBlue = 8; + kLime = 9; + kAqua = 10; + kRed = 11; + kFuchsia = 12; + kYellow = 13; + kWhite = 14; + kNickel = 15; + kChrome = 16; + kBrass = 17; + kCopper = 18; + kSilver = 19; + kGold = 20; + } + + enum ProductFinishEnum : ENUM8 { + kOther = 0; + kMatte = 1; + kSatin = 2; + kPolished = 3; + kRugged = 4; + kFabric = 5; + } + + struct CapabilityMinimaStruct { + int16u caseSessionsPerFabric = 0; + int16u subscriptionsPerFabric = 1; + } + + struct ProductAppearanceStruct { + ProductFinishEnum finish = 0; + nullable ColorEnum primaryColor = 1; + } + + critical event StartUp = 0 { + INT32U softwareVersion = 0; + } + + critical event ShutDown = 1 { + } + + info event Leave = 2 { + fabric_idx fabricIndex = 0; + } + + info event ReachableChanged = 3 { + boolean reachableNewValue = 0; + } + + readonly attribute int16u dataModelRevision = 0; + readonly attribute char_string<32> vendorName = 1; + readonly attribute vendor_id vendorID = 2; + readonly attribute char_string<32> productName = 3; + readonly attribute int16u productID = 4; + attribute access(write: manage) char_string<32> nodeLabel = 5; + attribute access(write: administer) char_string<2> location = 6; + readonly attribute int16u hardwareVersion = 7; + readonly attribute char_string<64> hardwareVersionString = 8; + readonly attribute int32u softwareVersion = 9; + readonly attribute char_string<64> softwareVersionString = 10; + readonly attribute char_string<16> manufacturingDate = 11; + readonly attribute char_string<32> partNumber = 12; + readonly attribute long_char_string<256> productURL = 13; + readonly attribute char_string<64> productLabel = 14; + readonly attribute char_string<32> serialNumber = 15; + attribute access(write: manage) boolean localConfigDisabled = 16; + readonly attribute boolean reachable = 17; + readonly attribute char_string<32> uniqueID = 18; + readonly attribute CapabilityMinimaStruct capabilityMinima = 19; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Provides an interface for providing OTA software updates */ +client cluster OtaSoftwareUpdateProvider = 41 { + enum OTAApplyUpdateAction : ENUM8 { + kProceed = 0; + kAwaitNextAction = 1; + kDiscontinue = 2; + } + + enum OTADownloadProtocol : ENUM8 { + kBDXSynchronous = 0; + kBDXAsynchronous = 1; + kHTTPS = 2; + kVendorSpecific = 3; + } + + enum OTAQueryStatus : ENUM8 { + kUpdateAvailable = 0; + kBusy = 1; + kNotAvailable = 2; + kDownloadProtocolNotSupported = 3; + } + + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct QueryImageRequest { + vendor_id vendorID = 0; + INT16U productID = 1; + INT32U softwareVersion = 2; + OTADownloadProtocol protocolsSupported[] = 3; + optional INT16U hardwareVersion = 4; + optional CHAR_STRING<2> location = 5; + optional BOOLEAN requestorCanConsent = 6; + optional OCTET_STRING<512> metadataForProvider = 7; + } + + response struct QueryImageResponse = 1 { + OTAQueryStatus status = 0; + optional INT32U delayedActionTime = 1; + optional CHAR_STRING<256> imageURI = 2; + optional INT32U softwareVersion = 3; + optional CHAR_STRING<64> softwareVersionString = 4; + optional OCTET_STRING<32> updateToken = 5; + optional BOOLEAN userConsentNeeded = 6; + optional OCTET_STRING<512> metadataForRequestor = 7; + } + + request struct ApplyUpdateRequestRequest { + OCTET_STRING<32> updateToken = 0; + INT32U newVersion = 1; + } + + response struct ApplyUpdateResponse = 3 { + OTAApplyUpdateAction action = 0; + INT32U delayedActionTime = 1; + } + + request struct NotifyUpdateAppliedRequest { + OCTET_STRING<32> updateToken = 0; + INT32U softwareVersion = 1; + } + + /** Determine availability of a new Software Image */ + command QueryImage(QueryImageRequest): QueryImageResponse = 0; + /** Determine next action to take for a downloaded Software Image */ + command ApplyUpdateRequest(ApplyUpdateRequestRequest): ApplyUpdateResponse = 2; + /** Notify OTA Provider that an update was applied */ + command NotifyUpdateApplied(NotifyUpdateAppliedRequest): DefaultSuccess = 4; +} + +/** Provides an interface for downloading and applying OTA software updates */ +server cluster OtaSoftwareUpdateRequestor = 42 { + enum OTAAnnouncementReason : ENUM8 { + kSimpleAnnouncement = 0; + kUpdateAvailable = 1; + kUrgentUpdateAvailable = 2; + } + + enum OTAChangeReasonEnum : ENUM8 { + kUnknown = 0; + kSuccess = 1; + kFailure = 2; + kTimeOut = 3; + kDelayByProvider = 4; + } + + enum OTAUpdateStateEnum : ENUM8 { + kUnknown = 0; + kIdle = 1; + kQuerying = 2; + kDelayedOnQuery = 3; + kDownloading = 4; + kApplying = 5; + kDelayedOnApply = 6; + kRollingBack = 7; + kDelayedOnUserConsent = 8; + } + + fabric_scoped struct ProviderLocation { + node_id providerNodeID = 1; + endpoint_no endpoint = 2; + fabric_idx fabricIndex = 254; + } + + info event StateTransition = 0 { + OTAUpdateStateEnum previousState = 0; + OTAUpdateStateEnum newState = 1; + OTAChangeReasonEnum reason = 2; + nullable INT32U targetSoftwareVersion = 3; + } + + critical event VersionApplied = 1 { + INT32U softwareVersion = 0; + INT16U productID = 1; + } + + info event DownloadError = 2 { + INT32U softwareVersion = 0; + INT64U bytesDownloaded = 1; + nullable INT8U progressPercent = 2; + nullable INT64S platformCode = 3; + } + + attribute ProviderLocation defaultOTAProviders[] = 0; + readonly attribute boolean updatePossible = 1; + readonly attribute OTAUpdateStateEnum updateState = 2; + readonly attribute nullable int8u updateStateProgress = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct AnnounceOTAProviderRequest { + node_id providerNodeID = 0; + vendor_id vendorID = 1; + OTAAnnouncementReason announcementReason = 2; + optional OCTET_STRING<512> metadataForNode = 3; + endpoint_no endpoint = 4; + } + + command AnnounceOTAProvider(AnnounceOTAProviderRequest): DefaultSuccess = 0; +} + +/** Nodes should be expected to be deployed to any and all regions of the world. These global regions + may have differing common languages, units of measurements, and numerical formatting + standards. As such, Nodes that visually or audibly convey information need a mechanism by which + they can be configured to use a user’s preferred language, units, etc */ +server cluster LocalizationConfiguration = 43 { + attribute char_string<35> activeLocale = 0; + readonly attribute CHAR_STRING supportedLocales[] = 1; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Nodes should be expected to be deployed to any and all regions of the world. These global regions + may have differing preferences for how dates and times are conveyed. As such, Nodes that visually + or audibly convey time information need a mechanism by which they can be configured to use a + user’s preferred format. */ +server cluster TimeFormatLocalization = 44 { + enum CalendarTypeEnum : ENUM8 { + kBuddhist = 0; + kChinese = 1; + kCoptic = 2; + kEthiopian = 3; + kGregorian = 4; + kHebrew = 5; + kIndian = 6; + kIslamic = 7; + kJapanese = 8; + kKorean = 9; + kPersian = 10; + kTaiwanese = 11; + } + + enum HourFormatEnum : ENUM8 { + k12hr = 0; + k24hr = 1; + } + + bitmap Feature : BITMAP32 { + kCalendarFormat = 0x1; + } + + attribute HourFormatEnum hourFormat = 0; + attribute CalendarTypeEnum activeCalendarType = 1; + readonly attribute CalendarTypeEnum supportedCalendarTypes[] = 2; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Nodes should be expected to be deployed to any and all regions of the world. These global regions + may have differing preferences for the units in which values are conveyed in communication to a + user. As such, Nodes that visually or audibly convey measurable values to the user need a + mechanism by which they can be configured to use a user’s preferred unit. */ +server cluster UnitLocalization = 45 { + enum TempUnitEnum : ENUM8 { + kFahrenheit = 0; + kCelsius = 1; + kKelvin = 2; + } + + bitmap Feature : BITMAP32 { + kTemperatureUnit = 0x1; + } + + attribute TempUnitEnum temperatureUnit = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** This cluster is used to describe the configuration and capabilities of a physical power source that provides power to the Node. */ +server cluster PowerSource = 47 { + enum BatApprovedChemistryEnum : ENUM16 { + kUnspecified = 0; + kAlkaline = 1; + kLithiumCarbonFluoride = 2; + kLithiumChromiumOxide = 3; + kLithiumCopperOxide = 4; + kLithiumIronDisulfide = 5; + kLithiumManganeseDioxide = 6; + kLithiumThionylChloride = 7; + kMagnesium = 8; + kMercuryOxide = 9; + kNickelOxyhydride = 10; + kSilverOxide = 11; + kZincAir = 12; + kZincCarbon = 13; + kZincChloride = 14; + kZincManganeseDioxide = 15; + kLeadAcid = 16; + kLithiumCobaltOxide = 17; + kLithiumIon = 18; + kLithiumIonPolymer = 19; + kLithiumIronPhosphate = 20; + kLithiumSulfur = 21; + kLithiumTitanate = 22; + kNickelCadmium = 23; + kNickelHydrogen = 24; + kNickelIron = 25; + kNickelMetalHydride = 26; + kNickelZinc = 27; + kSilverZinc = 28; + kSodiumIon = 29; + kSodiumSulfur = 30; + kZincBromide = 31; + kZincCerium = 32; + } + + enum BatChargeFaultEnum : ENUM8 { + kUnspecified = 0; + kAmbientTooHot = 1; + kAmbientTooCold = 2; + kBatteryTooHot = 3; + kBatteryTooCold = 4; + kBatteryAbsent = 5; + kBatteryOverVoltage = 6; + kBatteryUnderVoltage = 7; + kChargerOverVoltage = 8; + kChargerUnderVoltage = 9; + kSafetyTimeout = 10; + } + + enum BatChargeLevelEnum : ENUM8 { + kOK = 0; + kWarning = 1; + kCritical = 2; + } + + enum BatChargeStateEnum : ENUM8 { + kUnknown = 0; + kIsCharging = 1; + kIsAtFullCharge = 2; + kIsNotCharging = 3; + } + + enum BatCommonDesignationEnum : ENUM16 { + kUnspecified = 0; + kAAA = 1; + kAA = 2; + kC = 3; + kD = 4; + k4v5 = 5; + k6v0 = 6; + k9v0 = 7; + k12AA = 8; + kAAAA = 9; + kA = 10; + kB = 11; + kF = 12; + kN = 13; + kNo6 = 14; + kSubC = 15; + kA23 = 16; + kA27 = 17; + kBA5800 = 18; + kDuplex = 19; + k4SR44 = 20; + k523 = 21; + k531 = 22; + k15v0 = 23; + k22v5 = 24; + k30v0 = 25; + k45v0 = 26; + k67v5 = 27; + kJ = 28; + kCR123A = 29; + kCR2 = 30; + k2CR5 = 31; + kCRP2 = 32; + kCRV3 = 33; + kSR41 = 34; + kSR43 = 35; + kSR44 = 36; + kSR45 = 37; + kSR48 = 38; + kSR54 = 39; + kSR55 = 40; + kSR57 = 41; + kSR58 = 42; + kSR59 = 43; + kSR60 = 44; + kSR63 = 45; + kSR64 = 46; + kSR65 = 47; + kSR66 = 48; + kSR67 = 49; + kSR68 = 50; + kSR69 = 51; + kSR516 = 52; + kSR731 = 53; + kSR712 = 54; + kLR932 = 55; + kA5 = 56; + kA10 = 57; + kA13 = 58; + kA312 = 59; + kA675 = 60; + kAC41E = 61; + k10180 = 62; + k10280 = 63; + k10440 = 64; + k14250 = 65; + k14430 = 66; + k14500 = 67; + k14650 = 68; + k15270 = 69; + k16340 = 70; + kRCR123A = 71; + k17500 = 72; + k17670 = 73; + k18350 = 74; + k18500 = 75; + k18650 = 76; + k19670 = 77; + k25500 = 78; + k26650 = 79; + k32600 = 80; + } + + enum BatFaultEnum : ENUM8 { + kUnspecified = 0; + kOverTemp = 1; + kUnderTemp = 2; + } + + enum BatReplaceabilityEnum : ENUM8 { + kUnspecified = 0; + kNotReplaceable = 1; + kUserReplaceable = 2; + kFactoryReplaceable = 3; + } + + enum PowerSourceStatusEnum : ENUM8 { + kUnspecified = 0; + kActive = 1; + kStandby = 2; + kUnavailable = 3; + } + + enum WiredCurrentTypeEnum : ENUM8 { + kAC = 0; + kDC = 1; + } + + enum WiredFaultEnum : ENUM8 { + kUnspecified = 0; + kOverVoltage = 1; + kUnderVoltage = 2; + } + + bitmap Feature : BITMAP32 { + kWired = 0x1; + kBattery = 0x2; + kRechargeable = 0x4; + kReplaceable = 0x8; + } + + struct BatChargeFaultChangeType { + BatChargeFaultEnum current[] = 0; + BatChargeFaultEnum previous[] = 1; + } + + struct BatFaultChangeType { + BatFaultEnum current[] = 0; + BatFaultEnum previous[] = 1; + } + + struct WiredFaultChangeType { + WiredFaultEnum current[] = 0; + WiredFaultEnum previous[] = 1; + } + + info event WiredFaultChange = 0 { + WiredFaultEnum current[] = 0; + WiredFaultEnum previous[] = 1; + } + + info event BatFaultChange = 1 { + BatFaultEnum current[] = 0; + BatFaultEnum previous[] = 1; + } + + info event BatChargeFaultChange = 2 { + BatChargeFaultEnum current[] = 0; + BatChargeFaultEnum previous[] = 1; + } + + readonly attribute PowerSourceStatusEnum status = 0; + readonly attribute int8u order = 1; + readonly attribute char_string<60> description = 2; + readonly attribute WiredCurrentTypeEnum wiredCurrentType = 5; + readonly attribute endpoint_no endpointList[] = 31; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** This cluster is used to manage global aspects of the Commissioning flow. */ +server cluster GeneralCommissioning = 48 { + enum CommissioningErrorEnum : ENUM8 { + kOK = 0; + kValueOutsideRange = 1; + kInvalidAuthentication = 2; + kNoFailSafe = 3; + kBusyWithOtherAdmin = 4; + } + + enum RegulatoryLocationTypeEnum : ENUM8 { + kIndoor = 0; + kOutdoor = 1; + kIndoorOutdoor = 2; + } + + struct BasicCommissioningInfo { + int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; + } + + attribute access(write: administer) int64u breadcrumb = 0; + readonly attribute BasicCommissioningInfo basicCommissioningInfo = 1; + readonly attribute RegulatoryLocationTypeEnum regulatoryConfig = 2; + readonly attribute RegulatoryLocationTypeEnum locationCapability = 3; + readonly attribute boolean supportsConcurrentConnection = 4; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct ArmFailSafeRequest { + INT16U expiryLengthSeconds = 0; + INT64U breadcrumb = 1; + } + + request struct SetRegulatoryConfigRequest { + RegulatoryLocationTypeEnum newRegulatoryConfig = 0; + CHAR_STRING countryCode = 1; + INT64U breadcrumb = 2; + } + + response struct ArmFailSafeResponse = 1 { + CommissioningErrorEnum errorCode = 0; + CHAR_STRING debugText = 1; + } + + response struct SetRegulatoryConfigResponse = 3 { + CommissioningErrorEnum errorCode = 0; + CHAR_STRING debugText = 1; + } + + response struct CommissioningCompleteResponse = 5 { + CommissioningErrorEnum errorCode = 0; + CHAR_STRING debugText = 1; + } + + command access(invoke: administer) ArmFailSafe(ArmFailSafeRequest): ArmFailSafeResponse = 0; + command access(invoke: administer) SetRegulatoryConfig(SetRegulatoryConfigRequest): SetRegulatoryConfigResponse = 2; + fabric command access(invoke: administer) CommissioningComplete(): CommissioningCompleteResponse = 4; +} + +/** Functionality to configure, enable, disable network credentials and access on a Matter device. */ +server cluster NetworkCommissioning = 49 { + enum NetworkCommissioningStatusEnum : ENUM8 { + kSuccess = 0; + kOutOfRange = 1; + kBoundsExceeded = 2; + kNetworkIDNotFound = 3; + kDuplicateNetworkID = 4; + kNetworkNotFound = 5; + kRegulatoryError = 6; + kAuthFailure = 7; + kUnsupportedSecurity = 8; + kOtherConnectionFailure = 9; + kIPV6Failed = 10; + kIPBindFailed = 11; + kUnknownError = 12; + } + + enum WiFiBandEnum : ENUM8 { + k2G4 = 0; + k3G65 = 1; + k5G = 2; + k6G = 3; + k60G = 4; + k1G = 5; + } + + bitmap Feature : BITMAP32 { + kWiFiNetworkInterface = 0x1; + kThreadNetworkInterface = 0x2; + kEthernetNetworkInterface = 0x4; + } + + bitmap WiFiSecurityBitmap : BITMAP8 { + kUnencrypted = 0x1; + kWEP = 0x2; + kWPAPersonal = 0x4; + kWPA2Personal = 0x8; + kWPA3Personal = 0x10; + } + + struct NetworkInfoStruct { + octet_string<32> networkID = 0; + boolean connected = 1; + } + + struct ThreadInterfaceScanResultStruct { + int16u panId = 0; + int64u extendedPanId = 1; + char_string<16> networkName = 2; + int16u channel = 3; + int8u version = 4; + octet_string<8> extendedAddress = 5; + int8s rssi = 6; + int8u lqi = 7; + } + + struct WiFiInterfaceScanResultStruct { + WiFiSecurityBitmap security = 0; + octet_string<32> ssid = 1; + octet_string<6> bssid = 2; + int16u channel = 3; + WiFiBandEnum wiFiBand = 4; + int8s rssi = 5; + } + + readonly attribute access(read: administer) int8u maxNetworks = 0; + readonly attribute access(read: administer) NetworkInfoStruct networks[] = 1; + readonly attribute int8u scanMaxTimeSeconds = 2; + readonly attribute int8u connectMaxTimeSeconds = 3; + attribute access(write: administer) boolean interfaceEnabled = 4; + readonly attribute access(read: administer) nullable NetworkCommissioningStatusEnum lastNetworkingStatus = 5; + readonly attribute access(read: administer) nullable octet_string<32> lastNetworkID = 6; + readonly attribute access(read: administer) nullable int32s lastConnectErrorValue = 7; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct ScanNetworksRequest { + optional nullable OCTET_STRING<32> ssid = 0; + optional INT64U breadcrumb = 1; + } + + request struct AddOrUpdateWiFiNetworkRequest { + OCTET_STRING<32> ssid = 0; + OCTET_STRING<64> credentials = 1; + optional INT64U breadcrumb = 2; + } + + request struct AddOrUpdateThreadNetworkRequest { + OCTET_STRING<254> operationalDataset = 0; + optional INT64U breadcrumb = 1; + } + + request struct RemoveNetworkRequest { + OCTET_STRING<32> networkID = 0; + optional INT64U breadcrumb = 1; + } + + request struct ConnectNetworkRequest { + OCTET_STRING<32> networkID = 0; + optional INT64U breadcrumb = 1; + } + + request struct ReorderNetworkRequest { + OCTET_STRING<32> networkID = 0; + INT8U networkIndex = 1; + optional INT64U breadcrumb = 2; + } + + response struct ScanNetworksResponse = 1 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional CHAR_STRING debugText = 1; + optional WiFiInterfaceScanResultStruct wiFiScanResults[] = 2; + optional ThreadInterfaceScanResultStruct threadScanResults[] = 3; + } + + response struct NetworkConfigResponse = 5 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional CHAR_STRING<512> debugText = 1; + optional INT8U networkIndex = 2; + } + + response struct ConnectNetworkResponse = 7 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional CHAR_STRING debugText = 1; + nullable INT32S errorValue = 2; + } + + command access(invoke: administer) ScanNetworks(ScanNetworksRequest): ScanNetworksResponse = 0; + command access(invoke: administer) AddOrUpdateWiFiNetwork(AddOrUpdateWiFiNetworkRequest): NetworkConfigResponse = 2; + command access(invoke: administer) AddOrUpdateThreadNetwork(AddOrUpdateThreadNetworkRequest): NetworkConfigResponse = 3; + command access(invoke: administer) RemoveNetwork(RemoveNetworkRequest): NetworkConfigResponse = 4; + command access(invoke: administer) ConnectNetwork(ConnectNetworkRequest): ConnectNetworkResponse = 6; + command access(invoke: administer) ReorderNetwork(ReorderNetworkRequest): NetworkConfigResponse = 8; +} + +/** The General Diagnostics Cluster, along with other diagnostics clusters, provide a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems. */ +server cluster GeneralDiagnostics = 51 { + enum BootReasonEnum : ENUM8 { + kUnspecified = 0; + kPowerOnReboot = 1; + kBrownOutReset = 2; + kSoftwareWatchdogReset = 3; + kHardwareWatchdogReset = 4; + kSoftwareUpdateCompleted = 5; + kSoftwareReset = 6; + } + + enum HardwareFaultEnum : ENUM8 { + kUnspecified = 0; + kRadio = 1; + kSensor = 2; + kResettableOverTemp = 3; + kNonResettableOverTemp = 4; + kPowerSource = 5; + kVisualDisplayFault = 6; + kAudioOutputFault = 7; + kUserInterfaceFault = 8; + kNonVolatileMemoryError = 9; + kTamperDetected = 10; + } + + enum InterfaceTypeEnum : ENUM8 { + kUnspecified = 0; + kWiFi = 1; + kEthernet = 2; + kCellular = 3; + kThread = 4; + } + + enum NetworkFaultEnum : ENUM8 { + kUnspecified = 0; + kHardwareFailure = 1; + kNetworkJammed = 2; + kConnectionFailed = 3; + } + + enum RadioFaultEnum : ENUM8 { + kUnspecified = 0; + kWiFiFault = 1; + kCellularFault = 2; + kThreadFault = 3; + kNFCFault = 4; + kBLEFault = 5; + kEthernetFault = 6; + } + + struct NetworkInterface { + char_string<32> name = 0; + boolean isOperational = 1; + nullable boolean offPremiseServicesReachableIPv4 = 2; + nullable boolean offPremiseServicesReachableIPv6 = 3; + octet_string<8> hardwareAddress = 4; + octet_string IPv4Addresses[] = 5; + octet_string IPv6Addresses[] = 6; + InterfaceTypeEnum type = 7; + } + + critical event HardwareFaultChange = 0 { + HardwareFaultEnum current[] = 0; + HardwareFaultEnum previous[] = 1; + } + + critical event RadioFaultChange = 1 { + RadioFaultEnum current[] = 0; + RadioFaultEnum previous[] = 1; + } + + critical event NetworkFaultChange = 2 { + NetworkFaultEnum current[] = 0; + NetworkFaultEnum previous[] = 1; + } + + critical event BootReason = 3 { + BootReasonEnum bootReason = 0; + } + + readonly attribute NetworkInterface networkInterfaces[] = 0; + readonly attribute int16u rebootCount = 1; + readonly attribute int64u upTime = 2; + readonly attribute int32u totalOperationalHours = 3; + readonly attribute BootReasonEnum bootReason = 4; + readonly attribute HardwareFaultEnum activeHardwareFaults[] = 5; + readonly attribute RadioFaultEnum activeRadioFaults[] = 6; + readonly attribute NetworkFaultEnum activeNetworkFaults[] = 7; + readonly attribute boolean testEventTriggersEnabled = 8; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct TestEventTriggerRequest { + OCTET_STRING<16> enableKey = 0; + INT64U eventTrigger = 1; + } + + command access(invoke: manage) TestEventTrigger(TestEventTriggerRequest): DefaultSuccess = 0; +} + +/** The Wi-Fi Network Diagnostics Cluster provides a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems. */ +server cluster WiFiNetworkDiagnostics = 54 { + enum AssociationFailureCauseEnum : ENUM8 { + kUnknown = 0; + kAssociationFailed = 1; + kAuthenticationFailed = 2; + kSsidNotFound = 3; + } + + enum ConnectionStatusEnum : ENUM8 { + kConnected = 0; + kNotConnected = 1; + } + + enum SecurityTypeEnum : ENUM8 { + kUnspecified = 0; + kNone = 1; + kWEP = 2; + kWPA = 3; + kWPA2 = 4; + kWPA3 = 5; + } + + enum WiFiVersionEnum : ENUM8 { + kA = 0; + kB = 1; + kG = 2; + kN = 3; + kAc = 4; + kAx = 5; + kAh = 6; + } + + bitmap Feature : BITMAP32 { + kPacketCounts = 0x1; + kErrorCounts = 0x2; + } + + info event Disconnection = 0 { + INT16U reasonCode = 0; + } + + info event AssociationFailure = 1 { + AssociationFailureCauseEnum associationFailure = 0; + INT16U status = 1; + } + + info event ConnectionStatus = 2 { + ConnectionStatusEnum connectionStatus = 0; + } + + readonly attribute nullable octet_string<6> bssid = 0; + readonly attribute nullable SecurityTypeEnum securityType = 1; + readonly attribute nullable WiFiVersionEnum wiFiVersion = 2; + readonly attribute nullable int16u channelNumber = 3; + readonly attribute nullable int8s rssi = 4; + readonly attribute nullable int32u beaconLostCount = 5; + readonly attribute nullable int32u beaconRxCount = 6; + readonly attribute nullable int32u packetMulticastRxCount = 7; + readonly attribute nullable int32u packetMulticastTxCount = 8; + readonly attribute nullable int32u packetUnicastRxCount = 9; + readonly attribute nullable int32u packetUnicastTxCount = 10; + readonly attribute nullable int64u currentMaxRate = 11; + readonly attribute nullable int64u overrunCount = 12; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Commands to trigger a Node to allow a new Administrator to commission it. */ +server cluster AdministratorCommissioning = 60 { + enum CommissioningWindowStatusEnum : ENUM8 { + kWindowNotOpen = 0; + kEnhancedWindowOpen = 1; + kBasicWindowOpen = 2; + } + + enum StatusCode : ENUM8 { + kBusy = 2; + kPAKEParameterError = 3; + kWindowNotOpen = 4; + } + + readonly attribute CommissioningWindowStatusEnum windowStatus = 0; + readonly attribute nullable fabric_idx adminFabricIndex = 1; + readonly attribute nullable int16u adminVendorId = 2; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct OpenCommissioningWindowRequest { + INT16U commissioningTimeout = 0; + OCTET_STRING PAKEPasscodeVerifier = 1; + INT16U discriminator = 2; + INT32U iterations = 3; + OCTET_STRING salt = 4; + } + + request struct OpenBasicCommissioningWindowRequest { + INT16U commissioningTimeout = 0; + } + + timed command access(invoke: administer) OpenCommissioningWindow(OpenCommissioningWindowRequest): DefaultSuccess = 0; + timed command access(invoke: administer) OpenBasicCommissioningWindow(OpenBasicCommissioningWindowRequest): DefaultSuccess = 1; + timed command access(invoke: administer) RevokeCommissioning(): DefaultSuccess = 2; +} + +/** This cluster is used to add or remove Operational Credentials on a Commissionee or Node, as well as manage the associated Fabrics. */ +server cluster OperationalCredentials = 62 { + enum CertificateChainTypeEnum : ENUM8 { + kDACCertificate = 1; + kPAICertificate = 2; + } + + enum NodeOperationalCertStatusEnum : ENUM8 { + kOK = 0; + kInvalidPublicKey = 1; + kInvalidNodeOpId = 2; + kInvalidNOC = 3; + kMissingCsr = 4; + kTableFull = 5; + kInvalidAdminSubject = 6; + kFabricConflict = 9; + kLabelConflict = 10; + kInvalidFabricIndex = 11; + } + + fabric_scoped struct FabricDescriptorStruct { + octet_string<65> rootPublicKey = 1; + vendor_id vendorID = 2; + fabric_id fabricID = 3; + node_id nodeID = 4; + char_string<32> label = 5; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct NOCStruct { + fabric_sensitive octet_string noc = 1; + nullable fabric_sensitive octet_string icac = 2; + fabric_idx fabricIndex = 254; + } + + readonly attribute access(read: administer) NOCStruct NOCs[] = 0; + readonly attribute FabricDescriptorStruct fabrics[] = 1; + readonly attribute int8u supportedFabrics = 2; + readonly attribute int8u commissionedFabrics = 3; + readonly attribute OCTET_STRING trustedRootCertificates[] = 4; + readonly attribute int8u currentFabricIndex = 5; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct AttestationRequestRequest { + OCTET_STRING attestationNonce = 0; + } + + request struct CertificateChainRequestRequest { + CertificateChainTypeEnum certificateType = 0; + } + + request struct CSRRequestRequest { + OCTET_STRING CSRNonce = 0; + optional boolean isForUpdateNOC = 1; + } + + request struct AddNOCRequest { + OCTET_STRING NOCValue = 0; + optional OCTET_STRING ICACValue = 1; + OCTET_STRING IPKValue = 2; + Int64u caseAdminSubject = 3; + VENDOR_ID adminVendorId = 4; + } + + request struct UpdateNOCRequest { + OCTET_STRING NOCValue = 0; + optional OCTET_STRING ICACValue = 1; + } + + request struct UpdateFabricLabelRequest { + CHAR_STRING<32> label = 0; + } + + request struct RemoveFabricRequest { + fabric_idx fabricIndex = 0; + } + + request struct AddTrustedRootCertificateRequest { + OCTET_STRING rootCACertificate = 0; + } + + response struct AttestationResponse = 1 { + OCTET_STRING attestationElements = 0; + OCTET_STRING attestationSignature = 1; + } + + response struct CertificateChainResponse = 3 { + OCTET_STRING certificate = 0; + } + + response struct CSRResponse = 5 { + OCTET_STRING NOCSRElements = 0; + OCTET_STRING attestationSignature = 1; + } + + response struct NOCResponse = 8 { + NodeOperationalCertStatusEnum statusCode = 0; + optional fabric_idx fabricIndex = 1; + optional CHAR_STRING debugText = 2; + } + + command access(invoke: administer) AttestationRequest(AttestationRequestRequest): AttestationResponse = 0; + command access(invoke: administer) CertificateChainRequest(CertificateChainRequestRequest): CertificateChainResponse = 2; + command access(invoke: administer) CSRRequest(CSRRequestRequest): CSRResponse = 4; + command access(invoke: administer) AddNOC(AddNOCRequest): NOCResponse = 6; + fabric command access(invoke: administer) UpdateNOC(UpdateNOCRequest): NOCResponse = 7; + fabric command access(invoke: administer) UpdateFabricLabel(UpdateFabricLabelRequest): NOCResponse = 9; + command access(invoke: administer) RemoveFabric(RemoveFabricRequest): NOCResponse = 10; + command access(invoke: administer) AddTrustedRootCertificate(AddTrustedRootCertificateRequest): DefaultSuccess = 11; +} + +/** The Group Key Management Cluster is the mechanism by which group keys are managed. */ +server cluster GroupKeyManagement = 63 { + enum GroupKeySecurityPolicyEnum : ENUM8 { + kTrustFirst = 0; + kCacheAndSync = 1; + } + + bitmap Feature : BITMAP32 { + kCacheAndSync = 0x1; + } + + fabric_scoped struct GroupInfoMapStruct { + group_id groupId = 1; + endpoint_no endpoints[] = 2; + optional char_string<16> groupName = 3; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct GroupKeyMapStruct { + group_id groupId = 1; + int16u groupKeySetID = 2; + fabric_idx fabricIndex = 254; + } + + struct GroupKeySetStruct { + int16u groupKeySetID = 0; + GroupKeySecurityPolicyEnum groupKeySecurityPolicy = 1; + nullable octet_string<16> epochKey0 = 2; + nullable epoch_us epochStartTime0 = 3; + nullable octet_string<16> epochKey1 = 4; + nullable epoch_us epochStartTime1 = 5; + nullable octet_string<16> epochKey2 = 6; + nullable epoch_us epochStartTime2 = 7; + } + + attribute access(write: manage) GroupKeyMapStruct groupKeyMap[] = 0; + readonly attribute GroupInfoMapStruct groupTable[] = 1; + readonly attribute int16u maxGroupsPerFabric = 2; + readonly attribute int16u maxGroupKeysPerFabric = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct KeySetWriteRequest { + GroupKeySetStruct groupKeySet = 0; + } + + request struct KeySetReadRequest { + INT16U groupKeySetID = 0; + } + + request struct KeySetRemoveRequest { + INT16U groupKeySetID = 0; + } + + response struct KeySetReadResponse = 2 { + GroupKeySetStruct groupKeySet = 0; + } + + response struct KeySetReadAllIndicesResponse = 5 { + INT16U groupKeySetIDs[] = 0; + } + + fabric command access(invoke: administer) KeySetWrite(KeySetWriteRequest): DefaultSuccess = 0; + fabric command access(invoke: administer) KeySetRead(KeySetReadRequest): KeySetReadResponse = 1; + fabric command access(invoke: administer) KeySetRemove(KeySetRemoveRequest): DefaultSuccess = 3; + fabric command access(invoke: administer) KeySetReadAllIndices(): KeySetReadAllIndicesResponse = 4; +} + +/** The Fixed Label Cluster provides a feature for the device to tag an endpoint with zero or more read only +labels. */ +server cluster FixedLabel = 64 { + struct LabelStruct { + char_string<16> label = 0; + char_string<16> value = 1; + } + + readonly attribute LabelStruct labelList[] = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** The User Label Cluster provides a feature to tag an endpoint with zero or more labels. */ +server cluster UserLabel = 65 { + struct LabelStruct { + char_string<16> label = 0; + char_string<16> value = 1; + } + + attribute access(write: manage) LabelStruct labelList[] = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** An interface for configuring and controlling the functionality of a thermostat. */ +server cluster Thermostat = 513 { + enum SetpointAdjustMode : ENUM8 { + kHeat = 0; + kCool = 1; + kBoth = 2; + } + + enum ThermostatControlSequence : ENUM8 { + kCoolingOnly = 0; + kCoolingWithReheat = 1; + kHeatingOnly = 2; + kHeatingWithReheat = 3; + kCoolingAndHeating = 4; + kCoolingAndHeatingWithReheat = 5; + } + + enum ThermostatRunningMode : ENUM8 { + kOff = 0; + kCool = 3; + kHeat = 4; + } + + enum ThermostatSystemMode : ENUM8 { + kOff = 0; + kAuto = 1; + kCool = 3; + kHeat = 4; + kEmergencyHeat = 5; + kPrecooling = 6; + kFanOnly = 7; + kDry = 8; + kSleep = 9; + } + + bitmap DayOfWeek : BITMAP8 { + kSunday = 0x1; + kMonday = 0x2; + kTuesday = 0x4; + kWednesday = 0x8; + kThursday = 0x10; + kFriday = 0x20; + kSaturday = 0x40; + kAway = 0x80; + } + + bitmap Feature : BITMAP32 { + kHeating = 0x1; + kCooling = 0x2; + kOccupancy = 0x4; + kScheduleConfiguration = 0x8; + kSetback = 0x10; + kAutoMode = 0x20; + kLocalTemperatureNotExposed = 0x40; + } + + bitmap ModeForSequence : BITMAP8 { + kHeatSetpointPresent = 0x1; + kCoolSetpointPresent = 0x2; + } + + struct ThermostatScheduleTransition { + int16u transitionTime = 0; + nullable int16s heatSetpoint = 1; + nullable int16s coolSetpoint = 2; + } + + readonly attribute nullable int16s localTemperature = 0; + readonly attribute int16s absMinHeatSetpointLimit = 3; + readonly attribute int16s absMaxHeatSetpointLimit = 4; + readonly attribute int16s absMinCoolSetpointLimit = 5; + readonly attribute int16s absMaxCoolSetpointLimit = 6; + attribute access(write: manage) bitmap8 HVACSystemTypeConfiguration = 9; + attribute int16s occupiedCoolingSetpoint = 17; + attribute int16s occupiedHeatingSetpoint = 18; + attribute access(write: manage) int16s minHeatSetpointLimit = 21; + attribute access(write: manage) int16s maxHeatSetpointLimit = 22; + attribute access(write: manage) int16s minCoolSetpointLimit = 23; + attribute access(write: manage) int16s maxCoolSetpointLimit = 24; + attribute access(write: manage) int8s minSetpointDeadBand = 25; + attribute access(write: manage) ThermostatControlSequence controlSequenceOfOperation = 27; + attribute access(write: manage) enum8 systemMode = 28; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct SetpointRaiseLowerRequest { + SetpointAdjustMode mode = 0; + INT8S amount = 1; + } + + command SetpointRaiseLower(SetpointRaiseLowerRequest): DefaultSuccess = 0; +} + +endpoint 0 { + device type ma_rootdevice = 22, version 1; + + binding cluster OtaSoftwareUpdateProvider; + + server cluster Identify { + ram attribute identifyTime default = 0x0000; + ram attribute identifyType default = 0x00; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 4; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + ram attribute featureMap default = 0; + callback attribute clusterRevision default = 1; + } + + server cluster AccessControl { + emits event AccessControlEntryChanged; + emits event AccessControlExtensionChanged; + callback attribute acl; + callback attribute extension; + callback attribute subjectsPerAccessControlEntry default = 4; + callback attribute targetsPerAccessControlEntry default = 3; + callback attribute accessControlEntriesPerFabric default = 3; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster BasicInformation { + emits event StartUp; + emits event ShutDown; + emits event Leave; + callback attribute dataModelRevision default = 10; + callback attribute vendorName; + callback attribute vendorID; + callback attribute productName; + callback attribute productID; + persist attribute nodeLabel; + callback attribute location default = "XX"; + callback attribute hardwareVersion default = 0; + callback attribute hardwareVersionString; + callback attribute softwareVersion default = 0; + callback attribute softwareVersionString; + callback attribute manufacturingDate default = "20210614123456ZZ"; + callback attribute partNumber; + callback attribute productURL; + callback attribute productLabel; + callback attribute serialNumber; + persist attribute localConfigDisabled default = 0; + ram attribute reachable default = 1; + callback attribute uniqueID; + callback attribute capabilityMinima; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster OtaSoftwareUpdateRequestor { + callback attribute defaultOTAProviders default = 0; + ram attribute updatePossible default = 1; + ram attribute updateState default = 0; + ram attribute updateStateProgress default = 0; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster LocalizationConfiguration { + persist attribute activeLocale default = "en-US"; + callback attribute supportedLocales; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster TimeFormatLocalization { + persist attribute hourFormat default = 0; + persist attribute activeCalendarType default = 0; + callback attribute supportedCalendarTypes; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster UnitLocalization { + persist attribute temperatureUnit default = 0; + ram attribute featureMap default = 0x1; + ram attribute clusterRevision default = 1; + } + + server cluster GeneralCommissioning { + ram attribute breadcrumb default = 0x0000000000000000; + callback attribute basicCommissioningInfo; + callback attribute regulatoryConfig default = 0; + callback attribute locationCapability default = 0; + callback attribute supportsConcurrentConnection default = 1; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster NetworkCommissioning { + ram attribute maxNetworks; + callback attribute networks; + ram attribute scanMaxTimeSeconds; + ram attribute connectMaxTimeSeconds; + ram attribute interfaceEnabled; + ram attribute lastNetworkingStatus; + ram attribute lastNetworkID; + ram attribute lastConnectErrorValue; + ram attribute featureMap default = 2; + ram attribute clusterRevision default = 1; + } + + server cluster GeneralDiagnostics { + emits event BootReason; + callback attribute networkInterfaces; + callback attribute rebootCount default = 0x0000; + callback attribute upTime default = 0x0000000000000000; + callback attribute totalOperationalHours default = 0x00000000; + callback attribute bootReason; + callback attribute activeHardwareFaults; + callback attribute activeRadioFaults; + callback attribute activeNetworkFaults; + callback attribute testEventTriggersEnabled default = false; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster WiFiNetworkDiagnostics { + callback attribute bssid; + callback attribute securityType; + callback attribute wiFiVersion; + callback attribute channelNumber default = 0x0000; + callback attribute rssi default = 0x00; + callback attribute beaconLostCount default = 0x00000000; + callback attribute beaconRxCount default = 0x00000000; + callback attribute packetMulticastRxCount default = 0x00000000; + callback attribute packetMulticastTxCount default = 0x00000000; + callback attribute packetUnicastRxCount default = 0x00000000; + callback attribute packetUnicastTxCount default = 0x00000000; + callback attribute currentMaxRate default = 0x0000000000000000; + callback attribute overrunCount default = 0x0000000000000000; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster AdministratorCommissioning { + callback attribute windowStatus default = 0; + callback attribute adminFabricIndex default = 1; + callback attribute adminVendorId default = 0; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster OperationalCredentials { + callback attribute NOCs; + callback attribute fabrics; + callback attribute supportedFabrics; + callback attribute commissionedFabrics; + callback attribute trustedRootCertificates; + callback attribute currentFabricIndex; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster GroupKeyManagement { + callback attribute groupKeyMap; + callback attribute groupTable; + callback attribute maxGroupsPerFabric; + callback attribute maxGroupKeysPerFabric; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } +} +endpoint 1 { + device type ma_thermostat = 769, version 1; + + binding cluster Identify; + + server cluster Identify { + ram attribute identifyTime default = 0x0000; + ram attribute identifyType default = 0x0; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 4; + } + + server cluster Groups { + ram attribute nameSupport; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 4; + } + + server cluster Scenes { + callback attribute sceneCount default = 0x00; + ram attribute currentScene default = 0x00; + ram attribute currentGroup default = 0x0000; + ram attribute sceneValid default = 0x00; + ram attribute nameSupport; + ram attribute sceneTableSize; + callback attribute remainingCapacity; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 4; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + ram attribute featureMap default = 0; + callback attribute clusterRevision default = 1; + } + + server cluster Binding { + callback attribute binding; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster PowerSource { + ram attribute status; + ram attribute order; + ram attribute description; + ram attribute wiredCurrentType; + callback attribute endpointList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 1; + ram attribute clusterRevision default = 1; + } + + server cluster FixedLabel { + callback attribute labelList; + callback attribute eventList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster UserLabel { + callback attribute labelList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster Thermostat { + ram attribute localTemperature; + ram attribute absMinHeatSetpointLimit default = 700; + ram attribute absMaxHeatSetpointLimit default = 3000; + ram attribute absMinCoolSetpointLimit default = 1600; + ram attribute absMaxCoolSetpointLimit default = 3200; + ram attribute HVACSystemTypeConfiguration; + persist attribute occupiedCoolingSetpoint default = 0x0A28; + persist attribute occupiedHeatingSetpoint default = 0x07D0; + ram attribute minHeatSetpointLimit default = 700; + ram attribute maxHeatSetpointLimit default = 3000; + ram attribute minCoolSetpointLimit default = 1600; + ram attribute maxCoolSetpointLimit default = 3200; + ram attribute minSetpointDeadBand default = 0x19; + ram attribute controlSequenceOfOperation default = 0x04; + persist attribute systemMode default = 0x01; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0x3; + ram attribute clusterRevision default = 5; + } +} + + diff --git a/examples/thermostat/nxp/zap/thermostat_matter_wifi.zap b/examples/thermostat/nxp/zap/thermostat_matter_wifi.zap new file mode 100644 index 00000000000000..d81b09af1f6534 --- /dev/null +++ b/examples/thermostat/nxp/zap/thermostat_matter_wifi.zap @@ -0,0 +1,16543 @@ +{ + "featureLevel": 98, + "creator": "zap", + "keyValuePairs": [ + { + "key": "commandDiscovery", + "value": "1" + }, + { + "key": "defaultResponsePolicy", + "value": "always" + }, + { + "key": "manufacturerCodes", + "value": "0x1002" + } + ], + "package": [ + { + "pathRelativity": "relativeToZap", + "path": "../../../../src/app/zap-templates/zcl/zcl.json", + "type": "zcl-properties", + "category": "matter", + "version": 1, + "description": "Matter SDK ZCL data" + }, + { + "pathRelativity": "relativeToZap", + "path": "../../../../src/app/zap-templates/app-templates.json", + "type": "gen-templates-json", + "version": "chip-v1" + } + ], + "endpointTypes": [ + { + "id": 1, + "name": "MA-rootdevice", + "deviceTypeRef": { + "code": 22, + "profileId": 259, + "label": "MA-rootdevice", + "name": "MA-rootdevice" + }, + "deviceTypes": [ + { + "code": 22, + "profileId": 259, + "label": "MA-rootdevice", + "name": "MA-rootdevice" + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 22 + ], + "deviceTypeName": "MA-rootdevice", + "deviceTypeCode": 22, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddGroup", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewGroup", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetGroupMembership", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveGroup", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveAllGroups", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddGroupIfIdentifying", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "AddGroupResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewGroupResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetGroupMembershipResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveGroupResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "NameSupport", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "NameSupportBitmap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddScene", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewScene", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveScene", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveAllScenes", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StoreScene", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RecallScene", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetSceneMembership", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "AddSceneResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewSceneResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveSceneResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveAllScenesResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StoreSceneResponse", + "code": 4, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetSceneMembershipResponse", + "code": 6, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "SceneCount", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentScene", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentGroup", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "group_id", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SceneValid", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NameSupport", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/Off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Off", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "On", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Toggle", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/Off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "OnOff", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "MoveToLevel", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Move", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Step", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Stop", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToLevelWithOnOff", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveWithOnOff", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepWithOnOff", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StopWithOnOff", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "CurrentLevel", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "Binding", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Access Control", + "code": 31, + "mfgCode": null, + "define": "ACCESS_CONTROL_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "Access Control", + "code": 31, + "mfgCode": null, + "define": "ACCESS_CONTROL_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "ACL", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Extension", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SubjectsPerAccessControlEntry", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TargetsPerAccessControlEntry", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AccessControlEntriesPerFabric", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "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": "", + "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": "AccessControlEntryChanged", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "AccessControlExtensionChanged", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Basic Information", + "code": 40, + "mfgCode": null, + "define": "BASIC_INFORMATION_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Basic Information", + "code": 40, + "mfgCode": null, + "define": "BASIC_INFORMATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DataModelRevision", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "10", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorName", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorID", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductName", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductID", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NodeLabel", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Location", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "XX", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersion", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersionString", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersion", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersionString", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ManufacturingDate", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "20210614123456ZZ", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartNumber", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductURL", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "long_char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductLabel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SerialNumber", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LocalConfigDisabled", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Reachable", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UniqueID", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CapabilityMinima", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "CapabilityMinimaStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "StartUp", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "ShutDown", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "Leave", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "OTA Software Update Provider", + "code": 41, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_PROVIDER_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "QueryImage", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ApplyUpdateRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "NotifyUpdateApplied", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Provider", + "code": 41, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_PROVIDER_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "QueryImageResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ApplyUpdateResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Requestor", + "code": 42, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_REQUESTOR_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AnnounceOTAProvider", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "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": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Requestor", + "code": 42, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_REQUESTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DefaultOTAProviders", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "UpdatePossible", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "UpdateState", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "OTAUpdateStateEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "UpdateStateProgress", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "Localization Configuration", + "code": 43, + "mfgCode": null, + "define": "LOCALIZATION_CONFIGURATION_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "Localization Configuration", + "code": 43, + "mfgCode": null, + "define": "LOCALIZATION_CONFIGURATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "ActiveLocale", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "en-US", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportedLocales", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "Time Format Localization", + "code": 44, + "mfgCode": null, + "define": "TIME_FORMAT_LOCALIZATION_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "Time Format Localization", + "code": 44, + "mfgCode": null, + "define": "TIME_FORMAT_LOCALIZATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "HourFormat", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "HourFormatEnum", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveCalendarType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "CalendarTypeEnum", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportedCalendarTypes", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "Unit Localization", + "code": 45, + "mfgCode": null, + "define": "UNIT_LOCALIZATION_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "Unit Localization", + "code": 45, + "mfgCode": null, + "define": "UNIT_LOCALIZATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "TemperatureUnit", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "TempUnitEnum", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x1", + "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": "Power Source", + "code": 47, + "mfgCode": null, + "define": "POWER_SOURCE_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "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": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Power Source", + "code": 47, + "mfgCode": null, + "define": "POWER_SOURCE_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "Status", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "PowerSourceStatusEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Order", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Description", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredAssessedInputVoltage", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredAssessedInputFrequency", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredCurrentType", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "WiredCurrentTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredAssessedCurrent", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredNominalVoltage", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredMaximumCurrent", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredPresent", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveWiredFaults", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatVoltage", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatPercentRemaining", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatTimeRemaining", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatChargeLevel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "BatChargeLevelEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplacementNeeded", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplaceability", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "BatReplaceabilityEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatPresent", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveBatFaults", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplacementDescription", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatCommonDesignation", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "BatCommonDesignationEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatANSIDesignation", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatIECDesignation", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatApprovedChemistry", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "BatApprovedChemistryEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatCapacity", + "code": 24, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatQuantity", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatChargeState", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "BatChargeStateEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatTimeToFullCharge", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatFunctionalWhileCharging", + "code": 28, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatChargingCurrent", + "code": 29, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveBatChargeFaults", + "code": 30, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "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": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ArmFailSafe", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetRegulatoryConfig", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "CommissioningComplete", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ArmFailSafeResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetRegulatoryConfigResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "CommissioningCompleteResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "Breadcrumb", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BasicCommissioningInfo", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "BasicCommissioningInfo", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RegulatoryConfig", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationTypeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LocationCapability", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationTypeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportsConcurrentConnection", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ScanNetworks", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddOrUpdateWiFiNetwork", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "AddOrUpdateThreadNetwork", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveNetwork", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ConnectNetwork", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ReorderNetwork", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ScanNetworksResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "NetworkConfigResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ConnectNetworkResponse", + "code": 7, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "MaxNetworks", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Networks", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ScanMaxTimeSeconds", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ConnectMaxTimeSeconds", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "InterfaceEnabled", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkingStatus", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "NetworkCommissioningStatusEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkID", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastConnectErrorValue", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "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": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RetrieveLogsResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "TestEventTrigger", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "NetworkInterfaces", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RebootCount", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UpTime", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TotalOperationalHours", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BootReason", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "BootReasonEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveHardwareFaults", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveRadioFaults", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveNetworkFaults", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TestEventTriggersEnabled", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "false", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "BootReason", + "code": 3, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Software Diagnostics", + "code": 52, + "mfgCode": null, + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetWatermarks", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Software Diagnostics", + "code": 52, + "mfgCode": null, + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "ThreadMetrics", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapFree", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapUsed", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapHighWatermark", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Thread Network Diagnostics", + "code": 53, + "mfgCode": null, + "define": "THREAD_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetCounts", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ] + }, + { + "name": "Thread Network Diagnostics", + "code": 53, + "mfgCode": null, + "define": "THREAD_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "Channel", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RoutingRole", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "RoutingRoleEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NetworkName", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PanId", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ExtendedPanId", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MeshLocalPrefix", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OverrunCount", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NeighborTable", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RouteTable", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartitionId", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Weighting", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DataVersion", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "StableDataVersion", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LeaderRouterId", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DetachedRoleCount", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ChildRoleCount", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RouterRoleCount", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LeaderRoleCount", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "AttachAttemptCount", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartitionIdChangeCount", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BetterPartitionAttachAttemptCount", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ParentChangeCount", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxTotalCount", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxUnicastCount", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBroadcastCount", + "code": 24, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxAckRequestedCount", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxAckedCount", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxNoAckRequestedCount", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDataCount", + "code": 28, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDataPollCount", + "code": 29, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBeaconCount", + "code": 30, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBeaconRequestCount", + "code": 31, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxOtherCount", + "code": 32, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxRetryCount", + "code": 33, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDirectMaxRetryExpiryCount", + "code": 34, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxIndirectMaxRetryExpiryCount", + "code": 35, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrCcaCount", + "code": 36, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrAbortCount", + "code": 37, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrBusyChannelCount", + "code": 38, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxTotalCount", + "code": 39, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxUnicastCount", + "code": 40, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBroadcastCount", + "code": 41, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDataCount", + "code": 42, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDataPollCount", + "code": 43, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBeaconCount", + "code": 44, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBeaconRequestCount", + "code": 45, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxOtherCount", + "code": 46, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxAddressFilteredCount", + "code": 47, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDestAddrFilteredCount", + "code": 48, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDuplicatedCount", + "code": 49, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrNoFrameCount", + "code": 50, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrUnknownNeighborCount", + "code": 51, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrInvalidSrcAddrCount", + "code": 52, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrSecCount", + "code": 53, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrFcsCount", + "code": 54, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrOtherCount", + "code": 55, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ActiveTimestamp", + "code": 56, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PendingTimestamp", + "code": 57, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Delay", + "code": 58, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SecurityPolicy", + "code": 59, + "mfgCode": null, + "side": "server", + "type": "SecurityPolicy", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ChannelPage0Mask", + "code": 60, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OperationalDatasetComponents", + "code": 61, + "mfgCode": null, + "side": "server", + "type": "OperationalDatasetComponents", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ActiveNetworkFaultsList", + "code": 62, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x000F", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "WiFi Network Diagnostics", + "code": 54, + "mfgCode": null, + "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "WiFi Network Diagnostics", + "code": 54, + "mfgCode": null, + "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "BSSID", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SecurityType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "SecurityTypeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "WiFiVersion", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "WiFiVersionEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ChannelNumber", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RSSI", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int8s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BeaconLostCount", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BeaconRxCount", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PacketMulticastRxCount", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PacketMulticastTxCount", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PacketUnicastRxCount", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PacketUnicastTxCount", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentMaxRate", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OverrunCount", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Ethernet Network Diagnostics", + "code": 55, + "mfgCode": null, + "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetCounts", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Ethernet Network Diagnostics", + "code": 55, + "mfgCode": null, + "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "PHYRate", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "PHYRateEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FullDuplex", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PacketRxCount", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PacketTxCount", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrCount", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CollisionCount", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OverrunCount", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CarrierDetect", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TimeSinceReset", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Switch", + "code": 59, + "mfgCode": null, + "define": "SWITCH_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Switch", + "code": 59, + "mfgCode": null, + "define": "SWITCH_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "NumberOfPositions", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentPosition", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MultiPressMax", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Administrator Commissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Administrator Commissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "WindowStatus", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "CommissioningWindowStatusEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminFabricIndex", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "fabric_idx", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminVendorId", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Operational Credentials", + "code": 62, + "mfgCode": null, + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AttestationRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "CertificateChainRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "CSRRequest", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "AddNOC", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "UpdateNOC", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "UpdateFabricLabel", + "code": 9, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveFabric", + "code": 10, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddTrustedRootCertificate", + "code": 11, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Operational Credentials", + "code": 62, + "mfgCode": null, + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AttestationResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "CertificateChainResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "CSRResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "NOCResponse", + "code": 8, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "NOCs", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Fabrics", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SupportedFabrics", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CommissionedFabrics", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TrustedRootCertificates", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentFabricIndex", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "KeySetWrite", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetRead", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetRemove", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetReadAllIndices", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "KeySetReadResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "KeySetReadAllIndicesResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "GroupKeyMap", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GroupTable", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxGroupsPerFabric", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxGroupKeysPerFabric", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "LabelList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "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": "User Label", + "code": 65, + "mfgCode": null, + "define": "USER_LABEL_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "User Label", + "code": 65, + "mfgCode": null, + "define": "USER_LABEL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "LabelList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "Door Lock", + "code": 257, + "mfgCode": null, + "define": "DOOR_LOCK_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "LockDoor", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "UnlockDoor", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "UnlockWithTimeout", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetWeekDaySchedule", + "code": 11, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetWeekDaySchedule", + "code": 12, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearWeekDaySchedule", + "code": 13, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetYearDaySchedule", + "code": 14, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetYearDaySchedule", + "code": 15, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearYearDaySchedule", + "code": 16, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetHolidaySchedule", + "code": 17, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetHolidaySchedule", + "code": 18, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearHolidaySchedule", + "code": 19, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "6", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Door Lock", + "code": 257, + "mfgCode": null, + "define": "DOOR_LOCK_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "LockState", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "DlLockState", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LockType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "DlLockType", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ActuatorEnabled", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DoorState", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "DoorStateEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Language", + "code": 33, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LEDSettings", + "code": 34, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "AutoRelockTime", + "code": 35, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoundVolume", + "code": 36, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OperatingMode", + "code": 37, + "mfgCode": null, + "side": "server", + "type": "OperatingModeEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DefaultConfigurationRegister", + "code": 39, + "mfgCode": null, + "side": "server", + "type": "DlDefaultConfigurationRegister", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnableLocalProgramming", + "code": 40, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnableOneTouchLocking", + "code": 41, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnableInsideStatusLED", + "code": 42, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnablePrivacyModeButton", + "code": 43, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "WrongCodeEntryLimit", + "code": 48, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UserCodeTemporaryDisableTime", + "code": 49, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SendPINOverTheAir", + "code": 50, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RequirePINforRemoteOperation", + "code": 51, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "6", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Barrier Control", + "code": 259, + "mfgCode": null, + "define": "BARRIER_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "BarrierControlGoToPercent", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "BarrierControlStop", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Barrier Control", + "code": 259, + "mfgCode": null, + "define": "BARRIER_CONTROL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "barrier moving state", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "barrier safety status", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "bitmap16", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "barrier capabilities", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "barrier position", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Color Control", + "code": 768, + "mfgCode": null, + "define": "COLOR_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "MoveToHue", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveHue", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepHue", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToSaturation", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveSaturation", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepSaturation", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToHueAndSaturation", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToColor", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveColor", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepColor", + "code": 9, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToColorTemperature", + "code": 10, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StopMoveStep", + "code": 71, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveColorTemperature", + "code": 75, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepColorTemperature", + "code": 76, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Color Control", + "code": 768, + "mfgCode": null, + "define": "COLOR_CONTROL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "CurrentHue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentSaturation", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RemainingTime", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentX", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x616B", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentY", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x607D", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DriftCompensation", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CompensationText", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorTemperatureMireds", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00FA", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorMode", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Options", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NumberOfPrimaries", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary1X", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary1Y", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary1Intensity", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary2X", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary2Y", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary2Intensity", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary3X", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary3Y", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary3Intensity", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary4X", + "code": 32, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary4Y", + "code": 33, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary4Intensity", + "code": 34, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary5X", + "code": 36, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary5Y", + "code": 37, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary5Intensity", + "code": 38, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary6X", + "code": 40, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary6Y", + "code": 41, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary6Intensity", + "code": 42, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "WhitePointX", + "code": 48, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "WhitePointY", + "code": 49, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointRX", + "code": 50, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointRY", + "code": 51, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointRIntensity", + "code": 52, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointGX", + "code": 54, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointGY", + "code": 55, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointGIntensity", + "code": 56, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointBX", + "code": 58, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointBY", + "code": 59, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointBIntensity", + "code": 60, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnhancedCurrentHue", + "code": 16384, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnhancedColorMode", + "code": 16385, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorLoopActive", + "code": 16386, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorLoopDirection", + "code": 16387, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorLoopTime", + "code": 16388, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0019", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorCapabilities", + "code": 16394, + "mfgCode": null, + "side": "server", + "type": "bitmap16", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorTempPhysicalMinMireds", + "code": 16395, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorTempPhysicalMaxMireds", + "code": 16396, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFEFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CoupleColorTempToLevelMinMireds", + "code": 16397, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "StartUpColorTemperatureMireds", + "code": 16400, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Temperature Measurement", + "code": 1026, + "mfgCode": null, + "define": "TEMPERATURE_MEASUREMENT_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Temperature Measurement", + "code": 1026, + "mfgCode": null, + "define": "TEMPERATURE_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x8000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x8000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x8000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Relative Humidity Measurement", + "code": 1029, + "mfgCode": null, + "define": "RELATIVE_HUMIDITY_MEASUREMENT_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Relative Humidity Measurement", + "code": 1029, + "mfgCode": null, + "define": "RELATIVE_HUMIDITY_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Unit Testing", + "code": 4294048773, + "mfgCode": null, + "define": "UNIT_TESTING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Test", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "TestNotHandled", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "TestSpecific", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Unit Testing", + "code": 4294048773, + "mfgCode": null, + "define": "UNIT_TESTING_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "TestSpecificResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "boolean", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "false", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "bitmap8", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "Bitmap8MaskMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "bitmap16", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "Bitmap16MaskMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "bitmap32", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "Bitmap32MaskMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "bitmap64", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "Bitmap64MaskMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int8u", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int16u", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int32u", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int64u", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int8s", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "int8s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int16s", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int32s", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int32s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int64s", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "int64s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "enum8", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "enum16", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "enum16", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "octet_string", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "list_int8u", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "list_octet_string", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "list_struct_octet_string", + "code": 28, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 2, + "name": "MA-thermostat", + "deviceTypeRef": { + "code": 769, + "profileId": 259, + "label": "MA-thermostat", + "name": "MA-thermostat" + }, + "deviceTypes": [ + { + "code": 769, + "profileId": 259, + "label": "MA-thermostat", + "name": "MA-thermostat" + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 769 + ], + "deviceTypeName": "MA-thermostat", + "deviceTypeCode": 769, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddGroup", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewGroup", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetGroupMembership", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveGroup", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveAllGroups", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddGroupIfIdentifying", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AddGroupResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewGroupResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetGroupMembershipResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveGroupResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "NameSupport", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "NameSupportBitmap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddScene", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewScene", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveScene", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveAllScenes", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StoreScene", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RecallScene", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetSceneMembership", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AddSceneResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewSceneResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveSceneResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveAllScenesResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StoreSceneResponse", + "code": 4, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetSceneMembershipResponse", + "code": 6, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "SceneCount", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentScene", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentGroup", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "group_id", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SceneValid", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NameSupport", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SceneTableSize", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RemainingCapacity", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/Off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Off", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "On", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Toggle", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/Off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "OnOff", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GlobalSceneControl", + "code": 16384, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OnTime", + "code": 16385, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OffWaitTime", + "code": 16386, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "StartUpOnOff", + "code": 16387, + "mfgCode": null, + "side": "server", + "type": "StartUpOnOffEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "MoveToLevel", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Move", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Step", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "Stop", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToLevelWithOnOff", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveWithOnOff", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepWithOnOff", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StopWithOnOff", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "CurrentLevel", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RemainingTime", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinLevel", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxLevel", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFE", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentFrequency", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinFrequency", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxFrequency", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Options", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "LevelControlOptions", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OnOffTransitionTime", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OnLevel", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFE", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OnTransitionTime", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OffTransitionTime", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "DefaultMoveRate", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "StartUpCurrentLevel", + "code": 16384, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "255", + "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": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Binary Input (Basic)", + "code": 15, + "mfgCode": null, + "define": "BINARY_INPUT_BASIC_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Binary Input (Basic)", + "code": 15, + "mfgCode": null, + "define": "BINARY_INPUT_BASIC_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "out of service", + "code": 81, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "present value", + "code": 85, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "status flags", + "code": 111, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Binding", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "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": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Basic Information", + "code": 40, + "mfgCode": null, + "define": "BASIC_INFORMATION_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Basic Information", + "code": 40, + "mfgCode": null, + "define": "BASIC_INFORMATION_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "DataModelRevision", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "10", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorName", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorID", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductName", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductID", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NodeLabel", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Location", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "XX", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersion", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersionString", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersion", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersionString", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ManufacturingDate", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "20210614123456ZZ", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartNumber", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductURL", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "long_char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductLabel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SerialNumber", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LocalConfigDisabled", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Reachable", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UniqueID", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CapabilityMinima", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "CapabilityMinimaStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Provider", + "code": 41, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_PROVIDER_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "QueryImage", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ApplyUpdateRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Provider", + "code": 41, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_PROVIDER_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "ApplyUpdateResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Requestor", + "code": 42, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_REQUESTOR_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Requestor", + "code": 42, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_REQUESTOR_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Power Source", + "code": 47, + "mfgCode": null, + "define": "POWER_SOURCE_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "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": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Power Source", + "code": 47, + "mfgCode": null, + "define": "POWER_SOURCE_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Status", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "PowerSourceStatusEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Order", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Description", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredAssessedInputVoltage", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredAssessedInputFrequency", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredCurrentType", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "WiredCurrentTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredAssessedCurrent", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredNominalVoltage", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredMaximumCurrent", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredPresent", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveWiredFaults", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatVoltage", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatPercentRemaining", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatTimeRemaining", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatChargeLevel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "BatChargeLevelEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplacementNeeded", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplaceability", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "BatReplaceabilityEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatPresent", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveBatFaults", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplacementDescription", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatCommonDesignation", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "BatCommonDesignationEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatANSIDesignation", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatIECDesignation", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatApprovedChemistry", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "BatApprovedChemistryEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatCapacity", + "code": 24, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatQuantity", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatChargeState", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "BatChargeStateEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatTimeToFullCharge", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatFunctionalWhileCharging", + "code": 28, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatChargingCurrent", + "code": 29, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveBatChargeFaults", + "code": 30, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EndpointList", + "code": 31, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "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": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ArmFailSafe", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetRegulatoryConfig", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "ArmFailSafeResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetRegulatoryConfigResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "Breadcrumb", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "o", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BasicCommissioningInfo", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "BasicCommissioningInfo", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SupportsConcurrentConnection", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ScanNetworks", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddOrUpdateWiFiNetwork", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveNetwork", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ConnectNetwork", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ReorderNetwork", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "ScanNetworksResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "NetworkConfigResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ConnectNetworkResponse", + "code": 7, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Switch", + "code": 59, + "mfgCode": null, + "define": "SWITCH_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Switch", + "code": 59, + "mfgCode": null, + "define": "SWITCH_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "NumberOfPositions", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentPosition", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MultiPressMax", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "GroupKeyMap", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GroupTable", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "LabelList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "User Label", + "code": 65, + "mfgCode": null, + "define": "USER_LABEL_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "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": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "User Label", + "code": 65, + "mfgCode": null, + "define": "USER_LABEL_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "LabelList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "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": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "Door Lock", + "code": 257, + "mfgCode": null, + "define": "DOOR_LOCK_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "LockDoor", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "UnlockDoor", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "UnlockWithTimeout", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetWeekDaySchedule", + "code": 11, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetWeekDaySchedule", + "code": 12, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearWeekDaySchedule", + "code": 13, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetYearDaySchedule", + "code": 14, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetYearDaySchedule", + "code": 15, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearYearDaySchedule", + "code": 16, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetHolidaySchedule", + "code": 17, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetHolidaySchedule", + "code": 18, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ClearHolidaySchedule", + "code": 19, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "6", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Door Lock", + "code": 257, + "mfgCode": null, + "define": "DOOR_LOCK_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "LockState", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "DlLockState", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LockType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "DlLockType", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ActuatorEnabled", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DoorState", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "DoorStateEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Language", + "code": 33, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LEDSettings", + "code": 34, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "AutoRelockTime", + "code": 35, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoundVolume", + "code": 36, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OperatingMode", + "code": 37, + "mfgCode": null, + "side": "server", + "type": "OperatingModeEnum", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DefaultConfigurationRegister", + "code": 39, + "mfgCode": null, + "side": "server", + "type": "DlDefaultConfigurationRegister", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnableLocalProgramming", + "code": 40, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnableOneTouchLocking", + "code": 41, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnableInsideStatusLED", + "code": 42, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnablePrivacyModeButton", + "code": 43, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "WrongCodeEntryLimit", + "code": 48, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UserCodeTemporaryDisableTime", + "code": 49, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SendPINOverTheAir", + "code": 50, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RequirePINforRemoteOperation", + "code": 51, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "6", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Window Covering", + "code": 258, + "mfgCode": null, + "define": "WINDOW_COVERING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "UpOrOpen", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 0 + }, + { + "name": "DownOrClose", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 0 + }, + { + "name": "StopMotion", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 0 + }, + { + "name": "GoToLiftValue", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 0 + }, + { + "name": "GoToLiftPercentage", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 0 + }, + { + "name": "GoToTiltValue", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 0 + }, + { + "name": "GoToTiltPercentage", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Window Covering", + "code": 258, + "mfgCode": null, + "define": "WINDOW_COVERING_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "Type", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "Type", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentPositionLift", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentPositionTilt", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ConfigStatus", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "ConfigStatus", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x03", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentPositionLiftPercentage", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "Percent", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 100, + "reportableChange": 0 + }, + { + "name": "CurrentPositionTiltPercentage", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "Percent", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 100, + "reportableChange": 0 + }, + { + "name": "OperationalStatus", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "OperationalStatus", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 127, + "reportableChange": 0 + }, + { + "name": "TargetPositionLiftPercent100ths", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "Percent100ths", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 10000, + "reportableChange": 0 + }, + { + "name": "TargetPositionTiltPercent100ths", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "Percent100ths", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 10000, + "reportableChange": 0 + }, + { + "name": "EndProductType", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "EndProductType", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentPositionLiftPercent100ths", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "Percent100ths", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 10000, + "reportableChange": 0 + }, + { + "name": "CurrentPositionTiltPercent100ths", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "Percent100ths", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 10000, + "reportableChange": 0 + }, + { + "name": "InstalledOpenLimitLift", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "InstalledClosedLimitLift", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "InstalledOpenLimitTilt", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "InstalledClosedLimitTilt", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Mode", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "Mode", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 15, + "reportableChange": 0 + }, + { + "name": "SafetyStatus", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "SafetyStatus", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Barrier Control", + "code": 259, + "mfgCode": null, + "define": "BARRIER_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "BarrierControlGoToPercent", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "BarrierControlStop", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Barrier Control", + "code": 259, + "mfgCode": null, + "define": "BARRIER_CONTROL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "barrier moving state", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "barrier safety status", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "bitmap16", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "barrier capabilities", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "barrier position", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Pump Configuration and Control", + "code": 512, + "mfgCode": null, + "define": "PUMP_CONFIGURATION_AND_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Pump Configuration and Control", + "code": 512, + "mfgCode": null, + "define": "PUMP_CONFIGURATION_AND_CONTROL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "MaxPressure", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxSpeed", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxFlow", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PumpStatus", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "PumpStatusBitmap", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EffectiveOperationMode", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "OperationModeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EffectiveControlMode", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "ControlModeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Capacity", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OperationMode", + "code": 32, + "mfgCode": null, + "side": "server", + "type": "OperationModeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Thermostat", + "code": 513, + "mfgCode": null, + "define": "THERMOSTAT_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "SetpointRaiseLower", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetWeeklySchedule", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "GetWeeklySchedule", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ClearWeeklySchedule", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Thermostat", + "code": 513, + "mfgCode": null, + "define": "THERMOSTAT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "GetWeeklyScheduleResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "LocalTemperature", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "AbsMinHeatSetpointLimit", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "700", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "AbsMaxHeatSetpointLimit", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "AbsMinCoolSetpointLimit", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1600", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "AbsMaxCoolSetpointLimit", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3200", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PICoolingDemand", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PIHeatingDemand", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HVACSystemTypeConfiguration", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OccupiedCoolingSetpoint", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0A28", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OccupiedHeatingSetpoint", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x07D0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinHeatSetpointLimit", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "700", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxHeatSetpointLimit", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinCoolSetpointLimit", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1600", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxCoolSetpointLimit", + "code": 24, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3200", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinSetpointDeadBand", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int8s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x19", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ControlSequenceOfOperation", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "ThermostatControlSequence", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x04", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SystemMode", + "code": 28, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "StartOfWeek", + "code": 32, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NumberOfWeeklyTransitions", + "code": 33, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "7", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NumberOfDailyTransitions", + "code": 34, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "0x3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Thermostat User Interface Configuration", + "code": 516, + "mfgCode": null, + "define": "THERMOSTAT_USER_INTERFACE_CONFIGURATION_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "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": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Thermostat User Interface Configuration", + "code": 516, + "mfgCode": null, + "define": "THERMOSTAT_USER_INTERFACE_CONFIGURATION_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "TemperatureDisplayMode", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "KeypadLockout", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ScheduleProgrammingVisibility", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 0, + "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": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "Color Control", + "code": 768, + "mfgCode": null, + "define": "COLOR_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "MoveToHue", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveHue", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepHue", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToSaturation", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveSaturation", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepSaturation", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToHueAndSaturation", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToColor", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveColor", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepColor", + "code": 9, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToColorTemperature", + "code": 10, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StopMoveStep", + "code": 71, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveColorTemperature", + "code": 75, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepColorTemperature", + "code": 76, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Color Control", + "code": 768, + "mfgCode": null, + "define": "COLOR_CONTROL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "CurrentHue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentSaturation", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RemainingTime", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentX", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x616B", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentY", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x607D", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DriftCompensation", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CompensationText", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorTemperatureMireds", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00FA", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorMode", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Options", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NumberOfPrimaries", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary1X", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary1Y", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary1Intensity", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary2X", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary2Y", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary2Intensity", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary3X", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary3Y", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary3Intensity", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary4X", + "code": 32, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary4Y", + "code": 33, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary4Intensity", + "code": 34, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary5X", + "code": 36, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary5Y", + "code": 37, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary5Intensity", + "code": 38, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary6X", + "code": 40, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary6Y", + "code": 41, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Primary6Intensity", + "code": 42, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "WhitePointX", + "code": 48, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "WhitePointY", + "code": 49, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointRX", + "code": 50, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointRY", + "code": 51, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointRIntensity", + "code": 52, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointGX", + "code": 54, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointGY", + "code": 55, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointGIntensity", + "code": 56, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointBX", + "code": 58, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointBY", + "code": 59, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorPointBIntensity", + "code": 60, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnhancedCurrentHue", + "code": 16384, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnhancedColorMode", + "code": 16385, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorLoopActive", + "code": 16386, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorLoopDirection", + "code": 16387, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorLoopTime", + "code": 16388, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0019", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorCapabilities", + "code": 16394, + "mfgCode": null, + "side": "server", + "type": "bitmap16", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorTempPhysicalMinMireds", + "code": 16395, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorTempPhysicalMaxMireds", + "code": 16396, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFEFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CoupleColorTempToLevelMinMireds", + "code": 16397, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "StartUpColorTemperatureMireds", + "code": 16400, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Temperature Measurement", + "code": 1026, + "mfgCode": null, + "define": "TEMPERATURE_MEASUREMENT_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Temperature Measurement", + "code": 1026, + "mfgCode": null, + "define": "TEMPERATURE_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x8000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x8000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x8000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Pressure Measurement", + "code": 1027, + "mfgCode": null, + "define": "PRESSURE_MEASUREMENT_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Pressure Measurement", + "code": 1027, + "mfgCode": null, + "define": "PRESSURE_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ScaledValue", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ScaledTolerance", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Flow Measurement", + "code": 1028, + "mfgCode": null, + "define": "FLOW_MEASUREMENT_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Flow Measurement", + "code": 1028, + "mfgCode": null, + "define": "FLOW_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Relative Humidity Measurement", + "code": 1029, + "mfgCode": null, + "define": "RELATIVE_HUMIDITY_MEASUREMENT_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Relative Humidity Measurement", + "code": 1029, + "mfgCode": null, + "define": "RELATIVE_HUMIDITY_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Wake on LAN", + "code": 1283, + "mfgCode": null, + "define": "WAKE_ON_LAN_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Wake on LAN", + "code": 1283, + "mfgCode": null, + "define": "WAKE_ON_LAN_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "MACAddress", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Channel", + "code": 1284, + "mfgCode": null, + "define": "CHANNEL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ChangeChannel", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ChangeChannelByNumber", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Channel", + "code": 1284, + "mfgCode": null, + "define": "CHANNEL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "ChannelList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Lineup", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "LineupInfoStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentChannel", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "ChannelInfoStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Target Navigator", + "code": 1285, + "mfgCode": null, + "define": "TARGET_NAVIGATOR_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "NavigateTarget", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Target Navigator", + "code": 1285, + "mfgCode": null, + "define": "TARGET_NAVIGATOR_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "TargetList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Media Playback", + "code": 1286, + "mfgCode": null, + "define": "MEDIA_PLAYBACK_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Play", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "Pause", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "Stop", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "StartOver", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "Previous", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "Next", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "Rewind", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "FastForward", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "SkipForward", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "SkipBackward", + "code": 9, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Media Playback", + "code": 1286, + "mfgCode": null, + "define": "MEDIA_PLAYBACK_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Media Input", + "code": 1287, + "mfgCode": null, + "define": "MEDIA_INPUT_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "SelectInput", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ShowInputStatus", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "HideInputStatus", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RenameInput", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Media Input", + "code": 1287, + "mfgCode": null, + "define": "MEDIA_INPUT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "InputList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Low Power", + "code": 1288, + "mfgCode": null, + "define": "LOW_POWER_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Sleep", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Low Power", + "code": 1288, + "mfgCode": null, + "define": "LOW_POWER_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Keypad Input", + "code": 1289, + "mfgCode": null, + "define": "KEYPAD_INPUT_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "SendKey", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Keypad Input", + "code": 1289, + "mfgCode": null, + "define": "KEYPAD_INPUT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Content Launcher", + "code": 1290, + "mfgCode": null, + "define": "CONTENT_LAUNCHER_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "LaunchContent", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "LaunchURL", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Content Launcher", + "code": 1290, + "mfgCode": null, + "define": "CONTENT_LAUNCHER_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "AcceptHeader", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SupportedStreamingProtocols", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Audio Output", + "code": 1291, + "mfgCode": null, + "define": "AUDIO_OUTPUT_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "SelectOutput", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RenameOutput", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Audio Output", + "code": 1291, + "mfgCode": null, + "define": "AUDIO_OUTPUT_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "OutputList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Application Launcher", + "code": 1292, + "mfgCode": null, + "define": "APPLICATION_LAUNCHER_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "LaunchApp", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Application Launcher", + "code": 1292, + "mfgCode": null, + "define": "APPLICATION_LAUNCHER_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "CatalogList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Application Basic", + "code": 1293, + "mfgCode": null, + "define": "APPLICATION_BASIC_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Application Basic", + "code": 1293, + "mfgCode": null, + "define": "APPLICATION_BASIC_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "VendorName", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorID", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ApplicationName", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductID", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Status", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "ApplicationStatusEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ApplicationVersion", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Account Login", + "code": 1294, + "mfgCode": null, + "define": "ACCOUNT_LOGIN_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "GetSetupPIN", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Account Login", + "code": 1294, + "mfgCode": null, + "define": "ACCOUNT_LOGIN_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Unit Testing", + "code": 4294048773, + "mfgCode": null, + "define": "UNIT_TESTING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Test", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "TestNotHandled", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Unit Testing", + "code": 4294048773, + "mfgCode": null, + "define": "UNIT_TESTING_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "TestSpecificResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "boolean", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "false", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "bitmap8", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "Bitmap8MaskMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "bitmap16", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "Bitmap16MaskMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "bitmap32", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "Bitmap32MaskMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "bitmap64", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "Bitmap64MaskMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int8u", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int16u", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int32u", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int64u", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int8s", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "int8s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int16s", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int32s", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int32s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "int64s", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "int64s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "enum8", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "enum16", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "enum16", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "octet_string", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "list_int8u", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "list_octet_string", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "list_struct_octet_string", + "code": 28, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "long_octet_string", + "code": 29, + "mfgCode": null, + "side": "server", + "type": "long_octet_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + } + ] + } + ], + "endpoints": [ + { + "endpointTypeName": "MA-rootdevice", + "endpointTypeIndex": 0, + "profileId": 259, + "endpointId": 0, + "networkId": 0 + }, + { + "endpointTypeName": "MA-thermostat", + "endpointTypeIndex": 1, + "profileId": 259, + "endpointId": 1, + "networkId": 0 + } + ], + "log": [] +} \ No newline at end of file diff --git a/src/crypto/tests/BUILD.gn b/src/crypto/tests/BUILD.gn index e8770010da7aca..45024d801a32aa 100644 --- a/src/crypto/tests/BUILD.gn +++ b/src/crypto/tests/BUILD.gn @@ -57,7 +57,8 @@ chip_test_suite_using_nltest("tests") { } if (chip_device_platform == "esp32" || chip_device_platform == "nrfconnect" || - chip_device_platform == "efr32" || chip_device_platform == "openiotsdk") { + chip_device_platform == "efr32" || chip_device_platform == "nxp" || + chip_device_platform == "openiotsdk") { defines = [ "CURRENT_TIME_NOT_IMPLEMENTED=1" ] } diff --git a/src/lib/shell/BUILD.gn b/src/lib/shell/BUILD.gn index 4382eb80aabb9b..0bc5ce60874e02 100644 --- a/src/lib/shell/BUILD.gn +++ b/src/lib/shell/BUILD.gn @@ -61,6 +61,11 @@ static_library("shell") { "MainLoopDefault.cpp", "streamer_k32w.cpp", ] + } else if (chip_device_platform == "nxp") { + sources += [ + "MainLoopDefault.cpp", + "streamer_nxp.cpp", + ] } else if (chip_device_platform == "cyw30739") { sources += [ "MainLoopCYW30739.cpp", diff --git a/src/lib/shell/streamer_nxp.cpp b/src/lib/shell/streamer_nxp.cpp new file mode 100644 index 00000000000000..b499b40c0f72e8 --- /dev/null +++ b/src/lib/shell/streamer_nxp.cpp @@ -0,0 +1,243 @@ +/* + * + * Copyright (c) 2021 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. + */ + +/** + * @file + * Source implementation of an input / output stream for NXP targets. + */ + +/* -------------------------------------------------------------------------- */ +/* Includes */ +/* -------------------------------------------------------------------------- */ + +#include +#include + +#include +#include + +#include "board.h" +#include "fsl_clock.h" +#include "fsl_component_serial_manager.h" +#include "fsl_os_abstraction.h" + +#if CHIP_ENABLE_OPENTHREAD +#include "openthread-system.h" +#endif + +/* -------------------------------------------------------------------------- */ +/* Private macros */ +/* -------------------------------------------------------------------------- */ +#ifndef STREAMER_UART_SERIAL_MANAGER_RING_BUFFER_SIZE +#define STREAMER_UART_SERIAL_MANAGER_RING_BUFFER_SIZE (128U) +#endif +#ifndef STREAMER_UART_FLUSH_DELAY_MS +#define STREAMER_UART_FLUSH_DELAY_MS 2 +#endif + +#ifndef BOARD_APP_UART_INSTANCE +#if defined(RW612_SERIES) || defined(RW610_SERIES) +#define BOARD_APP_UART_INSTANCE 3 +#else +#define BOARD_APP_UART_INSTANCE 1 +#endif +#endif +#ifndef BOARD_APP_UART_CLK_FREQ +#if defined(RW612_SERIES) || defined(RW610_SERIES) +#define BOARD_APP_UART_CLK_FREQ CLOCK_GetFlexCommClkFreq(3) +#else +#define BOARD_APP_UART_CLK_FREQ BOARD_BT_UART_CLK_FREQ +#endif +#endif + +/* -------------------------------------------------------------------------- */ +/* Private prototypes */ +/* -------------------------------------------------------------------------- */ + +static void Uart_RxCallBack(void * pData, serial_manager_callback_message_t * message, serial_manager_status_t status); +static void Uart_TxCallBack(void * pBuffer, serial_manager_callback_message_t * message, serial_manager_status_t status); + +/* -------------------------------------------------------------------------- */ +/* Private memory */ +/* -------------------------------------------------------------------------- */ + +static SERIAL_MANAGER_HANDLE_DEFINE(streamerSerialHandle); +static SERIAL_MANAGER_WRITE_HANDLE_DEFINE(streamerSerialWriteHandle); +static SERIAL_MANAGER_READ_HANDLE_DEFINE(streamerSerialReadHandle); +static volatile int txCount = 0; +static bool readDone = true; + +static serial_port_uart_config_t uartConfig = { .clockRate = BOARD_APP_UART_CLK_FREQ, + .baudRate = BOARD_DEBUG_UART_BAUDRATE, + .parityMode = kSerialManager_UartParityDisabled, + .stopBitCount = kSerialManager_UartOneStopBit, + .enableRx = 1, + .enableTx = 1, + .enableRxRTS = 0, + .enableTxCTS = 0, + .instance = BOARD_APP_UART_INSTANCE }; + +static uint8_t s_ringBuffer[STREAMER_UART_SERIAL_MANAGER_RING_BUFFER_SIZE]; +static const serial_manager_config_t s_serialManagerConfig = { + .ringBuffer = &s_ringBuffer[0], + .ringBufferSize = STREAMER_UART_SERIAL_MANAGER_RING_BUFFER_SIZE, + .type = BOARD_DEBUG_UART_TYPE, + .blockType = kSerialManager_NonBlocking, + .portConfig = (serial_port_uart_config_t *) &uartConfig, +}; + +/* -------------------------------------------------------------------------- */ +/* Public functions */ +/* -------------------------------------------------------------------------- */ + +namespace chip { +namespace Shell { +namespace { + +int streamer_nxp_init(streamer_t * streamer) +{ + (void) streamer; + serial_manager_status_t status = kStatus_SerialManager_Error; + +#if defined(RW612_SERIES) || defined(RW610_SERIES) + /* attach FRG3 clock to FLEXCOMM3 */ + BOARD_CLIAttachClk(); +#endif + + uartConfig.clockRate = BOARD_APP_UART_CLK_FREQ; + + /* + * Make sure to disable interrupts while initializating the serial manager interface + * Some issues could happen if a UART IRQ is firing during serial manager initialization + */ + OSA_InterruptDisable(); + + do + { + if (SerialManager_Init((serial_handle_t) streamerSerialHandle, &s_serialManagerConfig) != kStatus_SerialManager_Success) + break; + if (SerialManager_OpenWriteHandle((serial_handle_t) streamerSerialHandle, + (serial_write_handle_t) streamerSerialWriteHandle) != kStatus_SerialManager_Success) + break; + if (SerialManager_OpenReadHandle((serial_handle_t) streamerSerialHandle, (serial_read_handle_t) streamerSerialReadHandle) != + kStatus_SerialManager_Success) + break; + if (SerialManager_InstallRxCallback((serial_read_handle_t) streamerSerialReadHandle, Uart_RxCallBack, NULL) != + kStatus_SerialManager_Success) + break; + if (SerialManager_InstallTxCallback((serial_write_handle_t) streamerSerialWriteHandle, Uart_TxCallBack, NULL) != + kStatus_SerialManager_Success) + break; + status = kStatus_SerialManager_Success; + } while (0); + + OSA_InterruptEnable(); + + return status; +} + +ssize_t streamer_nxp_read(streamer_t * streamer, char * buffer, size_t length) +{ + uint32_t bytesRead = 0; + serial_manager_status_t status = kStatus_SerialManager_Success; + + if (length != 0) + { + /** + * If the reading process is over, + * let CLI Task enter blocked state until notification + **/ + if (readDone) + { + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + readDone = false; + } + + status = SerialManager_TryRead((serial_read_handle_t) streamerSerialReadHandle, (uint8_t *) buffer, length, &bytesRead); + assert(status != kStatus_SerialManager_Error); + + /** + * If we are at the end of the line or the buffer is empty, + * consider the reading process done + **/ + if ((buffer[length - 1] == '\n') || (buffer[length - 1] == '\r') || (bytesRead == 0)) + { + readDone = true; + } + } + + return bytesRead; +} + +ssize_t streamer_nxp_write(streamer_t * streamer, const char * buffer, size_t length) +{ + uint32_t intMask; + serial_manager_status_t status = kStatus_SerialManager_Error; + size_t len = 0; + + intMask = DisableGlobalIRQ(); + txCount++; + status = + SerialManager_WriteNonBlocking((serial_write_handle_t) streamerSerialWriteHandle, (uint8_t *) buffer, (uint32_t) length); + EnableGlobalIRQ(intMask); + if (status == kStatus_SerialManager_Success) + { + len = length; + } + + /* Wait for the serial manager task to empty the TX buffer */ + while (txCount) + { + OSA_TimeDelay(STREAMER_UART_FLUSH_DELAY_MS); + } + + return len; +} + +static streamer_t streamer_nxp = { + .init_cb = streamer_nxp_init, + .read_cb = streamer_nxp_read, + .write_cb = streamer_nxp_write, +}; +} // namespace + +streamer_t * streamer_get(void) +{ + return &streamer_nxp; +} + +} // namespace Shell +} // namespace chip + +/* -------------------------------------------------------------------------- */ +/* Private functions */ +/* -------------------------------------------------------------------------- */ +extern TaskHandle_t AppMatterCliTaskHandle; +static void Uart_RxCallBack(void * pData, serial_manager_callback_message_t * message, serial_manager_status_t status) +{ + if (AppMatterCliTaskHandle != NULL) + { + /* notify the main loop that a RX buffer is available */ + xTaskNotifyGive(AppMatterCliTaskHandle); + } +} + +static void Uart_TxCallBack(void * pBuffer, serial_manager_callback_message_t * message, serial_manager_status_t status) +{ + txCount--; +} diff --git a/src/lwip/BUILD.gn b/src/lwip/BUILD.gn index 241a059abb7428..d6248cbfba01a3 100644 --- a/src/lwip/BUILD.gn +++ b/src/lwip/BUILD.gn @@ -30,13 +30,13 @@ if (lwip_platform == "") { assert(lwip_platform == "external" || lwip_platform == "standalone" || lwip_platform == "cc13xx_26xx" || lwip_platform == "cc32xx" || - lwip_platform == "silabs" || lwip_platform == "k32w0" || - lwip_platform == "k32w1" || lwip_platform == "qpg" || - lwip_platform == "mbed" || lwip_platform == "psoc6" || - lwip_platform == "cyw30739" || lwip_platform == "bl602" || - lwip_platform == "mw320" || lwip_platform == "bl702" || - lwip_platform == "bl702l" || lwip_platform == "mt793x" || - lwip_platform == "asr", + lwip_platform == "nxp" || lwip_platform == "silabs" || + lwip_platform == "k32w0" || lwip_platform == "k32w1" || + lwip_platform == "qpg" || lwip_platform == "mbed" || + lwip_platform == "psoc6" || lwip_platform == "cyw30739" || + lwip_platform == "bl602" || lwip_platform == "mw320" || + lwip_platform == "bl702" || lwip_platform == "bl702l" || + lwip_platform == "mt793x" || lwip_platform == "asr", "Unsupported lwIP platform: ${lwip_platform}") if (lwip_platform != "external") { @@ -70,6 +70,8 @@ if (lwip_platform == "cc13xx_26xx") { import("${chip_root}/src/platform/device.gni") } else if (lwip_platform == "bl702l") { import("//build_overrides/bouffalolab_iot_sdk.gni") +} else if (lwip_platform == "nxp") { + import("//build_overrides/nxp_sdk.gni") } else if (lwip_platform == "mw320") { import("//build_overrides/mw320_sdk.gni") } else if (lwip_platform == "mt793x") { @@ -166,6 +168,13 @@ if (current_os == "zephyr" || current_os == "mbed") { group("all") { deps = [ ":lwip" ] } +} else if (lwip_platform == "nxp") { + group("lwip") { + public_deps = [ + ":lwip_buildconfig", + "${nxp_sdk_build_root}:nxp_lwip", + ] + } } else { config("lwip_config") { include_dirs = [ lwip_platform ] diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn index 2b3188147311e9..7a7b6a81e689f5 100644 --- a/src/platform/BUILD.gn +++ b/src/platform/BUILD.gn @@ -208,6 +208,14 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { } else if (chip_device_platform == "k32w1") { device_layer_target_define = "K32W" defines += [ "CHIP_DEVICE_LAYER_TARGET=nxp/k32w/k32w1" ] + } else if (chip_device_platform == "nxp") { + import("//build_overrides/nxp_sdk.gni") + import("${nxp_sdk_build_root}/nxp_sdk.gni") + device_layer_target_define = "NXP" + defines += [ + "CHIP_DEVICE_LAYER_TARGET=${nxp_device_layer}", + "CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE=${chip_enable_ble}", + ] } else if (chip_device_platform == "telink") { device_layer_target_define = "TELINK" defines += [ "CHIP_DEVICE_LAYER_TARGET=telink" ] @@ -310,6 +318,7 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { "NRFCONNECT", "QPG", "K32W", + "NXP", "TELINK", "MBED", "BL602", @@ -508,6 +517,8 @@ if (chip_device_platform != "none") { _platform_target = "nrfconnect" } else if (chip_device_platform == "qpg") { _platform_target = "qpg" + } else if (chip_device_platform == "nxp") { + _platform_target = "nxp" } else if (chip_device_platform == "telink") { _platform_target = "telink" } else if (chip_device_platform == "mbed") { diff --git a/src/platform/device.gni b/src/platform/device.gni index c77b3cf7f70405..cf1dc07325a664 100644 --- a/src/platform/device.gni +++ b/src/platform/device.gni @@ -116,6 +116,12 @@ declare_args() { chip_subscription_timeout_resumption = chip_persist_subscriptions } +if (chip_device_platform == "nxp" && chip_enable_openthread) { + chip_mdns = "platform" +} else if (chip_device_platform == "nxp" && chip_enable_wifi) { + chip_mdns = "minimal" +} + _chip_device_layer = "none" if (chip_device_platform == "cc13x2_26x2") { _chip_device_layer = "cc13xx_26xx/cc13x2_26x2" @@ -143,6 +149,10 @@ if (chip_device_platform == "cc13x2_26x2") { _chip_device_layer = "nxp/k32w/k32w0" } else if (chip_device_platform == "k32w1") { _chip_device_layer = "nxp/k32w/k32w1" +} else if (chip_device_platform == "nxp") { + 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 == "telink") { _chip_device_layer = "telink" } else if (chip_device_platform == "mbed") { @@ -236,7 +246,7 @@ assert( chip_device_platform == "efr32" || chip_device_platform == "esp32" || chip_device_platform == "external" || chip_device_platform == "linux" || chip_device_platform == "tizen" || - chip_device_platform == "nrfconnect" || + chip_device_platform == "nrfconnect" || chip_device_platform == "nxp" || chip_device_platform == "k32w0" || chip_device_platform == "k32w1" || chip_device_platform == "qpg" || chip_device_platform == "telink" || chip_device_platform == "mbed" || chip_device_platform == "psoc6" || diff --git a/src/platform/nxp/BUILD.gn b/src/platform/nxp/BUILD.gn new file mode 100644 index 00000000000000..b0bc61c43a960b --- /dev/null +++ b/src/platform/nxp/BUILD.gn @@ -0,0 +1,21 @@ +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") +import("//build_overrides/nxp_sdk.gni") +import("${nxp_sdk_build_root}/nxp_sdk.gni") + +group("nxp") { + public_deps = [ "${chip_root}/src/platform/nxp/${nxp_platform}:nxp_platform" ] +} diff --git a/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h b/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h new file mode 100644 index 00000000000000..fba6a32fa26326 --- /dev/null +++ b/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h @@ -0,0 +1,108 @@ +/* + * + * Copyright (c) 2020-2022 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 + * Platform-specific configuration overrides for the chip Device Layer + * on NXP platforms using the NXP SDK. + */ + +#pragma once + +// ==================== Platform Adaptations ==================== + +#ifndef CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION +#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION 0 +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION + +#ifndef CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP +#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP 0 +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP + +#if !CHIP_DEVICE_CONFIG_ENABLE_THREAD +#define CHIP_DEVICE_CONFIG_ENABLE_UNPROVISIONED_MDNS 1 +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD + +#ifndef CHIP_DEVICE_CONFIG_ENABLE_THREAD +#define CHIP_DEVICE_CONFIG_ENABLE_THREAD 0 +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD + +#ifndef CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 0 +#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + +#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 ========= + +// These are configuration options that are unique to the NXP platform. +// These can be overridden by the application as needed. + +// ========== Platform-specific Configuration Overrides ========= +#ifndef CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE +#define CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE 10240 +#endif // CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE + +#ifndef CHIP_DEVICE_CONFIG_THREAD_TASK_STACK_SIZE +#define CHIP_DEVICE_CONFIG_THREAD_TASK_STACK_SIZE 8192 +#endif // CHIP_DEVICE_CONFIG_THREAD_TASK_STACK_SIZE + +#ifndef CHIP_DEVICE_CONFIG_THREAD_TASK_PRIORITY +/* If supported, the Thread task should have a highter priority than the app task */ +#define CHIP_DEVICE_CONFIG_THREAD_TASK_PRIORITY 5 +#endif // CHIP_DEVICE_CONFIG_THREAD_TASK_PRIORITY + +#ifndef CHIP_DEVICE_CONFIG_BLE_APP_TASK_NAME +#define CHIP_DEVICE_CONFIG_BLE_APP_TASK_NAME "BLE App Task" +#endif // CHIP_DEVICE_CONFIG_BLE_APP_TASK_NAME + +#ifndef CHIP_DEVICE_CONFIG_ENABLE_WIFI_TELEMETRY +#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_TELEMETRY 0 +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_TELEMETRY + +#ifndef CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY +#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY 0 +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY + +#ifndef CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY_FULL +#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY_FULL 0 +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY_FULL + +#ifndef CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED +#define CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED 1 +#endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED + +#ifndef CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART +#define CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART 0 +#endif // CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT 1 +/* Thread DNS client enablement required for OTA */ +#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT 1 +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD && !CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONABLE_DISCOVERY 1 +#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1 +#endif diff --git a/src/platform/nxp/common/CHIPDevicePlatformEvent.h b/src/platform/nxp/common/CHIPDevicePlatformEvent.h new file mode 100644 index 00000000000000..e3167f5cc2240f --- /dev/null +++ b/src/platform/nxp/common/CHIPDevicePlatformEvent.h @@ -0,0 +1,124 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Nest Labs, Inc. + * 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 + * Defines platform-specific event types and data for the chip + * Device Layer on NXP platforms using the NXP SDK. + */ + +#pragma once +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include +#include +#include +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_WPA +#if defined(__cplusplus) +extern "C" { +#endif /* _cplusplus */ +#include "wlan.h" +#if defined(__cplusplus) +} +#endif +#endif + +#include + +namespace chip { +namespace DeviceLayer { + +namespace DeviceEventType { + +/** + * Enumerates platform-specific event types that are visible to the application. + */ +enum PublicPlatformSpecificEventTypes +{ + /* None currently defined */ +}; + +/** + * Enumerates platform-specific event types that are internal to the chip Device Layer. + */ +enum InternalPlatformSpecificEventTypes +{ + kPlatformZephyrEvent = kRange_InternalPlatformSpecific, + kPlatformZephyrBleConnected, + kPlatformZephyrBleDisconnected, + kPlatformZephyrBleCCCWrite, + kPlatformZephyrBleC1WriteEvent, + kPlatformZephyrBleC2IndDoneEvent, + kPlatformZephyrBleOutOfBuffersEvent, + kPlatformNxpWlanEvent, + kPlatformNxpIpChangeEvent, + kPlatformNxpStartWlanConnectEvent, +}; + +} // namespace DeviceEventType + +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +struct BleConnEventType +{ + bt_conn * BtConn; + uint8_t HciResult; +}; + +struct BleCCCWriteEventType +{ + bt_conn * BtConn; + uint16_t Value; +}; + +struct BleC1WriteEventType +{ + bt_conn * BtConn; + ::chip::System::PacketBuffer * Data; +}; + +struct BleC2IndDoneEventType +{ + bt_conn * BtConn; + uint8_t Result; +}; + +#endif + +/** + * Represents platform-specific event information for Zephyr platforms. + */ +struct ChipDevicePlatformEvent final +{ + union + { +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + BleConnEventType BleConnEvent; + BleCCCWriteEventType BleCCCWriteEvent; + BleC1WriteEventType BleC1WriteEvent; + BleC2IndDoneEventType BleC2IndDoneEvent; +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + enum wlan_event_reason WlanEventReason; + struct wlan_network * pNetworkDataEvent; +#endif + }; +}; + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/ConfigurationManagerImpl.cpp b/src/platform/nxp/common/ConfigurationManagerImpl.cpp new file mode 100644 index 00000000000000..b14f551df63654 --- /dev/null +++ b/src/platform/nxp/common/ConfigurationManagerImpl.cpp @@ -0,0 +1,311 @@ +/* + * + * Copyright (c) 2020-2022 Project CHIP Authors + * Copyright (c) 2020 Nest Labs, Inc. + * 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 + * Provides the implementation of the Device Layer ConfigurationManager object + * for NXP platforms using the NXP SDK. + */ + +/* this file behaves like a config.h, comes first */ +#include + +#include "NXPConfig.h" +#include +#include +#include +#include + +#include "fsl_device_registers.h" + +#if CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA +#include "FactoryDataProvider.h" +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA +extern "C" { +#include "wlan.h" +} +#endif + +namespace chip { +namespace DeviceLayer { + +using namespace ::chip::DeviceLayer::Internal; + +ConfigurationManagerImpl & ConfigurationManagerImpl::GetDefaultInstance() +{ + static ConfigurationManagerImpl sInstance; + return sInstance; +} + +CHIP_ERROR ConfigurationManagerImpl::Init() +{ + CHIP_ERROR err; + uint32_t rebootCount = 0; + bool failSafeArmed; + + // Initialize the generic implementation base class. + err = Internal::GenericConfigurationManagerImpl::Init(); + SuccessOrExit(err); + + if (NXPConfig::ConfigValueExists(NXPConfig::kCounterKey_RebootCount)) + { + err = GetRebootCount(rebootCount); + SuccessOrExit(err); + + err = StoreRebootCount(rebootCount + 1); + SuccessOrExit(err); + } + else + { + // The first boot after factory reset of the Node. + err = StoreRebootCount(1); + SuccessOrExit(err); + } + + if (!NXPConfig::ConfigValueExists(NXPConfig::kCounterKey_TotalOperationalHours)) + { + err = StoreTotalOperationalHours(0); + SuccessOrExit(err); + } + + if (!NXPConfig::ConfigValueExists(NXPConfig::kCounterKey_BootReason)) + { + err = StoreBootReason(to_underlying(BootReasonType::kUnspecified)); + SuccessOrExit(err); + } + + // TODO: Initialize the global GroupKeyStore object here + + err = CHIP_NO_ERROR; + +exit: + return err; +} + +CHIP_ERROR ConfigurationManagerImpl::GetPrimaryWiFiMACAddress(uint8_t * buf) +{ +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + if (wlan_get_mac_address(buf) != WM_SUCCESS) + { + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +#else + (void) memset(&buf[0], 0, 6); // this is to avoid compilation error in GenericConfigurationManagerImpl.cpp + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +#endif +} + +CHIP_ERROR ConfigurationManagerImpl::GetUniqueId(char * buf, size_t bufSize) +{ + CHIP_ERROR err; + size_t uniqueIdLen = 0; // without counting null-terminator + err = ReadConfigValueStr(NXPConfig::kConfigKey_UniqueId, buf, bufSize, uniqueIdLen); + + ReturnErrorOnFailure(err); + + ReturnErrorCodeIf(uniqueIdLen >= bufSize, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(buf[uniqueIdLen] != 0, CHIP_ERROR_INVALID_STRING_LENGTH); + + return err; +} + +CHIP_ERROR ConfigurationManagerImpl::StoreUniqueId(const char * uniqueId, size_t uniqueIdLen) +{ + return WriteConfigValueStr(NXPConfig::kConfigKey_UniqueId, uniqueId, uniqueIdLen); +} + +CHIP_ERROR ConfigurationManagerImpl::GenerateUniqueId(char * buf, size_t bufSize) +{ + uint64_t randomUniqueId = Crypto::GetRandU64(); + return Encoding::BytesToUppercaseHexString(reinterpret_cast(&randomUniqueId), sizeof(uint64_t), buf, bufSize); +} + +bool ConfigurationManagerImpl::CanFactoryReset() +{ + // TODO: query the application to determine if factory reset is allowed. + return true; +} + +void ConfigurationManagerImpl::InitiateFactoryReset() +{ + PlatformMgr().ScheduleWork([](intptr_t) { + // Emit ShutDown event and delete all fabrics. + PlatformMgr().HandleServerShuttingDown(); + Server::GetInstance().GetFabricTable().DeleteAllFabrics(); + DoFactoryReset(0); + }); +} + +CHIP_ERROR ConfigurationManagerImpl::ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key persistedStorageKey, + uint32_t & value) +{ + CHIP_ERROR err; + + err = NXPConfig::ReadConfigValueCounter(persistedStorageKey, value); + if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) + { + err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; + } + SuccessOrExit(err); + +exit: + return err; +} + +CHIP_ERROR ConfigurationManagerImpl::WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key persistedStorageKey, + uint32_t value) +{ + // This method reads Chip Persisted Counter type nvm3 objects. + // (where persistedStorageKey represents an index to the counter). + CHIP_ERROR err; + + err = NXPConfig::WriteConfigValueCounter(persistedStorageKey, value); + if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) + { + err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; + } + SuccessOrExit(err); + +exit: + return err; +} + +CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, bool & val) +{ + return NXPConfig::ReadConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, uint32_t & val) +{ + return NXPConfig::ReadConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, uint64_t & val) +{ + return NXPConfig::ReadConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen) +{ + return NXPConfig::ReadConfigValueStr(key, buf, bufSize, outLen); +} + +CHIP_ERROR ConfigurationManagerImpl::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen) +{ + return NXPConfig::ReadConfigValueBin(key, buf, bufSize, outLen); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, bool val) +{ + return NXPConfig::WriteConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, uint32_t val) +{ + return NXPConfig::WriteConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, uint64_t val) +{ + return NXPConfig::WriteConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueStr(Key key, const char * str) +{ + return NXPConfig::WriteConfigValueStr(key, str); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueStr(Key key, const char * str, size_t strLen) +{ + return NXPConfig::WriteConfigValueStr(key, str, strLen); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen) +{ + return NXPConfig::WriteConfigValueBin(key, data, dataLen); +} + +void ConfigurationManagerImpl::RunConfigUnitTest(void) +{ + NXPConfig::RunConfigUnitTest(); +} + +void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) +{ + CHIP_ERROR err; + + ChipLogProgress(DeviceLayer, "Performing factory reset"); + + err = NXPConfig::FactoryResetConfig(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "FactoryResetConfig() failed: %s", ErrorStr(err)); + } + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + + ThreadStackMgr().ErasePersistentInfo(); + +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD + + /* Schedule a reset in the next idle call */ + PlatformMgrImpl().ScheduleResetInIdle(); +} + +CHIP_ERROR ConfigurationManagerImpl::GetRebootCount(uint32_t & rebootCount) +{ + return ReadConfigValue(NXPConfig::kCounterKey_RebootCount, rebootCount); +} + +CHIP_ERROR ConfigurationManagerImpl::StoreRebootCount(uint32_t rebootCount) +{ + return WriteConfigValue(NXPConfig::kCounterKey_RebootCount, rebootCount); +} + +CHIP_ERROR ConfigurationManagerImpl::GetBootReason(uint32_t & bootReason) +{ + return ReadConfigValue(NXPConfig::kCounterKey_BootReason, bootReason); +} + +CHIP_ERROR ConfigurationManagerImpl::StoreBootReason(uint32_t bootReason) +{ + return WriteConfigValue(NXPConfig::kCounterKey_BootReason, bootReason); +} + +CHIP_ERROR ConfigurationManagerImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours) +{ + return ReadConfigValue(NXPConfig::kCounterKey_TotalOperationalHours, totalOperationalHours); +} + +CHIP_ERROR ConfigurationManagerImpl::StoreTotalOperationalHours(uint32_t totalOperationalHours) +{ + return WriteConfigValue(NXPConfig::kCounterKey_TotalOperationalHours, totalOperationalHours); +} + +ConfigurationManager & ConfigurationMgrImpl() +{ + return ConfigurationManagerImpl::GetDefaultInstance(); +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/ConfigurationManagerImpl.h b/src/platform/nxp/common/ConfigurationManagerImpl.h new file mode 100644 index 00000000000000..062cc9dcac3901 --- /dev/null +++ b/src/platform/nxp/common/ConfigurationManagerImpl.h @@ -0,0 +1,92 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Nest Labs, Inc. + * 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 + * Provides an implementation of the ConfigurationManager object + * for NXP platforms using the NXP SDK. + */ + +#pragma once + +#include "NXPConfig.h" +#include + +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the ConfigurationManager singleton object for the NXP platform. + */ +class ConfigurationManagerImpl final : public Internal::GenericConfigurationManagerImpl +{ +public: + // This returns an instance of this class. + static ConfigurationManagerImpl & GetDefaultInstance(); + +private: + // ===== Members that implement the ConfigurationManager public interface. + + CHIP_ERROR Init(void) override; + CHIP_ERROR GetPrimaryWiFiMACAddress(uint8_t * buf) override; + bool CanFactoryReset(void) override; + void InitiateFactoryReset(void) override; + CHIP_ERROR ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t & value) override; + CHIP_ERROR WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t value) override; + CHIP_ERROR GetUniqueId(char * buf, size_t bufSize) override; + CHIP_ERROR StoreUniqueId(const char * uniqueId, size_t uniqueIdLen) override; + CHIP_ERROR GenerateUniqueId(char * buf, size_t bufSize) override; + CHIP_ERROR GetRebootCount(uint32_t & rebootCount) override; + CHIP_ERROR StoreRebootCount(uint32_t rebootCount) override; + CHIP_ERROR GetBootReason(uint32_t & bootReason) override; + CHIP_ERROR StoreBootReason(uint32_t bootReason) override; + CHIP_ERROR GetTotalOperationalHours(uint32_t & totalOperationalHours) override; + CHIP_ERROR StoreTotalOperationalHours(uint32_t totalOperationalHours) override; + + // NOTE: Other public interface methods are implemented by GenericConfigurationManagerImpl<>. + + // ===== Members that implement the GenericConfigurationManagerImpl protected interface. + CHIP_ERROR ReadConfigValue(Key key, bool & val) override; + CHIP_ERROR ReadConfigValue(Key key, uint32_t & val) override; + CHIP_ERROR ReadConfigValue(Key key, uint64_t & val) override; + CHIP_ERROR ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen) override; + CHIP_ERROR ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen) override; + CHIP_ERROR WriteConfigValue(Key key, bool val) override; + CHIP_ERROR WriteConfigValue(Key key, uint32_t val) override; + CHIP_ERROR WriteConfigValue(Key key, uint64_t val) override; + CHIP_ERROR WriteConfigValueStr(Key key, const char * str) override; + CHIP_ERROR WriteConfigValueStr(Key key, const char * str, size_t strLen) override; + CHIP_ERROR WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen) override; + void RunConfigUnitTest(void) override; + + // ===== Private members reserved for use by this class only. + + static void DoFactoryReset(intptr_t arg); +}; + +/** + * Returns the platform-specific implementation of the ConfigurationManager object. + * + * Applications can use this to gain access to features of the ConfigurationManager + * that are specific to the selected platform. + */ +ConfigurationManager & ConfigurationMgrImpl(); + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/ConnectivityManagerImpl.cpp b/src/platform/nxp/common/ConnectivityManagerImpl.cpp new file mode 100644 index 00000000000000..36b2ae978d65c8 --- /dev/null +++ b/src/platform/nxp/common/ConnectivityManagerImpl.cpp @@ -0,0 +1,513 @@ +/* + * + * Copyright (c) 2020-2022 Project CHIP Authors + * Copyright (c) 2020 Nest Labs, Inc. + * 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. + */ +/* this file behaves like a config.h, comes first */ +#include + +#include "NetworkCommissioningDriver.h" +#include +#include +#include +#include + +#include + +#if INET_CONFIG_ENABLE_TCP_ENDPOINT +#include +#endif + +#include +#include +#include +#include + +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + +extern "C" { +#include "wlan.h" +#include "wm_net.h" +#include +} + +#include + +#include + +#endif /* CHIP_DEVICE_CONFIG_ENABLE_WPA */ + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +#include +#endif + +using namespace ::chip; +using namespace ::chip::Inet; +using namespace ::chip::System; +using namespace ::chip::TLV; +using namespace ::chip::DeviceLayer::Internal; +using namespace ::chip::DeviceLayer::DeviceEventType; + +namespace chip { +namespace DeviceLayer { + +ConnectivityManagerImpl ConnectivityManagerImpl::sInstance; +#if CHIP_DEVICE_CONFIG_ENABLE_WPA +netif_ext_callback_t ConnectivityManagerImpl::sNetifCallback; +#endif /* CHIP_DEVICE_CONFIG_ENABLE_WPA */ + +CHIP_ERROR ConnectivityManagerImpl::_Init() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + mWiFiStationMode = kWiFiStationMode_Disabled; + mWiFiStationState = kWiFiStationState_NotConnected; + mWiFiStationReconnectIntervalMS = CHIP_DEVICE_CONFIG_WIFI_STATION_RECONNECT_INTERVAL; + + // Initialize the generic base classes that require it. +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + GenericConnectivityManagerImpl_Thread::_Init(); +#endif + + SuccessOrExit(err); + +exit: + return err; +} + +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 +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + if (event->Type == kPlatformNxpWlanEvent) + { + ProcessWlanEvent(event->Platform.WlanEventReason); + } + else if (event->Type == kPlatformNxpIpChangeEvent) + { + UpdateInternetConnectivityState(); + } + else if (event->Type == kPlatformNxpStartWlanConnectEvent) + { + if (wlan_add_network(event->Platform.pNetworkDataEvent) == WM_SUCCESS) + { + _SetWiFiStationState(kWiFiStationState_Connecting); + ChipLogProgress(DeviceLayer, "WLAN connecting to network.name = \"%s\"", event->Platform.pNetworkDataEvent->name); + wlan_connect(event->Platform.pNetworkDataEvent->name); + } + if (event->Platform.pNetworkDataEvent != NULL) + { + free(event->Platform.pNetworkDataEvent); + } + } +#endif +} + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + +ConnectivityManager::WiFiStationMode ConnectivityManagerImpl::_GetWiFiStationMode() +{ + return mWiFiStationMode; +} + +CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationMode(ConnectivityManager::WiFiStationMode val) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(val != ConnectivityManager::kWiFiStationMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT); + + if (mWiFiStationMode != val) + { + ChipLogProgress(DeviceLayer, "WiFi station mode change: %s -> %s", WiFiStationModeToStr(mWiFiStationMode), + WiFiStationModeToStr(val)); + } + + mWiFiStationMode = val; +exit: + return err; +} + +void ConnectivityManagerImpl::_SetWiFiStationState(ConnectivityManager::WiFiStationState val) +{ + if (mWiFiStationState != val) + { + ChipLogProgress(DeviceLayer, "WiFi station state change: %s -> %s", WiFiStationStateToStr(mWiFiStationState), + WiFiStationStateToStr(val)); + } + + mWiFiStationState = val; +} + +CHIP_ERROR ConnectivityManagerImpl::_SetWiFiAPMode(WiFiAPMode val) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(val != kWiFiAPMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT); + + if (mWiFiAPMode != val) + { + ChipLogProgress(DeviceLayer, "WiFi AP mode change: %s -> %s", WiFiAPModeToStr(mWiFiAPMode), WiFiAPModeToStr(val)); + } + + mWiFiAPMode = val; +exit: + return err; +} + +bool ConnectivityManagerImpl::_IsWiFiStationEnabled() +{ + return GetWiFiStationMode() == kWiFiStationMode_Enabled; +} + +bool ConnectivityManagerImpl::_IsWiFiStationConnected() +{ + return (mWiFiStationState == kWiFiStationState_Connected); +} + +bool ConnectivityManagerImpl::_IsWiFiStationApplicationControlled() +{ + return mWiFiStationMode == ConnectivityManager::kWiFiStationMode_ApplicationControlled; +} + +void ConnectivityManagerImpl::ProcessWlanEvent(enum wlan_event_reason wlanEvent) +{ +#if CHIP_DETAIL_LOGGING + enum wlan_connection_state state; + int result; + + result = wlan_get_connection_state(&state); + if (result == WM_SUCCESS) + { + ChipLogDetail(DeviceLayer, "WLAN event: %d, WLAN connection state: %d", wlanEvent, state); + } + else + { + ChipLogDetail(DeviceLayer, "WLAN event: %d, WLAN connection state: unknown", wlanEvent); + } +#endif /* CHIP_DETAIL_LOGGING */ + + switch (wlanEvent) + { + case WLAN_REASON_SUCCESS: + ChipLogProgress(DeviceLayer, "Connected to WLAN network = %d", is_sta_ipv6_connected()); + if (sInstance._GetWiFiStationState() == kWiFiStationState_Connecting) + { + sInstance._SetWiFiStationState(kWiFiStationState_Connecting_Succeeded); + sInstance._SetWiFiStationState(kWiFiStationState_Connected); + NetworkCommissioning::NXPWiFiDriver::GetInstance().OnConnectWiFiNetwork(NetworkCommissioning::Status::kSuccess, + CharSpan(), wlanEvent); + sInstance.OnStationConnected(); + } + break; + + case WLAN_REASON_AUTH_SUCCESS: + ChipLogProgress(DeviceLayer, "Associated to WLAN network"); + break; + + case WLAN_REASON_CONNECT_FAILED: + ChipLogError(DeviceLayer, "WLAN (re)connect failed"); + sInstance._SetWiFiStationState(kWiFiStationState_NotConnected); + UpdateInternetConnectivityState(); + break; + + case WLAN_REASON_NETWORK_NOT_FOUND: + ChipLogError(DeviceLayer, "WLAN network not found"); + NetworkCommissioning::NXPWiFiDriver::GetInstance().OnConnectWiFiNetwork(NetworkCommissioning::Status::kNetworkNotFound, + CharSpan(), wlanEvent); + break; + + case WLAN_REASON_NETWORK_AUTH_FAILED: + ChipLogError(DeviceLayer, "Authentication to WLAN network failed"); + NetworkCommissioning::NXPWiFiDriver::GetInstance().OnConnectWiFiNetwork(NetworkCommissioning::Status::kAuthFailure, + CharSpan(), wlanEvent); + ChipLogError(DeviceLayer, "Authentication to WLAN network failed end"); + break; + + case WLAN_REASON_LINK_LOST: + ChipLogError(DeviceLayer, "WLAN link lost"); + if (sInstance._GetWiFiStationState() == kWiFiStationState_Connected) + { + sInstance._SetWiFiStationState(kWiFiStationState_NotConnected); + sInstance.OnStationDisconnected(); + } + break; + + case WLAN_REASON_USER_DISCONNECT: + ChipLogProgress(DeviceLayer, "Disconnected from WLAN network"); + sInstance._SetWiFiStationState(kWiFiStationState_NotConnected); + sInstance.OnStationDisconnected(); + break; + + case WLAN_REASON_INITIALIZED: + sInstance._SetWiFiStationState(kWiFiStationState_NotConnected); + sInstance._SetWiFiStationMode(kWiFiStationMode_Enabled); + break; + + default: + break; + } +} + +int ConnectivityManagerImpl::_WlanEventCallback(enum wlan_event_reason wlanEvent, void * data) +{ + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformNxpWlanEvent; + event.Platform.WlanEventReason = wlanEvent; + (void) PlatformMgr().PostEvent(&event); + return 0; +} + +void ConnectivityManagerImpl::OnStationConnected() +{ + CHIP_ERROR err; + ChipDeviceEvent event; + + event.Type = DeviceEventType::kWiFiConnectivityChange; + event.WiFiConnectivityChange.Result = kConnectivity_Established; + (void) PlatformMgr().PostEvent(&event); + + /* Update the connectivity state in case the connected event has been received after getting an IP addr */ + UpdateInternetConnectivityState(); +} + +void ConnectivityManagerImpl::OnStationDisconnected() +{ + CHIP_ERROR err; + ChipDeviceEvent event; + + event.Type = DeviceEventType::kWiFiConnectivityChange; + event.WiFiConnectivityChange.Result = kConnectivity_Lost; + (void) PlatformMgr().PostEvent(&event); + + /* Update the connectivity state in case the connected event has been received after getting an IP addr */ + UpdateInternetConnectivityState(); +} + +void ConnectivityManagerImpl::UpdateInternetConnectivityState() +{ + bool haveIPv4Conn = false; + bool haveIPv6Conn = false; + const bool hadIPv4Conn = mFlags.Has(ConnectivityFlags::kHaveIPv4InternetConnectivity); + const bool hadIPv6Conn = mFlags.Has(ConnectivityFlags::kHaveIPv6InternetConnectivity); + const ip_addr_t * addr4; + const ip6_addr_t * addr6; + CHIP_ERROR err; + ChipDeviceEvent event; + + // If the WiFi station is currently in the connected state... + if (_IsWiFiStationConnected()) + { + // Get the LwIP netif for the WiFi station interface. + struct netif * netif = static_cast(net_get_mlan_handle()); + + // If the WiFi station interface is up... + if ((netif != nullptr) && netif_is_up(netif) && netif_is_link_up(netif)) + { +#if INET_CONFIG_ENABLE_IPV4 + // Check if a DNS server is currently configured. If so... + ip_addr_t dnsServerAddr = *dns_getserver(0); + if (!ip_addr_isany_val(dnsServerAddr)) + { + // If the station interface has been assigned an IPv4 address, and has + // an IPv4 gateway, then presume that the device has IPv4 Internet + // connectivity. + if (!ip4_addr_isany_val(*netif_ip4_addr(netif)) && !ip4_addr_isany_val(*netif_ip4_gw(netif))) + { + haveIPv4Conn = true; + addr4 = &netif->ip_addr; + } + } +#endif + + // Search among the IPv6 addresses assigned to the interface for an + // address that is in the valid state. Search goes backwards because + // the link-local address is in the first slot and we prefer to report + // other than the link-local address value if there are multiple addresses. + for (int i = (LWIP_IPV6_NUM_ADDRESSES - 1); i >= 0; i--) + { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) + { + haveIPv6Conn = true; + addr6 = netif_ip6_addr(netif, i); + break; + } + } + } + } + + // Update the current state. + mFlags.Set(ConnectivityFlags::kHaveIPv4InternetConnectivity, haveIPv4Conn) + .Set(ConnectivityFlags::kHaveIPv6InternetConnectivity, haveIPv6Conn); + + if (haveIPv4Conn != hadIPv4Conn) + { + /* Check if the */ + event.Type = DeviceEventType::kInternetConnectivityChange; + event.InternetConnectivityChange.IPv4 = GetConnectivityChange(hadIPv4Conn, haveIPv4Conn); + event.InternetConnectivityChange.IPv6 = kConnectivity_NoChange; + if (haveIPv4Conn) + { + event.InternetConnectivityChange.ipAddress = IPAddress(*addr4); + /* (Re-)start the DNSSD server */ + chip::app::DnssdServer::Instance().StartServer(); + } + err = PlatformMgr().PostEvent(&event); + VerifyOrDie(err == CHIP_NO_ERROR); + + ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv4", (haveIPv4Conn) ? "ESTABLISHED" : "LOST"); + } + + if (haveIPv6Conn != hadIPv6Conn) + { + event.Type = DeviceEventType::kInternetConnectivityChange; + event.InternetConnectivityChange.IPv4 = kConnectivity_NoChange; + event.InternetConnectivityChange.IPv6 = GetConnectivityChange(hadIPv6Conn, haveIPv6Conn); + if (haveIPv6Conn) + { + event.InternetConnectivityChange.ipAddress = IPAddress(*addr6); + /* (Re-)start the DNSSD server */ + chip::app::DnssdServer::Instance().StartServer(); + } + err = PlatformMgr().PostEvent(&event); + VerifyOrDie(err == CHIP_NO_ERROR); + + ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv6", (haveIPv6Conn) ? "ESTABLISHED" : "LOST"); + } +} + +void ConnectivityManagerImpl::_NetifExtCallback(struct netif * netif, netif_nsc_reason_t reason, + const netif_ext_callback_args_t * args) +{ + struct netif * station_netif; + ChipDeviceEvent event; + + ChipLogDetail(DeviceLayer, "_NetifExtCallback: netif=%p, reason=0x%04x", netif, reason); + + station_netif = static_cast(net_get_mlan_handle()); + if (netif == station_netif) + { + event.Type = DeviceEventType::kPlatformNxpIpChangeEvent; + (void) PlatformMgr().PostEvent(&event); + } +} + +void ConnectivityManagerImpl::StartWiFiManagement() +{ + struct netif * netif = nullptr; + EventBits_t bits; + int32_t result; + + LOCK_TCPIP_CORE(); + netif = static_cast(net_get_mlan_handle()); + if (netif != nullptr) + { + memset(&ConnectivityManagerImpl::sNetifCallback, 0, sizeof(ConnectivityManagerImpl::sNetifCallback)); + netif_add_ext_callback(&ConnectivityManagerImpl::sNetifCallback, &_NetifExtCallback); + } + UNLOCK_TCPIP_CORE(); + + result = wlan_start(_WlanEventCallback); + + if (result != WM_SUCCESS) + { + ChipLogError(DeviceLayer, "Failed to start WLAN Connection Manager"); + chipDie(); + } +} +#endif // CHIP_DEVICE_CONFIG_ENABLE_WPA + +CHIP_ERROR ConnectivityManagerImpl::ProvisionWiFiNetwork(const char * ssid, uint8_t ssidLen, const char * key, uint8_t keyLen) +{ +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + CHIP_ERROR ret = CHIP_NO_ERROR; + struct wlan_network * pNetworkData = (struct wlan_network *) malloc(sizeof(struct wlan_network)); + int result; + + VerifyOrExit(pNetworkData != NULL, ret = CHIP_ERROR_NO_MEMORY); + VerifyOrExit(ssidLen <= IEEEtypes_SSID_SIZE, ret = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(mWiFiStationState != kWiFiStationState_Connecting, ret = CHIP_ERROR_BUSY); + + memset(pNetworkData, 0, sizeof(struct wlan_network)); + + if (ssidLen < WLAN_NETWORK_NAME_MAX_LENGTH) + { + memcpy(pNetworkData->name, ssid, ssidLen); + pNetworkData->name[ssidLen] = '\0'; + } + else + { + memcpy(pNetworkData->name, ssid, WLAN_NETWORK_NAME_MAX_LENGTH); + pNetworkData->name[WLAN_NETWORK_NAME_MAX_LENGTH] = '\0'; + } + + memcpy(pNetworkData->ssid, ssid, ssidLen); + pNetworkData->ip.ipv4.addr_type = ADDR_TYPE_DHCP; + pNetworkData->ssid_specific = 1; + + pNetworkData->security.type = WLAN_SECURITY_NONE; + + if (keyLen > 0) + { + pNetworkData->security.type = WLAN_SECURITY_WILDCARD; + memcpy(pNetworkData->security.psk, key, keyLen); + pNetworkData->security.psk_len = keyLen; + } + + ConnectNetworkTimerHandler(NULL, (void *) pNetworkData); + +exit: + return ret; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif +} + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA +void ConnectivityManagerImpl::ConnectNetworkTimerHandler(::chip::System::Layer * aLayer, void * context) +{ + ChipDeviceEvent event; + + /* + * Make sure to have the Wi-Fi station enabled before scheduling a connect event . + * Otherwise start a new timer to check again the status later. + */ + if (ConnectivityMgr().IsWiFiStationEnabled()) + { + /* Post an event to start the connection asynchronously in the Matter task context */ + event.Type = DeviceEventType::kPlatformNxpStartWlanConnectEvent; + event.Platform.pNetworkDataEvent = (struct wlan_network *) context; + (void) PlatformMgr().PostEvent(&event); + } + else + { + PlatformMgr().LockChipStack(); + DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_WIFI_STATION_RECONNECT_INTERVAL), + ConnectNetworkTimerHandler, context); + PlatformMgr().UnlockChipStack(); + } +} +#endif + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/ConnectivityManagerImpl.h b/src/platform/nxp/common/ConnectivityManagerImpl.h new file mode 100644 index 00000000000000..427cbbe8e61cc3 --- /dev/null +++ b/src/platform/nxp/common/ConnectivityManagerImpl.h @@ -0,0 +1,188 @@ +/* + * + * Copyright (c) 2020-2022 Project CHIP Authors + * Copyright (c) 2020 Nest Labs, Inc. + * 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. + */ + +#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_WPA +#include +extern "C" { +#include "wlan.h" +} +#include "event_groups.h" +#include "lwip/netif.h" +#else +#include +#endif + +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the ConnectivityManager singleton object for NXP platforms. + */ +class ConnectivityManagerImpl final : public ConnectivityManager, +#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 + public Internal::GenericConnectivityManagerImpl_UDP, +#if INET_CONFIG_ENABLE_TCP_ENDPOINT + public Internal::GenericConnectivityManagerImpl_TCP, +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + public Internal::GenericConnectivityManagerImpl_WiFi, +#else + public Internal::GenericConnectivityManagerImpl_NoWiFi, +#endif + + public Internal::GenericConnectivityManagerImpl +{ + // Allow the ConnectivityManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class ConnectivityManager; + +public: + CHIP_ERROR ProvisionWiFiNetwork(const char * ssid, uint8_t ssidLen, const char * key, uint8_t keyLen); + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + void StartWiFiManagement(); +#endif + +private: + // ===== Members that implement the ConnectivityManager abstract interface. + + bool _HaveIPv4InternetConnectivity(void); + bool _HaveIPv6InternetConnectivity(void); + bool _HaveServiceConnectivity(void); + CHIP_ERROR _Init(void); + void _OnPlatformEvent(const ChipDeviceEvent * event); +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + void ProcessWlanEvent(enum wlan_event_reason wlanEvent); + WiFiStationMode _GetWiFiStationMode(); + CHIP_ERROR _SetWiFiStationMode(ConnectivityManager::WiFiStationMode val); + ConnectivityManager::WiFiStationState _GetWiFiStationState(void); + void _SetWiFiStationState(ConnectivityManager::WiFiStationState val); + CHIP_ERROR _SetWiFiAPMode(WiFiAPMode val); + + static void ConnectNetworkTimerHandler(::chip::System::Layer * aLayer, void * context); + + bool _IsWiFiStationEnabled(); + bool _IsWiFiStationConnected(); + bool _IsWiFiStationApplicationControlled(); +#endif /* CHIP_DEVICE_CONFIG_ENABLE_WPA */ + + // ===== Members for internal use by the following friends. + + friend ConnectivityManager & ConnectivityMgr(void); + friend ConnectivityManagerImpl & ConnectivityMgrImpl(void); + + static ConnectivityManagerImpl sInstance; + + // ===== Private members reserved for use by this class only. + ConnectivityManager::WiFiStationMode mWiFiStationMode; + ConnectivityManager::WiFiStationState mWiFiStationState; + ConnectivityManager::WiFiAPMode mWiFiAPMode; + uint32_t mWiFiStationReconnectIntervalMS; + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + enum WiFiEventGroup{ + kWiFiEventGroup_WiFiStationModeBit = (1 << 0), + }; + + BitFlags mFlags; + static netif_ext_callback_t sNetifCallback; + + static int _WlanEventCallback(enum wlan_event_reason event, void * data); + static void _NetifExtCallback(struct netif * netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t * args); + + void OnStationConnected(void); + void OnStationDisconnected(void); + void UpdateInternetConnectivityState(void); +#endif /* CHIP_DEVICE_CONFIG_ENABLE_WPA */ +}; + +inline bool ConnectivityManagerImpl::_HaveIPv4InternetConnectivity(void) +{ + return false; +} + +inline bool ConnectivityManagerImpl::_HaveIPv6InternetConnectivity(void) +{ + return false; +} + +inline bool ConnectivityManagerImpl::_HaveServiceConnectivity(void) +{ + return _HaveServiceConnectivity(); +} +#if CHIP_DEVICE_CONFIG_ENABLE_WPA +inline ConnectivityManager::WiFiStationState ConnectivityManagerImpl::_GetWiFiStationState(void) +{ + return mWiFiStationState; +} +#endif +/** + * 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 ESP32 platform. + */ +inline ConnectivityManagerImpl & ConnectivityMgrImpl(void) +{ + return ConnectivityManagerImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/DiagnosticDataProviderImpl.cpp b/src/platform/nxp/common/DiagnosticDataProviderImpl.cpp new file mode 100644 index 00000000000000..92ef8c0c310d29 --- /dev/null +++ b/src/platform/nxp/common/DiagnosticDataProviderImpl.cpp @@ -0,0 +1,332 @@ +/* + * + * Copyright (c) 2021 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. + */ + +/** + * @file + * Provides an implementation of the DiagnosticDataProvider object + * for nxp platform. + */ + +#include +#include + +#include "DiagnosticDataProviderImpl.h" +#include +#include + +#include +#include + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA +extern "C" { +#include +} +#endif + +namespace chip { +namespace DeviceLayer { + +DiagnosticDataProviderImpl & DiagnosticDataProviderImpl::GetDefaultInstance() +{ + static DiagnosticDataProviderImpl sInstance; + return sInstance; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetRebootCount(uint16_t & rebootCount) +{ + uint32_t count = 0; + + CHIP_ERROR err = ConfigurationMgr().GetRebootCount(count); + + if (err == CHIP_NO_ERROR) + { + VerifyOrReturnError(count <= UINT16_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE); + rebootCount = static_cast(count); + } + + return err; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetUpTime(uint64_t & upTime) +{ + System::Clock::Timestamp currentTime = System::SystemClock().GetMonotonicTimestamp(); + System::Clock::Timestamp startTime = PlatformMgrImpl().GetStartTime(); + + if (currentTime >= startTime) + { + upTime = std::chrono::duration_cast(currentTime - startTime).count(); + return CHIP_NO_ERROR; + } + + return CHIP_ERROR_INVALID_TIME; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours) +{ + uint64_t upTime = 0; + + if (GetUpTime(upTime) == CHIP_NO_ERROR) + { + uint32_t totalHours = 0; + if (ConfigurationMgr().GetTotalOperationalHours(totalHours) == CHIP_NO_ERROR) + { + VerifyOrReturnError(upTime / 3600 <= UINT32_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE); + totalOperationalHours = totalHours + static_cast(upTime / 3600); + return CHIP_NO_ERROR; + } + } + + return CHIP_ERROR_INVALID_TIME; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetBootReason(BootReasonType & bootReason) +{ + uint32_t reason = 0; + + CHIP_ERROR err = ConfigurationMgr().GetBootReason(reason); + + if (err == CHIP_NO_ERROR) + { + VerifyOrReturnError(reason <= UINT8_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE); + bootReason = static_cast(reason); + } + + return err; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetNetworkInterfaces(NetworkInterface ** netifpp) +{ + NetworkInterface * ifp = new NetworkInterface(); + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + const char * threadNetworkName = otThreadGetNetworkName(ThreadStackMgrImpl().OTInstance()); + ifp->name = CharSpan(threadNetworkName, strlen(threadNetworkName)); + ifp->isOperational = true; + ifp->offPremiseServicesReachableIPv4.SetNull(); + ifp->offPremiseServicesReachableIPv6.SetNull(); + ifp->type = EMBER_ZCL_INTERFACE_TYPE_ENUM_THREAD; + ConfigurationMgr().GetPrimary802154MACAddress(ifp->MacAddress); + ifp->hardwareAddress = ByteSpan(ifp->MacAddress, kMaxHardwareAddrSize); +#elif CHIP_DEVICE_CONFIG_ENABLE_WPA + struct netif * netif = nullptr; + netif = static_cast(net_get_mlan_handle()); + strncpy(ifp->Name, "wlan0", Inet::InterfaceId::kMaxIfNameLength); + ifp->name = CharSpan(ifp->Name, strlen(ifp->Name)); + ifp->isOperational = true; + ifp->offPremiseServicesReachableIPv4.SetNull(); + ifp->offPremiseServicesReachableIPv6.SetNull(); + ifp->type = EMBER_ZCL_INTERFACE_TYPE_ENUM_WI_FI; + ifp->hardwareAddress = ByteSpan(netif->hwaddr, netif->hwaddr_len); +#endif + + // IPv6-only support + Inet::InterfaceAddressIterator interfAddrIterator; + uint8_t ipv6AddressesCount = 0; + while (interfAddrIterator.HasCurrent() && ipv6AddressesCount < kMaxIPv6AddrCount) + { + chip::Inet::IPAddress ipv6Address; + if (interfAddrIterator.GetAddress(ipv6Address) == CHIP_NO_ERROR) + { + memcpy(ifp->Ipv6AddressesBuffer[ipv6AddressesCount], ipv6Address.Addr, kMaxIPv6AddrSize); + ifp->Ipv6AddressSpans[ipv6AddressesCount] = ByteSpan(ifp->Ipv6AddressesBuffer[ipv6AddressesCount]); + ipv6AddressesCount++; + } + interfAddrIterator.Next(); + } + ifp->IPv6Addresses = chip::app::DataModel::List(ifp->Ipv6AddressSpans, ipv6AddressesCount); + + *netifpp = ifp; + return CHIP_NO_ERROR; +} + +void DiagnosticDataProviderImpl::ReleaseNetworkInterfaces(NetworkInterface * netifp) +{ + while (netifp) + { + NetworkInterface * del = netifp; + netifp = netifp->Next; + delete del; + } +} + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBssId(MutableByteSpan & BssId) +{ + constexpr size_t bssIdSize = 6; + struct wlan_network current_network; + + VerifyOrReturnError(BssId.size() >= bssIdSize, CHIP_ERROR_BUFFER_TOO_SMALL); + + int ret = wlan_get_current_network(¤t_network); + if (ret == WM_SUCCESS) + { + memcpy(BssId.data(), current_network.bssid, bssIdSize); + BssId.reduce_size(bssIdSize); + return CHIP_NO_ERROR; + } + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiSecurityType(app::Clusters::WiFiNetworkDiagnostics::SecurityTypeEnum & securityType) +{ + using app::Clusters::WiFiNetworkDiagnostics::SecurityTypeEnum; + struct wlan_network current_network; + int ret = wlan_get_current_network(¤t_network); + + if (ret != WM_SUCCESS) + { + // Set as no security by default + securityType = SecurityTypeEnum::kNone; + return CHIP_NO_ERROR; + } + switch (current_network.security.type) + { + case WLAN_SECURITY_WEP_OPEN: + case WLAN_SECURITY_WEP_SHARED: + securityType = SecurityTypeEnum::kWep; + break; + case WLAN_SECURITY_WPA: + securityType = SecurityTypeEnum::kWpa; + break; + case WLAN_SECURITY_WPA2: + securityType = SecurityTypeEnum::kWpa2; + break; + case WLAN_SECURITY_WPA3_SAE: + securityType = SecurityTypeEnum::kWpa3; + break; + case WLAN_SECURITY_NONE: + default: // Default: No_security + securityType = SecurityTypeEnum::kNone; + } + + ChipLogProgress(DeviceLayer, "GetWiFiSecurityType: %u", to_underlying(securityType)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiVersion(app::Clusters::WiFiNetworkDiagnostics::WiFiVersionEnum & wifiVersion) +{ +#if defined(CONFIG_11AX) + wifiVersion = app::Clusters::WiFiNetworkDiagnostics::WiFiVersionEnum::kAx; +#elif defined(CONFIG_11AC) + wifiVersion = app::Clusters::WiFiNetworkDiagnostics::WiFiVersionEnum::kAc; +#elif defined(CONFIG_11N) + wifiVersion = app::Clusters::WiFiNetworkDiagnostics::WiFiVersionEnum::kN; +#endif + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiChannelNumber(uint16_t & channelNumber) +{ + channelNumber = wlan_get_current_channel(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiRssi(int8_t & rssi) +{ + short w_rssi; + int err = wlan_get_current_rssi(&w_rssi); + if (err != 0) + { + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + } + rssi = static_cast(w_rssi); + return CHIP_NO_ERROR; +} + +#if DGWIFI_RESET_COUNTS_SUPPORTED +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBeaconLostCount(uint32_t & beaconLostCount) +{ +#ifdef CONFIG_WIFI_GET_LOG + wifi_pkt_stats_t stats; + int ret = wifi_get_log(&stats, MLAN_BSS_TYPE_STA); + if (ret == WM_SUCCESS) + { + beaconLostCount = stats.bcn_miss_cnt; + return CHIP_NO_ERROR; + } +#endif /* CONFIG_WIFI_GET_LOG */ + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBeaconRxCount(uint32_t & beaconRxCount) +{ +#ifdef CONFIG_WIFI_GET_LOG + wifi_pkt_stats_t stats; + int ret = wifi_get_log(&stats, MLAN_BSS_TYPE_STA); + if (ret == WM_SUCCESS) + { + beaconRxCount = stats.bcn_rcv_cnt; + return CHIP_NO_ERROR; + } +#endif /* CONFIG_WIFI_GET_LOG */ + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketMulticastRxCount(uint32_t & packetMulticastRxCount) +{ +#ifdef CONFIG_WIFI_GET_LOG + wifi_pkt_stats_t stats; + int ret = wifi_get_log(&stats, MLAN_BSS_TYPE_STA); + if (ret == WM_SUCCESS) + { + packetMulticastRxCount = stats.mcast_rx_frame; + return CHIP_NO_ERROR; + } +#endif /* CONFIG_WIFI_GET_LOG */ + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketMulticastTxCount(uint32_t & packetMulticastTxCount) +{ +#ifdef CONFIG_WIFI_GET_LOG + wifi_pkt_stats_t stats; + int ret = wifi_get_log(&stats, MLAN_BSS_TYPE_STA); + if (ret == WM_SUCCESS) + { + packetMulticastTxCount = stats.mcast_tx_frame; + return CHIP_NO_ERROR; + } +#endif /* CONFIG_WIFI_GET_LOG */ + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketUnicastTxCount(uint32_t & packetUnicastTxCount) +{ +#ifdef CONFIG_WIFI_GET_LOG + wifi_pkt_stats_t stats; + int ret = wifi_get_log(&stats, MLAN_BSS_TYPE_STA); + if (ret == WM_SUCCESS) + { + packetUnicastTxCount = stats.tx_frame; + return CHIP_NO_ERROR; + } +#endif /* CONFIG_WIFI_GET_LOG */ + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + +#endif /* DGWIFI_RESET_COUNTS_SUPPORTED */ + +#endif /* CHIP_DEVICE_CONFIG_ENABLE_WPA */ + +DiagnosticDataProvider & GetDiagnosticDataProviderImpl() +{ + return DiagnosticDataProviderImpl::GetDefaultInstance(); +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/DiagnosticDataProviderImpl.h b/src/platform/nxp/common/DiagnosticDataProviderImpl.h new file mode 100644 index 00000000000000..1f6af84e267f34 --- /dev/null +++ b/src/platform/nxp/common/DiagnosticDataProviderImpl.h @@ -0,0 +1,91 @@ +/* + * + * Copyright (c) 2021 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. + */ + +/** + * @file + * Provides an implementation of the DiagnosticDataProvider object. + */ + +#pragma once + +#include + +#include + +/** + * DiagnosticDataProviderImpl::ResetWiFiNetworkDiagnosticsCounts() is + * currently not supported due to missing reset feature from SDK's wifi driver. + * For this reason, the PKTCNT (beaconRxCount, packetMulticastRxCount, + * packetMulticastTxCount, packetUnicastRxCount, packetUnicastTxCount) + * and ERRCNT (beaconLostCount, overrunCount) features of DGWIFI cluster + * are currently not supported. + */ +#define DGWIFI_RESET_COUNTS_SUPPORTED 0 + +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the PlatformManager singleton object for Linux platforms. + */ +class DiagnosticDataProviderImpl : public DiagnosticDataProvider +{ +public: + static DiagnosticDataProviderImpl & GetDefaultInstance(); + + // ===== Methods that implement the PlatformManager abstract interface. + + CHIP_ERROR GetRebootCount(uint16_t & rebootCount) override; + CHIP_ERROR GetUpTime(uint64_t & upTime) override; + CHIP_ERROR GetTotalOperationalHours(uint32_t & totalOperationalHours) override; + CHIP_ERROR GetBootReason(BootReasonType & bootReason) override; + + CHIP_ERROR GetNetworkInterfaces(NetworkInterface ** netifpp) override; + void ReleaseNetworkInterfaces(NetworkInterface * netifp) override; + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + CHIP_ERROR GetWiFiBssId(MutableByteSpan & value) override; + CHIP_ERROR GetWiFiSecurityType(app::Clusters::WiFiNetworkDiagnostics::SecurityTypeEnum & securityType) override; + CHIP_ERROR GetWiFiVersion(app::Clusters::WiFiNetworkDiagnostics::WiFiVersionEnum & wifiVersion) override; + CHIP_ERROR GetWiFiChannelNumber(uint16_t & channelNumber) override; + CHIP_ERROR GetWiFiRssi(int8_t & rssi) override; +#if DGWIFI_RESET_COUNTS_SUPPORTED + CHIP_ERROR GetWiFiBeaconLostCount(uint32_t & beaconLostCount) override; + CHIP_ERROR GetWiFiBeaconRxCount(uint32_t & beaconRxCount) override; + CHIP_ERROR GetWiFiPacketMulticastRxCount(uint32_t & packetMulticastRxCount) override; + CHIP_ERROR GetWiFiPacketMulticastTxCount(uint32_t & packetMulticastTxCount) override; + CHIP_ERROR GetWiFiPacketUnicastTxCount(uint32_t & packetUnicastTxCount) override; + /** + * TODO : This should reset BeaconLostCount, BeaconRxCount, PacketMulticastRxCount, + * PacketMulticastTxCount, PacketUnicastRxCount, PacketUnicastTxCount + */ + // CHIP_ERROR ResetWiFiNetworkDiagnosticsCounts() override; +#endif /* DGWIFI_RESET_COUNTS_SUPPORTED */ +#endif /* CHIP_DEVICE_CONFIG_ENABLE_WPA */ +}; + +/** + * Returns the platform-specific implementation of the DiagnosticDataProvider singleton object. + * + * Applications can use this to gain access to features of the DiagnosticDataProvider + * that are specific to the selected platform. + */ +DiagnosticDataProvider & GetDiagnosticDataProviderImpl(); + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/InetNXPPlatformDefaultConfig.h b/src/platform/nxp/common/InetNXPPlatformDefaultConfig.h new file mode 100644 index 00000000000000..c8cff40ce31fe8 --- /dev/null +++ b/src/platform/nxp/common/InetNXPPlatformDefaultConfig.h @@ -0,0 +1,31 @@ +/* + * + * Copyright (c) 2020-2022 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 + * Platform-specific configuration overrides for the CHIP Inet + * Layer on NXP platforms using the NXP SDK. + * + */ + +#pragma once + +#include + +// ==================== Platform Adaptations ==================== diff --git a/src/platform/nxp/common/KeyValueStoreManagerImpl.cpp b/src/platform/nxp/common/KeyValueStoreManagerImpl.cpp new file mode 100644 index 00000000000000..8b704841374d21 --- /dev/null +++ b/src/platform/nxp/common/KeyValueStoreManagerImpl.cpp @@ -0,0 +1,96 @@ +/* + * + * Copyright (c) 2021-2022 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 + * Platform-specific key value storage implementation for NXP platforms + */ +/* this file behaves like a config.h, comes first */ +#include + +#include "NXPConfig.h" +#include "lib/support/CHIPMem.h" +#include +#include + +namespace chip { +namespace DeviceLayer { +namespace PersistedStorage { + +KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance; + +CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size, + size_t offset_bytes) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + size_t read_bytes; + + VerifyOrExit((key != NULL) && (value != NULL), err = CHIP_ERROR_INVALID_ARGUMENT); + + ChipLogProgress(DeviceLayer, "KVS, get key id:: %s", key); + + err = chip::DeviceLayer::Internal::NXPConfig::ReadConfigValueBin(key, (uint8_t *) value, value_size, read_bytes); + + *read_bytes_size = read_bytes; + +exit: + ConvertError(err); + return err; +} + +CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, size_t value_size) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit((key != NULL) && (value != NULL), err = CHIP_ERROR_INVALID_ARGUMENT); + + ChipLogProgress(DeviceLayer, "KVS, put key id:: %s ", key); + + err = chip::DeviceLayer::Internal::NXPConfig::WriteConfigValueBin(key, (uint8_t *) value, value_size); + +exit: + ConvertError(err); + return err; +} + +CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(key != NULL, err = CHIP_ERROR_INVALID_ARGUMENT); + + ChipLogProgress(DeviceLayer, "KVS, deleting key id:: %s", key); + + err = chip::DeviceLayer::Internal::NXPConfig::ClearConfigValue(key); + +exit: + ConvertError(err); + return err; +} + +void KeyValueStoreManagerImpl::ConvertError(CHIP_ERROR & err) +{ + if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) + { + err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; + } +} + +} // namespace PersistedStorage +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/KeyValueStoreManagerImpl.h b/src/platform/nxp/common/KeyValueStoreManagerImpl.h new file mode 100644 index 00000000000000..5b26c8f32a41f7 --- /dev/null +++ b/src/platform/nxp/common/KeyValueStoreManagerImpl.h @@ -0,0 +1,82 @@ +/* + * + * Copyright (c) 2021 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 + * Platform-specific key value storage implementation for NXP platforms + */ + +#pragma once + +namespace chip { +namespace DeviceLayer { +namespace PersistedStorage { + +class KeyValueStoreManagerImpl final : public KeyValueStoreManager +{ + // Allow the KeyValueStoreManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class KeyValueStoreManager; + +public: + // NOTE: Currently this platform does not support partial and offset reads + // these will return CHIP_ERROR_NOT_IMPLEMENTED. + CHIP_ERROR _Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size, size_t offset); + + CHIP_ERROR _Delete(const char * key); + + CHIP_ERROR _Put(const char * key, const void * value, size_t value_size); + +private: + // ===== Members for internal use by the following friends. + friend KeyValueStoreManager & KeyValueStoreMgr(); + friend KeyValueStoreManagerImpl & KeyValueStoreMgrImpl(); + + // Reading config values uses the NXPConfig API, which returns CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND + // error if a key was not found. Convert this error to the correct error KeyValueStoreManagerImpl + // should return: CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND + void ConvertError(CHIP_ERROR & err); + + static KeyValueStoreManagerImpl sInstance; +}; + +/** + * Returns the public interface of the KeyValueStoreManager singleton object. + * + * Chip applications should use this to access features of the KeyValueStoreManager object + * that are common to all platforms. + */ +inline KeyValueStoreManager & KeyValueStoreMgr(void) +{ + return KeyValueStoreManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the KeyValueStoreManager singleton object. + * + * Chip applications can use this to gain access to features of the KeyValueStoreManager + * that are specific to NXP platforms. + */ +inline KeyValueStoreManagerImpl & KeyValueStoreMgrImpl(void) +{ + return KeyValueStoreManagerImpl::sInstance; +} + +} // namespace PersistedStorage +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/Logging.cpp b/src/platform/nxp/common/Logging.cpp new file mode 100644 index 00000000000000..671a8dcbb123ef --- /dev/null +++ b/src/platform/nxp/common/Logging.cpp @@ -0,0 +1,97 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Nest Labs, Inc. + * 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. + */ +#include +#include + +#include "fsl_debug_console.h" +#include +#include + +#include +#include + +#include +#include +#include +#include + +namespace chip { +namespace Logging { +namespace Platform { + +/** + * CHIP log output function. + * Called only by ember-print (zcl log) + */ +void LogV(const char * module, uint8_t category, const char * msg, va_list v) +{ + char formattedMsg[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE] = { 0 }; + size_t prefixLen; + + /* First add the timestamp to the log message */ + snprintf(formattedMsg, sizeof(formattedMsg), "[%ld] ", xTaskGetTickCount()); + prefixLen = strlen(formattedMsg); + + /* Then add log category */ + switch (category) + { + case kLogCategory_Error: + snprintf(formattedMsg + prefixLen, sizeof(formattedMsg) - prefixLen, "%s ", "[ERR]"); + break; + + case kLogCategory_Progress: + snprintf(formattedMsg + prefixLen, sizeof(formattedMsg) - prefixLen, "%s ", "[INFO]"); + break; + + default: + snprintf(formattedMsg + prefixLen, sizeof(formattedMsg) - prefixLen, "%s ", "[TRACE]"); + break; + } + + prefixLen = strlen(formattedMsg); + + /* Add the module to the log output */ + snprintf(formattedMsg + prefixLen, sizeof(formattedMsg) - prefixLen, "[%s] ", module); + prefixLen = strlen(formattedMsg); + + // Append the log message. + vsnprintf(formattedMsg + prefixLen, sizeof(formattedMsg) - prefixLen, msg, v); + prefixLen = strlen(formattedMsg); + + /* Add CR+LF */ + snprintf(formattedMsg + prefixLen, sizeof(formattedMsg) - prefixLen, "%s", "\r\n"); + + PRINTF("%s", formattedMsg); +} + +/** + * LwIP log output function. + */ +extern "C" void LwIPLog(const char * msg, ...) +{ + va_list v; + + va_start(v, msg); + LogV("lwip", kLogCategory_Progress, msg, v); + va_end(v); +} + +} // namespace Platform +} // namespace Logging +} // namespace chip diff --git a/src/platform/nxp/common/NXPConfig.cpp b/src/platform/nxp/common/NXPConfig.cpp new file mode 100644 index 00000000000000..a90a3e44d05aa7 --- /dev/null +++ b/src/platform/nxp/common/NXPConfig.cpp @@ -0,0 +1,614 @@ +/* + * + * Copyright (c) 2020-2022 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. + */ + +/** + * @file + * Utilities for accessing persisted device configuration on + * platforms based on the NXP SDK. + */ +/* this file behaves like a config.h, comes first */ +#include + +#include "NXPConfig.h" + +#include "FreeRTOS.h" +#include "FunctionLib.h" +#include "board.h" +#include +#include + +/* FS Writes in Idle task only - LittleFS only , already enabled by default on NVM */ +#ifndef CHIP_PLAT_SAVE_NVM_DATA_ON_IDLE +#define CHIP_PLAT_SAVE_NVM_DATA_ON_IDLE 1 +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +#include "ot_platform_common.h" +#endif + +#define BUFFER_LOG_SIZE 256 +#define CHIP_CONFIG_RAM_BUFFER_KEY_INT_SIZE 4 * 2048 +#define CHIP_CONFIG_RAM_BUFFER_KEY_STRING_SIZE 4 * 5000 + +#ifndef NVM_ID_CHIP_CONFIG_DATA_KEY_INT +#define NVM_ID_CHIP_CONFIG_DATA_KEY_INT 0xf104 +#endif + +#ifndef NVM_ID_CHIP_CONFIG_DATA_KEY_STRING +#define NVM_ID_CHIP_CONFIG_DATA_KEY_STRING 0xf105 +#endif + +#if defined(DEBUG_NVM) && (DEBUG_NVM == 2) +#include "fsl_debug_console.h" +#define DBG_PRINTF PRINTF +#define INFO_PRINTF PRINTF + +#elif defined(DEBUG_NVM) && (DEBUG_NVM == 1) +#include "fsl_debug_console.h" +#define DBG_PRINTF PRINTF +#define INFO_PRINTF(...) + +#else +#define DBG_PRINTF(...) +#define INFO_PRINTF(...) +#endif + +#define FREERTOS_TIMER_TICKS_2_MS(ticks) (((uint64_t) ticks) * portTICK_PERIOD_MS) + +typedef struct +{ + uint16_t chipConfigRamBufferLen; + uint16_t padding; + uint8_t chipConfigRamBuffer[CHIP_CONFIG_RAM_BUFFER_KEY_INT_SIZE]; +} ChipConfigRamStructKeyInt; + +typedef struct +{ + uint16_t chipConfigRamBufferLen; + uint16_t padding; + uint8_t chipConfigRamBuffer[CHIP_CONFIG_RAM_BUFFER_KEY_STRING_SIZE]; +} ChipConfigRamStructKeyString; + +/* File system containing only integer keys */ +static ChipConfigRamStructKeyInt chipConfigRamStructKeyInt; +static ramBufferDescriptor ramDescrKeyInt = { + .ramBufferLen = &chipConfigRamStructKeyInt.chipConfigRamBufferLen, + .ramBufferMaxLen = CHIP_CONFIG_RAM_BUFFER_KEY_INT_SIZE, + .pRamBuffer = &chipConfigRamStructKeyInt.chipConfigRamBuffer[0], +}; + +/* File system containing only string keys */ +static ChipConfigRamStructKeyString chipConfigRamStructKeyString; +static ramBufferDescriptor ramDescrKeyString = { + .ramBufferLen = &chipConfigRamStructKeyString.chipConfigRamBufferLen, + .ramBufferMaxLen = CHIP_CONFIG_RAM_BUFFER_KEY_STRING_SIZE, + .pRamBuffer = &chipConfigRamStructKeyString.chipConfigRamBuffer[0], +}; + +static bool isInitialized = false; + +#if (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_NVM_FWK) +NVM_RegisterDataSet((void *) &chipConfigRamStructKeyInt, 1, sizeof(chipConfigRamStructKeyInt), NVM_ID_CHIP_CONFIG_DATA_KEY_INT, + gNVM_MirroredInRam_c); +NVM_RegisterDataSet((void *) &chipConfigRamStructKeyString, 1, sizeof(chipConfigRamStructKeyString), + NVM_ID_CHIP_CONFIG_DATA_KEY_STRING, gNVM_MirroredInRam_c); + +#elif (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_LITTLEFS) +const char * mt_key_int_file_name = "mt_key_int"; +const char * mt_key_str_file_name = "mt_key_str"; +#if CHIP_PLAT_SAVE_NVM_DATA_ON_IDLE +static bool mt_key_int_save_in_flash = false; +static bool mt_key_str_save_in_flash = false; +#endif + +#endif + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +int NXPConfig::SaveIntKeysToFS(void) +{ + int err_len; +#if (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_NVM_FWK) + err_len = -1; + NvSaveOnIdle(&chipConfigRamStructKeyInt, false); + +#elif (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_LITTLEFS) + err_len = -2; + +#if CHIP_PLAT_SAVE_NVM_DATA_ON_IDLE + mt_key_int_save_in_flash = true; +#else + + /* Save it in flash now */ + err_len = ramStorageSavetoFlash(mt_key_int_file_name, &chipConfigRamStructKeyInt.chipConfigRamBuffer[0], + chipConfigRamStructKeyInt.chipConfigRamBufferLen); + + assert(err_len <= CHIP_CONFIG_RAM_BUFFER_KEY_INT_SIZE); + assert(err_len >= 0); +#endif + +#else + + err_len = -3; +#endif + return err_len; +} + +int NXPConfig::SaveStringKeysToFS(void) +{ + int err_len; +#if (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_NVM_FWK) + err_len = -1; + NvSaveOnIdle(&chipConfigRamStructKeyInt, false); + +#elif (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_LITTLEFS) + err_len = -2; +#if CHIP_PLAT_SAVE_NVM_DATA_ON_IDLE + mt_key_str_save_in_flash = true; +#else + + /* Save it in flash now */ + err_len = ramStorageSavetoFlash(mt_key_str_file_name, &chipConfigRamStructKeyString.chipConfigRamBuffer[0], + chipConfigRamStructKeyString.chipConfigRamBufferLen); + + assert(err_len <= CHIP_CONFIG_RAM_BUFFER_KEY_STRING_SIZE); + assert(err_len >= 0); +#endif + +#else + err_len = -3; +#endif + + return err_len; +} + +CHIP_ERROR NXPConfig::Init() +{ + if (!isInitialized) + { + ramStorageInit(); + +#if (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_NVM_FWK) + /* Init the NVM module */ + NvModuleInit(); +#elif (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_LITTLEFS) + int err_len; + + /* Init the NVM module */ + err_len = FS_Init(); + assert(err_len >= 0); +#endif + + FLib_MemSet((void *) &chipConfigRamStructKeyInt, 0, sizeof(chipConfigRamStructKeyInt)); + FLib_MemSet((void *) &chipConfigRamStructKeyString, 0, sizeof(chipConfigRamStructKeyString)); + +#if (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_NVM_FWK) + /* Try to load the ot dataset in RAM */ + NvRestoreDataSet((void *) &chipConfigRamStructKeyInt, 0); + NvRestoreDataSet((void *) &chipConfigRamStructKeyString, 0); + +#elif (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_LITTLEFS) + /* Try to load the ot dataset in RAM */ + err_len = ramStorageReadFromFlash(mt_key_int_file_name, &chipConfigRamStructKeyInt.chipConfigRamBuffer[0], + CHIP_CONFIG_RAM_BUFFER_KEY_INT_SIZE); + assert(err_len <= CHIP_CONFIG_RAM_BUFFER_KEY_INT_SIZE); + assert(err_len >= 0); + chipConfigRamStructKeyInt.chipConfigRamBufferLen = (uint16_t) err_len; + + err_len = ramStorageReadFromFlash(mt_key_str_file_name, &chipConfigRamStructKeyString.chipConfigRamBuffer[0], + CHIP_CONFIG_RAM_BUFFER_KEY_STRING_SIZE); + assert(err_len <= CHIP_CONFIG_RAM_BUFFER_KEY_STRING_SIZE); + assert(err_len >= 0); + chipConfigRamStructKeyString.chipConfigRamBufferLen = (uint16_t) err_len; + +#endif + isInitialized = true; + } + + DBG_PRINTF("mt read %d / %d\r\n", chipConfigRamStructKeyInt.chipConfigRamBufferLen, + chipConfigRamStructKeyString.chipConfigRamBufferLen); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR NXPConfig::ReadConfigValue(Key key, bool & val) +{ + CHIP_ERROR err; + bool tempVal; + rsError status; + uint16_t sizeToRead = sizeof(tempVal); + + VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. + status = ramStorageGet(&ramDescrKeyInt, (uint8_t *) &key, sizeof(Key), 0, (uint8_t *) &tempVal, &sizeToRead); + SuccessOrExit(err = MapRamStorageStatus(status)); + val = tempVal; + + ChipLogProgress(DeviceLayer, "ReadConfigValue bool = %u", val); + +exit: + return err; +} + +CHIP_ERROR NXPConfig::ReadConfigValue(Key key, uint32_t & val) +{ + CHIP_ERROR err; + uint32_t tempVal; + rsError status; + uint16_t sizeToRead = sizeof(tempVal); + + VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. + status = ramStorageGet(&ramDescrKeyInt, (uint8_t *) &key, sizeof(Key), 0, (uint8_t *) &tempVal, &sizeToRead); + SuccessOrExit(err = MapRamStorageStatus(status)); + val = tempVal; + + ChipLogProgress(DeviceLayer, "ReadConfigValue uint32_t = %lu", val); + +exit: + return err; +} + +CHIP_ERROR NXPConfig::ReadConfigValue(Key key, uint64_t & val) +{ + CHIP_ERROR err; + uint32_t tempVal; + rsError status; + uint16_t sizeToRead = sizeof(tempVal); + + VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. + status = ramStorageGet(&ramDescrKeyInt, (uint8_t *) &key, sizeof(Key), 0, (uint8_t *) &tempVal, &sizeToRead); + SuccessOrExit(err = MapRamStorageStatus(status)); + val = tempVal; + + ChipLogProgress(DeviceLayer, "ReadConfigValue uint64_t = " ChipLogFormatX64, ChipLogValueX64(val)); + +exit: + return err; +} + +CHIP_ERROR NXPConfig::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen) +{ + CHIP_ERROR err; + rsError status; + uint16_t sizeToRead = bufSize; + + VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. + status = ramStorageGet(&ramDescrKeyInt, (uint8_t *) &key, sizeof(Key), 0, (uint8_t *) buf, &sizeToRead); + SuccessOrExit(err = MapRamStorageStatus(status)); + outLen = sizeToRead; + ChipLogProgress(DeviceLayer, "ReadConfigValueStr lenRead = %u", outLen); + +exit: + return err; +} + +CHIP_ERROR NXPConfig::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen) +{ + return ReadConfigValueStr(key, (char *) buf, bufSize, outLen); +} + +CHIP_ERROR NXPConfig::ReadConfigValueBin(const char * keyString, uint8_t * buf, size_t bufSize, size_t & outLen) +{ + CHIP_ERROR err; + rsError status; + uint16_t sizeToRead = bufSize; + + VerifyOrExit(keyString != NULL, err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. + status = ramStorageGet(&ramDescrKeyString, (const uint8_t *) keyString, strlen(keyString), 0, (uint8_t *) buf, &sizeToRead); + SuccessOrExit(err = MapRamStorageStatus(status)); + outLen = sizeToRead; + ChipLogProgress(DeviceLayer, "ReadConfigValueStr lenRead = %u", outLen); + +exit: + return err; +} + +CHIP_ERROR NXPConfig::ReadConfigValueCounter(uint8_t counterIdx, uint32_t & val) +{ + Key key = kMinConfigKey_ChipCounter + counterIdx; + return ReadConfigValue(key, val); +} + +CHIP_ERROR NXPConfig::WriteConfigValue(Key key, bool val) +{ + CHIP_ERROR err; + rsError status; + int err_len; + + VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. + status = ramStorageSet(&ramDescrKeyInt, (uint8_t *) &key, sizeof(Key), (uint8_t *) &val, sizeof(bool)); + SuccessOrExit(err = MapRamStorageStatus(status)); + + err_len = SaveIntKeysToFS(); + (void) err_len; + DBG_PRINTF("WriteConfigValue: MT write %d\r\n", err_len); + + ChipLogProgress(DeviceLayer, "WriteConfigValue done"); + +exit: + return err; +} + +CHIP_ERROR NXPConfig::WriteConfigValue(Key key, uint32_t val) +{ + CHIP_ERROR err; + rsError status; + int err_len; + + VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. + status = ramStorageSet(&ramDescrKeyInt, (uint8_t *) &key, sizeof(Key), (uint8_t *) &val, sizeof(uint32_t)); + SuccessOrExit(err = MapRamStorageStatus(status)); + + err_len = NXPConfig::SaveIntKeysToFS(); + (void) err_len; + DBG_PRINTF("WriteConfigValue: MT write %d\r\n", err_len); + + ChipLogProgress(DeviceLayer, "WriteConfigValue done"); + +exit: + return err; +} + +CHIP_ERROR NXPConfig::WriteConfigValue(Key key, uint64_t val) +{ + CHIP_ERROR err; + rsError status; + int err_len; + + VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. + status = ramStorageSet(&ramDescrKeyInt, (uint8_t *) &key, sizeof(Key), (uint8_t *) &val, sizeof(uint64_t)); + SuccessOrExit(err = MapRamStorageStatus(status)); + + err_len = NXPConfig::SaveIntKeysToFS(); + (void) err_len; + DBG_PRINTF("WriteConfigValue64: MT write %d\r\n", err_len); + + ChipLogProgress(DeviceLayer, "WriteConfigValue done"); + +exit: + return err; +} + +CHIP_ERROR NXPConfig::WriteConfigValueStr(Key key, const char * str) +{ + return WriteConfigValueStr(key, str, (str != NULL) ? strlen(str) : 0); +} + +CHIP_ERROR NXPConfig::WriteConfigValueStr(Key key, const char * str, size_t strLen) +{ + CHIP_ERROR err; + rsError status; + int err_len; + + VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. + status = ramStorageSet(&ramDescrKeyInt, (uint8_t *) &key, sizeof(Key), (uint8_t *) str, strLen); + SuccessOrExit(err = MapRamStorageStatus(status)); + + err_len = NXPConfig::SaveIntKeysToFS(); + (void) err_len; + DBG_PRINTF("WriteConfigValueStr: MT write %d\r\n", err_len); + + ChipLogProgress(DeviceLayer, "WriteConfigValue done"); + +exit: + return err; +} + +CHIP_ERROR NXPConfig::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen) +{ + return WriteConfigValueStr(key, (char *) data, dataLen); +} + +CHIP_ERROR NXPConfig::WriteConfigValueBin(const char * keyString, const uint8_t * data, size_t dataLen) +{ + CHIP_ERROR err; + rsError status; + int err_len; + + VerifyOrExit(keyString != NULL, err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. + status = ramStorageSet(&ramDescrKeyString, (const uint8_t *) keyString, strlen(keyString), (uint8_t *) data, dataLen); + SuccessOrExit(err = MapRamStorageStatus(status)); + + err_len = NXPConfig::SaveStringKeysToFS(); + (void) err_len; + DBG_PRINTF("WriteConfigValueBin: MT write %d\r\n", err_len); + + ChipLogProgress(DeviceLayer, "WriteConfigValue done"); + +exit: + return err; +} + +CHIP_ERROR NXPConfig::WriteConfigValueCounter(uint8_t counterIdx, uint32_t val) +{ + Key key = kMinConfigKey_ChipCounter + counterIdx; + return WriteConfigValue(key, val); +} + +CHIP_ERROR NXPConfig::ClearConfigValue(Key key) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + rsError status; + int err_len; + + VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. + status = ramStorageDelete(&ramDescrKeyInt, (uint8_t *) &key, sizeof(key), 0); + SuccessOrExit(err = MapRamStorageStatus(status)); + + err_len = NXPConfig::SaveIntKeysToFS(); + (void) err_len; + DBG_PRINTF("ClearConfigValue: MT write %d\r\n", err_len); + +exit: + return err; +} + +CHIP_ERROR NXPConfig::ClearConfigValue(const char * keyString) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + rsError status; + int err_len; + + VerifyOrExit(keyString != NULL, err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. + status = ramStorageDelete(&ramDescrKeyString, (const uint8_t *) keyString, strlen(keyString), 0); + SuccessOrExit(err = MapRamStorageStatus(status)); + + err_len = NXPConfig::SaveStringKeysToFS(); + (void) err_len; + DBG_PRINTF("WriteConfigValueBin: MT write %d\r\n", err_len); + +exit: + return err; +} + +bool NXPConfig::ConfigValueExists(Key key) +{ + rsError status; + uint16_t sizeToRead; + bool found = false; + + if (ValidConfigKey(key)) + { + status = ramStorageGet(&ramDescrKeyInt, (uint8_t *) &key, sizeof(Key), 0, NULL, &sizeToRead); + found = (status == RS_ERROR_NONE && sizeToRead != 0); + } + return found; +} + +CHIP_ERROR NXPConfig::FactoryResetConfig(void) +{ + + for (Key key = kMinConfigKey_ChipConfig; key <= kMaxConfigKey_ChipConfig; key++) + { + ClearConfigValue(key); + } + + /* Reset the key string file system as it contains on data that needs to be erased when doing a factoryreset */ + FLib_MemSet((void *) &chipConfigRamStructKeyString, 0, sizeof(chipConfigRamStructKeyString)); + + SaveStringKeysToFS(); + SaveIntKeysToFS(); + DBG_PRINTF("FactoryResetConfig done\r\n"); + + return CHIP_NO_ERROR; +} + +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)) + { + return true; + } + + return false; +} + +CHIP_ERROR NXPConfig::MapRamStorageStatus(rsError rsStatus) +{ + CHIP_ERROR err; + + switch (rsStatus) + { + case RS_ERROR_NONE: + err = CHIP_NO_ERROR; + break; + case RS_ERROR_NOT_FOUND: + err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + break; + case RS_ERROR_WRONG_ARG: + err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + assert(0); + break; + default: + err = CHIP_ERROR_BUFFER_TOO_SMALL; + break; + } + + return err; +} + +void NXPConfig::RunConfigUnitTest(void) {} + +void NXPConfig::RunSystemIdleTask(void) +{ + + if (isInitialized) + { +#if (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_NVM_FWK) + NvIdle(); + +#elif (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_LITTLEFS) +#if CHIP_PLAT_SAVE_NVM_DATA_ON_IDLE + if (mt_key_int_save_in_flash) + { + int err_len; + + /* Clear the flag first, so there could be an other write + if the buffer is updated when the write in flash has not completed fully */ + mt_key_int_save_in_flash = false; + + /* Save it in flash now */ + err_len = ramStorageSavetoFlash(mt_key_int_file_name, &chipConfigRamStructKeyInt.chipConfigRamBuffer[0], + chipConfigRamStructKeyInt.chipConfigRamBufferLen); + + assert(err_len <= CHIP_CONFIG_RAM_BUFFER_KEY_INT_SIZE); + assert(err_len >= 0); + + INFO_PRINTF("int mt write %d bytes / %d \r\n", err_len, chipConfigRamStructKeyInt.chipConfigRamBufferLen); +#if 0 + int len = ramStorageReadFromFlash(mt_key_int_file_name, &chipConfigRamStructKeyInt.chipConfigRamBuffer[0], CHIP_CONFIG_RAM_BUFFER_KEY_INT_SIZE); + INFO_PRINTF("mt read after write %d\r\n", len); +#endif + } + + if (mt_key_str_save_in_flash) + { + int err_len; + + /* Clear the flag first, so there could be an other write + if the buffer is updated when the write in flash has not completed fully */ + mt_key_str_save_in_flash = false; + + /* Save it in flash now */ + err_len = ramStorageSavetoFlash(mt_key_str_file_name, &chipConfigRamStructKeyString.chipConfigRamBuffer[0], + chipConfigRamStructKeyString.chipConfigRamBufferLen); + + assert(err_len <= CHIP_CONFIG_RAM_BUFFER_KEY_STRING_SIZE); + assert(err_len >= 0); + + INFO_PRINTF("str mt write %d bytes / %d \r\n", err_len, chipConfigRamStructKeyString.chipConfigRamBufferLen); +#if 0 + int len = ramStorageReadFromFlash(mt_key_str_file_name, &chipConfigRamStructKeyString.chipConfigRamBuffer[0], CHIP_CONFIG_RAM_BUFFER_KEY_STRING_SIZE); + INFO_PRINTF("mt read after write %d\r\n", len); +#endif + } +#endif +#endif + } + +#if (defined(LOG_ENABLE) && (LOG_ENABLE > 0)) && ((defined LOG_ENABLE_ASYNC_MODE) && (LOG_ENABLE_ASYNC_MODE)) + LOG_Dump(bufferLog, sizeof(bufferLog), NULL); +#endif +} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/NXPConfig.h b/src/platform/nxp/common/NXPConfig.h new file mode 100644 index 00000000000000..c20dc7e5071d48 --- /dev/null +++ b/src/platform/nxp/common/NXPConfig.h @@ -0,0 +1,201 @@ +/* + * + * Copyright (c) 2020-2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Utilities for accessing persisted device configuration on + * platforms based on the NXP SDK. + */ + +#pragma once + +#include + +#include "FreeRTOS.h" +#include + +#define CHIP_PLAT_NO_NVM 0 +#define CHIP_PLAT_NVM_FWK 1 +#define CHIP_PLAT_LITTLEFS 2 +#define CHIP_PLAT_KEY_STORAGE 3 + +#define DEBUG_NVM 0 + +#ifndef CHIP_PLAT_NVM_SUPPORT +#define CHIP_PLAT_NVM_SUPPORT CHIP_PLAT_NO_NVM +#endif + +#if (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_NVM_FWK) +#include "NVM_Interface.h" +#elif (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_LITTLEFS) +#include "fwk_filesystem.h" +#endif + +#if (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_KEY_STORAGE) +#include "fwk_key_storage.h" +#else +#include "ram_storage.h" +#endif + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +/* Base for the category calculation when determining the key IDs */ +#define CATEGORY_BASE 0x01 + +constexpr inline uint16_t config_key(uint8_t chipId, uint8_t pdmId) +{ + return static_cast(chipId) << 8 | pdmId; +} + +/** + * This implementation uses the NVM component from Connectivity Framework or the + * The Little FS component depending on CHIP_PLAT_NVM_SUPPORT defined in the build system + * + * NOTE: This class is designed to be mixed-in to the concrete subclass of the + * GenericConfigurationManagerImpl<> template. When used this way, the class + * naturally provides implementations for the delegated members referenced by + * the template class (e.g. the ReadConfigValue() method). + */ +class NXPConfig +{ +public: + // Category ids used by the CHIP Device Layer + static constexpr uint8_t kFileId_ChipFactory = CATEGORY_BASE; /**< Category containing persistent config values set at + * manufacturing time. Retained during factory reset. */ + static constexpr uint8_t kFileId_ChipConfig = CATEGORY_BASE + 1; /**< Catyegory containing dynamic config values set at runtime. + * Cleared during factory reset. */ + static constexpr uint8_t kFileId_ChipCounter = CATEGORY_BASE + 2; /**< Category containing dynamic counter values set at + * runtime. Retained during factory reset. */ + static constexpr uint8_t kFileId_KVS = CATEGORY_BASE + 3; /**< Category containing KVS set at runtime. + * Cleared during factory reset. */ + + using Key = uint16_t; + + // Key definitions for well-known configuration values. + // Factory config keys + static constexpr Key kConfigKey_SerialNum = config_key(kFileId_ChipFactory, 0x00); + static constexpr Key kConfigKey_UniqueId = config_key(kFileId_ChipFactory, 0x01); + static constexpr Key kConfigKey_MfrDeviceId = config_key(kFileId_ChipFactory, 0x02); + static constexpr Key kConfigKey_MfrDeviceCert = config_key(kFileId_ChipFactory, 0x03); + static constexpr Key kConfigKey_MfrDevicePrivateKey = config_key(kFileId_ChipFactory, 0x04); + static constexpr Key kConfigKey_ManufacturingDate = config_key(kFileId_ChipFactory, 0x05); + static constexpr Key kConfigKey_SetupPinCode = config_key(kFileId_ChipFactory, 0x06); + static constexpr Key kConfigKey_MfrDeviceICACerts = config_key(kFileId_ChipFactory, 0x07); + static constexpr Key kConfigKey_HardwareVersion = config_key(kFileId_ChipFactory, 0x08); + static constexpr Key kConfigKey_SetupDiscriminator = config_key(kFileId_ChipFactory, 0x09); + static constexpr Key kConfigKey_Spake2pIterationCount = config_key(kFileId_ChipFactory, 0x0A); + static constexpr Key kConfigKey_Spake2pSalt = config_key(kFileId_ChipFactory, 0x0B); + static constexpr Key kConfigKey_Spake2pVerifier = config_key(kFileId_ChipFactory, 0x0C); + + // CHIP Config Keys + static constexpr Key kConfigKey_FabricId = config_key(kFileId_ChipConfig, 0x00); + static constexpr Key kConfigKey_ServiceConfig = config_key(kFileId_ChipConfig, 0x01); + static constexpr Key kConfigKey_PairedAccountId = config_key(kFileId_ChipConfig, 0x02); + static constexpr Key kConfigKey_ServiceId = config_key(kFileId_ChipConfig, 0x03); + static constexpr Key kConfigKey_FabricSecret = config_key(kFileId_ChipConfig, 0x04); + static constexpr Key kConfigKey_LastUsedEpochKeyId = config_key(kFileId_ChipConfig, 0x05); + static constexpr Key kConfigKey_FailSafeArmed = config_key(kFileId_ChipConfig, 0x06); + + static constexpr Key kConfigKey_OperationalDeviceId = config_key(kFileId_ChipConfig, 0x07); + static constexpr Key kConfigKey_OperationalDeviceCert = config_key(kFileId_ChipConfig, 0x08); + static constexpr Key kConfigKey_OperationalDeviceICACerts = config_key(kFileId_ChipConfig, 0x09); + static constexpr Key kConfigKey_OperationalDevicePrivateKey = config_key(kFileId_ChipConfig, 0x0A); + + static constexpr Key kConfigKey_RegulatoryLocation = config_key(kFileId_ChipConfig, 0x0B); + static constexpr Key kConfigKey_CountryCode = config_key(kFileId_ChipConfig, 0x0C); + static constexpr Key kConfigKey_Breadcrumb = config_key(kFileId_ChipConfig, 0x0D); + + // CHIP Counter Keys + static constexpr Key kCounterKey_RebootCount = config_key(kFileId_ChipCounter, 0x00); + static constexpr Key kCounterKey_UpTime = config_key(kFileId_ChipCounter, 0x01); + static constexpr Key kCounterKey_TotalOperationalHours = config_key(kFileId_ChipCounter, 0x02); + static constexpr Key kCounterKey_BootReason = config_key(kFileId_ChipCounter, 0x03); + + static constexpr Key kConfigKey_GroupKey = config_key(kFileId_ChipConfig, 0x0E); + static constexpr Key kConfigKey_GroupKey0 = config_key(kFileId_ChipConfig, 0x0F); + static constexpr Key kConfigKey_GroupKey1 = config_key(kFileId_ChipConfig, 0x10); + static constexpr Key kConfigKey_GroupKey2 = config_key(kFileId_ChipConfig, 0x11); + static constexpr Key kConfigKey_GroupKey3 = config_key(kFileId_ChipConfig, 0x12); + static constexpr Key kConfigKey_GroupKey4 = config_key(kFileId_ChipConfig, 0x13); + static constexpr Key kConfigKey_GroupKey5 = config_key(kFileId_ChipConfig, 0x14); + static constexpr Key kConfigKey_GroupKey6 = config_key(kFileId_ChipConfig, 0x15); + static constexpr Key kConfigKey_GroupKey7 = config_key(kFileId_ChipConfig, 0x16); + static constexpr Key kConfigKey_GroupKey8 = config_key(kFileId_ChipConfig, 0x17); + static constexpr Key kConfigKey_GroupKey9 = config_key(kFileId_ChipConfig, 0x18); + static constexpr Key kConfigKey_GroupKey10 = config_key(kFileId_ChipConfig, 0x19); + static constexpr Key kConfigKey_GroupKey11 = config_key(kFileId_ChipConfig, 0x1A); + static constexpr Key kConfigKey_GroupKey12 = config_key(kFileId_ChipConfig, 0x1B); + static constexpr Key kConfigKey_GroupKey13 = config_key(kFileId_ChipConfig, 0x1C); + static constexpr Key kConfigKey_GroupKey14 = config_key(kFileId_ChipConfig, 0x1D); + static constexpr Key kConfigKey_GroupKey15 = config_key(kFileId_ChipConfig, 0x1E); + + static constexpr Key kConfigKey_GroupKeyBase = kConfigKey_GroupKey0; + static constexpr Key kConfigKey_GroupKeyMax = config_key(kFileId_ChipConfig, 0x1E); + ; // Allows 16 Group Keys to be created. + + // 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); + static constexpr Key kMinConfigKey_ChipConfig = config_key(kFileId_ChipConfig, 0x00); + static constexpr Key kMaxConfigKey_ChipConfig = config_key(kFileId_ChipConfig, 0x1E); + static constexpr Key kMinConfigKey_ChipCounter = config_key(kFileId_ChipCounter, 0x00); + 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 CHIP_ERROR Init(void); + + // Configuration methods used by the GenericConfigurationManagerImpl<> template. + static CHIP_ERROR ReadConfigValue(Key key, bool & val); + static CHIP_ERROR ReadConfigValue(Key key, uint32_t & val); + static CHIP_ERROR ReadConfigValue(Key key, uint64_t & val); + static CHIP_ERROR ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen); + static CHIP_ERROR ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen); + static CHIP_ERROR ReadConfigValueBin(const char * keyString, uint8_t * buf, size_t bufSize, size_t & outLen); + static CHIP_ERROR ReadConfigValueCounter(uint8_t counterIdx, uint32_t & val); + static CHIP_ERROR WriteConfigValue(Key key, bool val); + static CHIP_ERROR WriteConfigValue(Key key, uint32_t val); + static CHIP_ERROR WriteConfigValue(Key key, uint64_t val); + static CHIP_ERROR WriteConfigValueStr(Key key, const char * str); + static CHIP_ERROR WriteConfigValueStr(Key key, const char * str, size_t strLen); + static CHIP_ERROR WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen); + static CHIP_ERROR WriteConfigValueBin(const char * keyString, const uint8_t * data, size_t dataLen); + static CHIP_ERROR WriteConfigValueCounter(uint8_t counterIdx, uint32_t val); + static CHIP_ERROR ClearConfigValue(Key key); + static CHIP_ERROR ClearConfigValue(const char * keyString); + static bool ConfigValueExists(Key key); + static CHIP_ERROR FactoryResetConfig(void); + static bool ValidConfigKey(Key key); + + static void RunConfigUnitTest(void); + static void RunSystemIdleTask(void); + +private: +#if (CHIP_PLAT_NVM_SUPPORT == CHIP_PLAT_KEY_STORAGE) + static CHIP_ERROR MapKeyStorageStatus(ks_error_t ksStatus); +#else + static CHIP_ERROR MapRamStorageStatus(rsError rsStatus); +#endif + static int SaveIntKeysToFS(void); + static int SaveStringKeysToFS(void); +}; + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/NetworkCommissioningDriver.h b/src/platform/nxp/common/NetworkCommissioningDriver.h new file mode 100644 index 00000000000000..4e7c9f0292e47b --- /dev/null +++ b/src/platform/nxp/common/NetworkCommissioningDriver.h @@ -0,0 +1,114 @@ +/* + * + * Copyright (c) 2021-2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace chip { +namespace DeviceLayer { +namespace NetworkCommissioning { +#if CHIP_DEVICE_CONFIG_ENABLE_WPA +namespace { +constexpr uint8_t kMaxWiFiNetworks = 1; +constexpr uint8_t kWiFiScanNetworksTimeOutSeconds = 10; +constexpr uint8_t kWiFiConnectNetworkTimeoutSeconds = + 80; // 60 seconds is DHCP_TIMEOUT from [NXP MCUXpresso SDK]/middleware/wifi_nxp/port/lwip/net.c +} // namespace + +class NXPWiFiDriver final : public WiFiDriver +{ +public: + class WiFiNetworkIterator final : public NetworkIterator + { + public: + WiFiNetworkIterator(NXPWiFiDriver * aDriver) : mDriver(aDriver) {} + size_t Count() override; + bool Next(Network & item) override; + void Release() override { delete this; } + ~WiFiNetworkIterator() = default; + + private: + NXPWiFiDriver * mDriver; + bool mExhausted = false; + }; + + struct WiFiNetwork + { + char ssid[DeviceLayer::Internal::kMaxWiFiSSIDLength]; + uint8_t ssidLen = 0; + char credentials[DeviceLayer::Internal::kMaxWiFiKeyLength]; + uint8_t credentialsLen = 0; + }; + + // BaseDriver + NetworkIterator * GetNetworks() override { return new WiFiNetworkIterator(this); } + CHIP_ERROR Init(NetworkStatusChangeCallback * networkStatusChangeCallback) override; + void Shutdown() override; + + // WirelessDriver + uint8_t GetMaxNetworks() override { return kMaxWiFiNetworks; } + uint8_t GetScanNetworkTimeoutSeconds() override { return kWiFiScanNetworksTimeOutSeconds; } + uint8_t GetConnectNetworkTimeoutSeconds() override { return kWiFiConnectNetworkTimeoutSeconds; } + + CHIP_ERROR CommitConfiguration() override; + CHIP_ERROR RevertConfiguration() override; + + Status RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex) override; + Status ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText) override; + void ConnectNetwork(ByteSpan networkId, ConnectCallback * callback) override; + + /* Returns the network SSID. User needs to allocate a buffer of size >= DeviceLayer::Internal::kMaxWiFiSSIDLength. + * ssid - pointer to the returned SSID + */ + Status GetNetworkSSID(char * ssid); + + /* Returns the network password. User needs to allocate a buffer of size >= DeviceLayer::Internal::kMaxWiFiKeyLength. + * credentials - pointer to the returned password + */ + Status GetNetworkPassword(char * credentials); + + // WiFiDriver + Status AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials, MutableCharSpan & outDebugText, + uint8_t & outNetworkIndex) override; + void ScanNetworks(ByteSpan ssid, ScanCallback * callback) override; + + CHIP_ERROR ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, const char * key, uint8_t keyLen); + void OnConnectWiFiNetwork(Status commissioningError, CharSpan debugText, int32_t connectStatus); + static int OnScanWiFiNetworkDone(unsigned int count); + static NXPWiFiDriver & GetInstance() + { + static NXPWiFiDriver instance; + return instance; + } + +private: + bool NetworkMatch(const WiFiNetwork & network, ByteSpan networkId); + CHIP_ERROR StartScanWiFiNetworks(ByteSpan ssid); + + WiFiNetworkIterator mWiFiIterator = WiFiNetworkIterator(this); + WiFiNetwork mSavedNetwork; + WiFiNetwork mStagingNetwork; + ScanCallback * mpScanCallback; + ConnectCallback * mpConnectCallback; + NetworkStatusChangeCallback * mpStatusChangeCallback = nullptr; +}; +#endif // CHIP_DEVICE_CONFIG_ENABLE_WPA + +} // namespace NetworkCommissioning +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/NetworkCommissioningWiFiDriver.cpp b/src/platform/nxp/common/NetworkCommissioningWiFiDriver.cpp new file mode 100644 index 00000000000000..7863b511b227c2 --- /dev/null +++ b/src/platform/nxp/common/NetworkCommissioningWiFiDriver.cpp @@ -0,0 +1,447 @@ +/* + * + * Copyright (c) 2021-2022 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. + */ +#include + +#include "NetworkCommissioningDriver.h" +#include +#include +#include + +using namespace ::chip; + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA +namespace chip { +namespace DeviceLayer { +namespace NetworkCommissioning { + +namespace { +constexpr char kWiFiSSIDKeyName[] = "wifi-ssid"; +constexpr char kWiFiCredentialsKeyName[] = "wifi-pass"; +} // namespace + +class NXPScanResponseIterator : public Iterator +{ +public: + NXPScanResponseIterator(const size_t size, WiFiScanResponse * responses) : mSize(size), mResponses(responses) {} + size_t Count() override { return mSize; } + bool Next(WiFiScanResponse & item) override + { + if (mIternum >= mSize) + { + return false; + } + + item = mResponses[mIternum]; + mIternum++; + + return true; + } + void Release() override {} + +private: + const size_t mSize; + WiFiScanResponse * mResponses; + size_t mIternum = 0; +}; + +CHIP_ERROR NXPWiFiDriver::Init(NetworkStatusChangeCallback * networkStatusChangeCallback) +{ + CHIP_ERROR err; + size_t ssidLen = 0; + size_t credentialsLen = 0; + + err = PersistedStorage::KeyValueStoreMgr().Get(kWiFiSSIDKeyName, mSavedNetwork.ssid, sizeof(mSavedNetwork.ssid), &ssidLen); + if (err != CHIP_NO_ERROR) + { + ChipLogProgress(DeviceLayer, "WiFi network SSID not retrieved from persisted storage: %" CHIP_ERROR_FORMAT, err.Format()); + return CHIP_NO_ERROR; + } + + err = PersistedStorage::KeyValueStoreMgr().Get(kWiFiCredentialsKeyName, mSavedNetwork.credentials, + sizeof(mSavedNetwork.credentials), &credentialsLen); + if (err != CHIP_NO_ERROR) + { + ChipLogProgress(DeviceLayer, "WiFi network credentials not retrieved from persisted storage: %" CHIP_ERROR_FORMAT, + err.Format()); + return CHIP_NO_ERROR; + } + + mSavedNetwork.credentialsLen = credentialsLen; + mSavedNetwork.ssidLen = ssidLen; + + mStagingNetwork = mSavedNetwork; + mpScanCallback = nullptr; + mpConnectCallback = nullptr; + mpStatusChangeCallback = networkStatusChangeCallback; + + // Connect to saved network + ConnectWiFiNetwork(mSavedNetwork.ssid, ssidLen, mSavedNetwork.credentials, credentialsLen); + + return err; +} + +void NXPWiFiDriver::Shutdown() +{ + mpStatusChangeCallback = nullptr; +} + +CHIP_ERROR NXPWiFiDriver::CommitConfiguration() +{ + ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiSSIDKeyName, mStagingNetwork.ssid, mStagingNetwork.ssidLen)); + ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiCredentialsKeyName, mStagingNetwork.credentials, + mStagingNetwork.credentialsLen)); + mSavedNetwork = mStagingNetwork; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR NXPWiFiDriver::RevertConfiguration() +{ + mStagingNetwork = mSavedNetwork; + + return CHIP_NO_ERROR; +} + +bool NXPWiFiDriver::NetworkMatch(const WiFiNetwork & network, ByteSpan networkId) +{ + return networkId.size() == network.ssidLen && memcmp(networkId.data(), network.ssid, network.ssidLen) == 0; +} + +Status NXPWiFiDriver::AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials, MutableCharSpan & outDebugText, + uint8_t & outNetworkIndex) +{ + outDebugText.reduce_size(0); + outNetworkIndex = 0; + VerifyOrReturnError(mStagingNetwork.ssidLen == 0 || NetworkMatch(mStagingNetwork, ssid), Status::kBoundsExceeded); + VerifyOrReturnError(credentials.size() <= sizeof(mStagingNetwork.credentials), Status::kOutOfRange); + VerifyOrReturnError(ssid.size() <= sizeof(mStagingNetwork.ssid), Status::kOutOfRange); + + memcpy(mStagingNetwork.credentials, credentials.data(), credentials.size()); + mStagingNetwork.credentialsLen = static_cast(credentials.size()); + + memcpy(mStagingNetwork.ssid, ssid.data(), ssid.size()); + mStagingNetwork.ssidLen = static_cast(ssid.size()); + + return Status::kSuccess; +} + +Status NXPWiFiDriver::RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex) +{ + outDebugText.reduce_size(0); + outNetworkIndex = 0; + VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound); + + // Use empty ssid for representing invalid network + mStagingNetwork.ssidLen = 0; + memset(mStagingNetwork.ssid, 0, DeviceLayer::Internal::kMaxWiFiSSIDLength); + memset(mStagingNetwork.credentials, 0, DeviceLayer::Internal::kMaxWiFiKeyLength); + return Status::kSuccess; +} + +/* Returns the network SSID. User needs to allocate a buffer of size >= DeviceLayer::Internal::kMaxWiFiSSIDLength. + * ssid - pointer to the returned SSID + */ +Status NXPWiFiDriver::GetNetworkSSID(char * ssid) +{ + VerifyOrReturnError(ssid != NULL, Status::kOutOfRange); + + memcpy(ssid, mStagingNetwork.ssid, mStagingNetwork.ssidLen); + return Status::kSuccess; +} + +/* Returns the network password. User needs to allocate a buffer of size >= DeviceLayer::Internal::kMaxWiFiKeyLength. + * credentials - pointer to the returned password + */ +Status NXPWiFiDriver::GetNetworkPassword(char * credentials) +{ + VerifyOrReturnError(credentials != NULL, Status::kOutOfRange); + + memcpy(credentials, mStagingNetwork.credentials, mStagingNetwork.credentialsLen); + return Status::kSuccess; +} + +Status NXPWiFiDriver::ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText) +{ + outDebugText.reduce_size(0); + + // Only one network is supported now + VerifyOrReturnError(index == 0, Status::kOutOfRange); + VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound); + + return Status::kSuccess; +} + +CHIP_ERROR NXPWiFiDriver::ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, const char * key, uint8_t keyLen) +{ + return ConnectivityMgrImpl().ProvisionWiFiNetwork(ssid, ssidLen, key, keyLen); +} + +void NXPWiFiDriver::OnConnectWiFiNetwork(Status commissioningError, CharSpan debugText, int32_t connectStatus) +{ + if (mpConnectCallback != nullptr) + { + mpConnectCallback->OnResult(commissioningError, debugText, connectStatus); + mpConnectCallback = nullptr; + } +} + +void NXPWiFiDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * callback) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + Status networkingStatus = Status::kSuccess; + + ChipLogProgress(NetworkProvisioning, "Connecting to WiFi network: SSID: %.*s", static_cast(networkId.size()), + networkId.data()); + + VerifyOrExit(NetworkMatch(mStagingNetwork, networkId), networkingStatus = Status::kNetworkIDNotFound); + VerifyOrExit(mpConnectCallback == nullptr, networkingStatus = Status::kUnknownError); + + mpConnectCallback = callback; + err = ConnectWiFiNetwork(reinterpret_cast(mStagingNetwork.ssid), mStagingNetwork.ssidLen, + reinterpret_cast(mStagingNetwork.credentials), mStagingNetwork.credentialsLen); + +exit: + if (err != CHIP_NO_ERROR) + { + networkingStatus = Status::kUnknownError; + } + + if (networkingStatus != Status::kSuccess) + { + ChipLogError(NetworkProvisioning, "Failed to start connecting to WiFi network: %" CHIP_ERROR_FORMAT, err.Format()); + mpConnectCallback = nullptr; + } + + /* Always inform the cluster of the network status so that in case of success, + * we have time send the response to the controller before switching to a new network. + */ + if (callback != nullptr) + { + callback->OnResult(networkingStatus, CharSpan(), 0); + } +} + +CHIP_ERROR NXPWiFiDriver::StartScanWiFiNetworks(ByteSpan ssid) +{ + wlan_scan_params_v2_t wlan_scan_param; + + ChipLogProgress(DeviceLayer, "Scan for WiFi network(s) requested"); + + (void) memset(&wlan_scan_param, 0, sizeof(wlan_scan_params_v2_t)); + wlan_scan_param.cb = &NXPWiFiDriver::OnScanWiFiNetworkDone; + + if ((ssid.size() > 0) && (ssid.size() < MLAN_MAX_SSID_LENGTH)) + { +#ifdef CONFIG_COMBO_SCAN + (void) memcpy(wlan_scan_param.ssid[0], ssid.data(), ssid.size()); +#else + (void) memcpy(wlan_scan_param.ssid, ssid.data(), ssid.size()); +#endif + } + + int status = wlan_scan_with_opt(wlan_scan_param); + if (status != WM_SUCCESS) + { + ChipLogError(DeviceLayer, "Failed to start scan for WiFi network(s): %d", status); + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +// TODO should be modified to do it in the context of the Matter stack +int NXPWiFiDriver::OnScanWiFiNetworkDone(unsigned int count) +{ + ChipLogProgress(DeviceLayer, "Scan for WiFi network(s) done, found: %u", count); + + if (count == 0) + { + if (GetInstance().mpScanCallback != nullptr) + { + GetInstance().mpScanCallback->OnFinished(Status::kSuccess, CharSpan(), nullptr); + GetInstance().mpScanCallback = nullptr; + } + return WM_SUCCESS; + } + + std::unique_ptr response_list_ptr(new struct WiFiScanResponse[count]); + if (response_list_ptr == nullptr) + { + ChipLogError(DeviceLayer, "Can't allocate memory for scan response_list"); + if (GetInstance().mpScanCallback) + { + GetInstance().mpScanCallback->OnFinished(Status::kUnknownError, CharSpan(), nullptr); + GetInstance().mpScanCallback = nullptr; + } + return WM_SUCCESS; + } + + struct WiFiScanResponse * response_list = response_list_ptr.get(); + + int valid = 0; + + for (int i = 0; i < count; i++) + { + struct wlan_scan_result res; + struct WiFiScanResponse response; + + int status = wlan_get_scan_result(i, &res); + + if (status != WM_SUCCESS) + { + ChipLogError(DeviceLayer, "Can't get scan result: %d", status); + continue; + } + + response.security = WiFiSecurity::kUnencrypted; + + if (res.wep != 0U) + { + response.security = WiFiSecurity::kWep; + } + else if (res.wpa != 0U) + { + response.security = WiFiSecurity::kWpaPersonal; + } + else if (res.wpa2 != 0U) + { + response.security = WiFiSecurity::kWpa2Personal; + } + else if (res.wpa3_sae != 0U) + { + response.security = WiFiSecurity::kWpa3Personal; + } + else if (res.wpa2_entp != 0U) + { + // ChipLogProgress(DeviceLayer, "Ignoring scanned network with WPA2-Enterprise security"); + // continue; + } + + if (res.ssid_len > DeviceLayer::Internal::kMaxWiFiSSIDLength) + { + ChipLogError(DeviceLayer, "Ignoring scanned network with too long SSID: %u", res.ssid_len); + continue; + } + memcpy(response.ssid, res.ssid, res.ssid_len); + response.ssidLen = res.ssid_len; + + memcpy(response.bssid, res.bssid, DeviceLayer::Internal::kWiFiBSSIDLength); + + response.channel = (uint16_t) res.channel; + response.wiFiBand = chip::DeviceLayer::NetworkCommissioning::WiFiBand::k2g4; // TODO 5 GHz also possible, but results don't + // show this information + response.rssi = -static_cast(res.rssi); + + response_list[valid] = response; + + valid++; + } + + if (CHIP_NO_ERROR == DeviceLayer::SystemLayer().ScheduleLambda([valid, response_list]() { + std::unique_ptr auto_free(response_list); + NXPScanResponseIterator iter(valid, response_list); + if (GetInstance().mpScanCallback) + { + GetInstance().mpScanCallback->OnFinished(Status::kSuccess, CharSpan(), &iter); + GetInstance().mpScanCallback = nullptr; + } + else + { + ChipLogError(DeviceLayer, "Can't find the ScanCallback function"); + } + })) + { + response_list_ptr.release(); + } + + return WM_SUCCESS; +} + +void NXPWiFiDriver::ScanNetworks(ByteSpan ssid, WiFiDriver::ScanCallback * callback) +{ + if (callback != nullptr) + { + mpScanCallback = callback; + if (StartScanWiFiNetworks(ssid) != CHIP_NO_ERROR) + { + mpScanCallback = nullptr; + callback->OnFinished(Status::kUnknownError, CharSpan(), nullptr); + } + } +} + +static CHIP_ERROR GetConnectedNetwork(Network & network) +{ + struct wlan_network wlan_network; + int result; + + result = wlan_get_current_network(&wlan_network); + if (result != WM_SUCCESS) + { + return CHIP_ERROR_INTERNAL; + } + + uint8_t length = strnlen(reinterpret_cast(wlan_network.ssid), DeviceLayer::Internal::kMaxWiFiSSIDLength); + + if (length > sizeof(network.networkID)) + { + return CHIP_ERROR_INTERNAL; + } + + memcpy(network.networkID, wlan_network.ssid, length); + network.networkIDLen = length; + + return CHIP_NO_ERROR; +} + +size_t NXPWiFiDriver::WiFiNetworkIterator::Count() +{ + return mDriver->mStagingNetwork.ssidLen == 0 ? 0 : 1; +} + +bool NXPWiFiDriver::WiFiNetworkIterator::Next(Network & item) +{ + if (mExhausted || mDriver->mStagingNetwork.ssidLen == 0) + { + return false; + } + + memcpy(item.networkID, mDriver->mStagingNetwork.ssid, mDriver->mStagingNetwork.ssidLen); + item.networkIDLen = mDriver->mStagingNetwork.ssidLen; + item.connected = false; + mExhausted = true; + + Network connectedNetwork; + CHIP_ERROR err = GetConnectedNetwork(connectedNetwork); + + if (err == CHIP_NO_ERROR) + { + if (connectedNetwork.networkIDLen == item.networkIDLen && + memcmp(connectedNetwork.networkID, item.networkID, item.networkIDLen) == 0) + { + item.connected = true; + } + } + + return true; +} + +} // namespace NetworkCommissioning +} // namespace DeviceLayer +} // namespace chip +#endif // CHIP_DEVICE_CONFIG_ENABLE_WPA diff --git a/src/platform/nxp/common/NetworkProvisioningServerImpl.cpp b/src/platform/nxp/common/NetworkProvisioningServerImpl.cpp new file mode 100644 index 00000000000000..bf8a8925963528 --- /dev/null +++ b/src/platform/nxp/common/NetworkProvisioningServerImpl.cpp @@ -0,0 +1,41 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Nest Labs, Inc. + * 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. + */ +/* this file behaves like a config.h, comes first */ +#include + +#include +#include + +#include +#include + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +NetworkProvisioningServerImpl NetworkProvisioningServerImpl::sInstance; + +CHIP_ERROR NetworkProvisioningServerImpl::_Init(void) +{ + return GenericNetworkProvisioningServerImpl::DoInit(); +} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/NetworkProvisioningServerImpl.h b/src/platform/nxp/common/NetworkProvisioningServerImpl.h new file mode 100644 index 00000000000000..42cc1c914ac090 --- /dev/null +++ b/src/platform/nxp/common/NetworkProvisioningServerImpl.h @@ -0,0 +1,80 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Nest Labs, Inc. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +/** + * Concrete implementation of the NetworkProvisioningServer singleton object for the + * NXP platforms. + */ +class NetworkProvisioningServerImpl final : public NetworkProvisioningServer, + public Internal::GenericNetworkProvisioningServerImpl +{ + // Allow the NetworkProvisioningServer interface class to delegate method calls to + // the implementation methods provided by this class. + friend class ::chip::DeviceLayer::Internal::NetworkProvisioningServer; + + // Allow the GenericNetworkProvisioningServerImpl base class to access helper methods + // and types defined on this class. + friend class GenericNetworkProvisioningServerImpl; + +private: + // ===== Members that implement the NetworkProvisioningServer public interface. + + CHIP_ERROR _Init(void); + + // ===== Members for internal use by the following friends. + + friend ::chip::DeviceLayer::Internal::NetworkProvisioningServer & NetworkProvisioningSvr(void); + friend NetworkProvisioningServerImpl & NetworkProvisioningSvrImpl(void); + + static NetworkProvisioningServerImpl sInstance; +}; + +/** + * Returns a reference to the public interface of the NetworkProvisioningServer singleton object. + * + * Internal components should use this to access features of the NetworkProvisioningServer object + * that are common to all platforms. + */ +inline NetworkProvisioningServer & NetworkProvisioningSvr(void) +{ + return NetworkProvisioningServerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the NetworkProvisioningServer singleton object. + * + * Internal components can use this to gain access to features of the NetworkProvisioningServer + * that are specific to the NXP platform. + */ +inline NetworkProvisioningServerImpl & NetworkProvisioningSvrImpl(void) +{ + return NetworkProvisioningServerImpl::sInstance; +} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/OTAImageProcessorImpl.cpp b/src/platform/nxp/common/OTAImageProcessorImpl.cpp new file mode 100644 index 00000000000000..9844e099b1b2e2 --- /dev/null +++ b/src/platform/nxp/common/OTAImageProcessorImpl.cpp @@ -0,0 +1,357 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * 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. + */ + +#include +#include + +#include "OTAImageProcessorImpl.h" + +namespace chip { + +CHIP_ERROR OTAImageProcessorImpl::PrepareDownload() +{ + DeviceLayer::PlatformMgr().ScheduleWork(HandlePrepareDownload, reinterpret_cast(this)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR OTAImageProcessorImpl::Finalize() +{ + DeviceLayer::PlatformMgr().ScheduleWork(HandleFinalize, reinterpret_cast(this)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR OTAImageProcessorImpl::Apply() +{ + DeviceLayer::PlatformMgr().ScheduleWork(HandleApply, reinterpret_cast(this)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR OTAImageProcessorImpl::Abort() +{ + if (mImageFile == nullptr) + { + ChipLogError(SoftwareUpdate, "Invalid output image file supplied"); + return CHIP_ERROR_INTERNAL; + } + DeviceLayer::PlatformMgr().ScheduleWork(HandleAbort, reinterpret_cast(this)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & block) +{ + if ((block.data() == nullptr) || block.empty()) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + + /* Store block data for HandleProcessBlock to access */ + CHIP_ERROR err = SetBlock(block); + if (err != CHIP_NO_ERROR) + { + ChipLogError(SoftwareUpdate, "Cannot set block data: %" CHIP_ERROR_FORMAT, err.Format()); + } + + DeviceLayer::PlatformMgr().ScheduleWork(HandleProcessBlock, reinterpret_cast(this)); + return CHIP_NO_ERROR; +} + +void OTAImageProcessorImpl::TriggerNewRequestForData(intptr_t context) +{ + auto * imageProcessor = reinterpret_cast(context); + imageProcessor->mDownloader->FetchNextData(); +} + +bool OTAImageProcessorImpl::IsFirstImageRun() +{ + OTARequestorInterface * requestor = chip::GetRequestorInstance(); + if (requestor == nullptr) + { + return false; + } + + return requestor->GetCurrentUpdateState() == OTARequestorInterface::OTAUpdateStateEnum::kApplying; +} + +CHIP_ERROR OTAImageProcessorImpl::ConfirmCurrentImage() +{ + OTARequestorInterface * requestor = chip::GetRequestorInstance(); + if (requestor == nullptr) + { + return CHIP_ERROR_INTERNAL; + } + + uint32_t currentVersion; + uint32_t targetVersion = requestor->GetTargetVersion(); + ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSoftwareVersion(currentVersion)); + if (currentVersion != targetVersion) + { + ChipLogError(SoftwareUpdate, "Current software version = %" PRIu32 ", expected software version = %" PRIu32, currentVersion, + targetVersion); + return CHIP_ERROR_INCORRECT_STATE; + } + + return CHIP_NO_ERROR; +} + +void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) +{ + auto * imageProcessor = reinterpret_cast(context); + if (imageProcessor == nullptr) + { + ChipLogError(SoftwareUpdate, "ImageProcessor context is null"); + return; + } + else if (imageProcessor->mDownloader == nullptr) + { + ChipLogError(SoftwareUpdate, "mDownloader is null"); + return; + } + + /* Initialize OTA External Storage Memory */ + if (OTA_SelectExternalStoragePartition() != gOtaSuccess_c) + { + ChipLogError(SoftwareUpdate, "Failed to select valid External Flash partition"); + } + + /* Resume flash write/erase transactions only in the idle task */ + ota_config_t OTAconfig; + OTA_GetDefaultConfig(&OTAconfig); + OTAconfig.PostedOpInIdleTask = true; + OTA_SetConfig(&OTAconfig); + + /* Initialize OTA service for posted operations */ + if (gOtaSuccess_c == OTA_ServiceInit(&imageProcessor->mPostedOperationsStorage[0], NB_PENDING_TRANSACTIONS * TRANSACTION_SZ)) + { + imageProcessor->mHeaderParser.Init(); + imageProcessor->mDownloader->OnPreparedForDownload(CHIP_NO_ERROR); + } +} + +void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) +{ + auto * imageProcessor = reinterpret_cast(context); + if (imageProcessor == nullptr) + { + ChipLogError(SoftwareUpdate, "ImageProcessor context is null"); + return; + } + else if (imageProcessor->mDownloader == nullptr) + { + ChipLogError(SoftwareUpdate, "mDownloader is null"); + return; + } + CHIP_ERROR error = CHIP_NO_ERROR; + + /* Process Header of the received OTA block if mHeaderParser is in Initialized state */ + if (imageProcessor->mHeaderParser.IsInitialized()) + { + ByteSpan block = ByteSpan(imageProcessor->mBlock.data(), imageProcessor->mBlock.size()); + + error = imageProcessor->ProcessHeader(block); + + if (error == CHIP_NO_ERROR) + { + /* Start the OTA Image writing session */ + if (gOtaSuccess_c == OTA_StartImage(imageProcessor->mParams.totalFileBytes)) + { + uint8_t * ptr = static_cast(chip::Platform::MemoryAlloc(block.size())); + if (ptr != nullptr) + { + MutableByteSpan mutableBlock = MutableByteSpan(ptr, block.size()); + error = CopySpanToMutableSpan(block, mutableBlock); + + if (error == CHIP_NO_ERROR) + { + imageProcessor->ReleaseBlock(); + imageProcessor->mBlock = MutableByteSpan(mutableBlock.data(), mutableBlock.size()); + } + } + else + { + error = CHIP_ERROR_NO_MEMORY; + } + } + else + { + error = CHIP_ERROR_INTERNAL; + } + } + } + /* Stop the downloading process if header isn't valid */ + if (error != CHIP_NO_ERROR) + { + ChipLogError(SoftwareUpdate, "Failed to process OTA image header: cancel image update."); + GetRequestorInstance()->CancelImageUpdate(); + return; + } + + if (imageProcessor->mBlock.data() != nullptr) + { + ChipLogProgress(SoftwareUpdate, "OTA Block received, preparing to write in flash..."); + } + + /* + * Prior to writing in flash the block received, we must erase enough space to store it. + * OTA_MakeHeadRoomForNextBlock and OTA_PushImageChunk post erase / write transactions to the queue, + * these operations are later processed in the context of the idle task. + * After the flash erase transaction is processed, the HandleBlockEraseComplete callback + * requests the next OTA block to the provider. + */ + if (gOtaSuccess_c == + OTA_MakeHeadRoomForNextBlock(imageProcessor->mBlock.size(), HandleBlockEraseComplete, (uint32_t) imageProcessor)) + { + /* Send block to be written in external flash */ + if (gOtaSuccess_c == + OTA_PushImageChunk(imageProcessor->mBlock.data(), (uint16_t) imageProcessor->mBlock.size(), NULL, NULL)) + { + imageProcessor->mParams.downloadedBytes += imageProcessor->mBlock.size(); + return; + } + } +} + +CHIP_ERROR OTAImageProcessorImpl::ProcessHeader(ByteSpan & block) +{ + OTAImageHeader header; + CHIP_ERROR error = mHeaderParser.AccumulateAndDecode(block, header); + + /* Needs more data to decode the header */ + ReturnErrorCodeIf(error == CHIP_ERROR_BUFFER_TOO_SMALL, CHIP_NO_ERROR); + ReturnErrorOnFailure(error); + + mParams.totalFileBytes = header.mPayloadSize; + mSoftwareVersion = header.mSoftwareVersion; + mHeaderParser.Clear(); + + return CHIP_NO_ERROR; +} + +void OTAImageProcessorImpl::HandleBlockEraseComplete(uint32_t param) +{ + intptr_t context = (intptr_t) param; + DeviceLayer::PlatformMgr().ScheduleWork(TriggerNewRequestForData, reinterpret_cast(context)); +} + +void OTAImageProcessorImpl::HandleFinalize(intptr_t context) +{ + auto * imageProcessor = reinterpret_cast(context); + if (imageProcessor == nullptr) + { + return; + } + /* Finalize writing the OTA update image in flash */ + OTA_CommitImage(NULL); + + imageProcessor->ReleaseBlock(); + + ChipLogProgress(SoftwareUpdate, "OTA Image download complete"); +} + +void OTAImageProcessorImpl::HandleApply(intptr_t context) +{ + auto * imageProcessor = reinterpret_cast(context); + if (imageProcessor == nullptr) + { + return; + } + + /* + * Set the new image state as ready for test, this would allow the bootloader to perform + * the upgrade at next reboot. + */ + OTA_SetNewImageFlag(); + + ChipLogProgress(SoftwareUpdate, "Update ready for test"); + + /* + * Restart the device in order to apply the update image. + * This should be done with a delay so the device has enough time to send + * the state-transition event when applying the update. + */ + ChipLogProgress(SoftwareUpdate, "Restarting device in 5 seconds ..."); + DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(5 * 1000), HandleRestart, nullptr); + + /* + * At next boot time, the bootloader will test + validate new image. + * If validated, the image is marked "ok" at run time and the update state is switched to permanent. + * If the image is not valid, the bootloader will revert back to the primary application. + */ +} + +void OTAImageProcessorImpl::HandleRestart(System::Layer * aLayer, void * context) +{ + DeviceLayer::PlatformMgrImpl().ScheduleResetInIdle(); +} + +void OTAImageProcessorImpl::HandleAbort(intptr_t context) +{ + auto * imageProcessor = reinterpret_cast(context); + if (imageProcessor == nullptr) + { + return; + } + + OTA_CancelImage(); + + imageProcessor->ReleaseBlock(); +} + +CHIP_ERROR OTAImageProcessorImpl::SetBlock(ByteSpan & block) +{ + if (!IsSpanUsable(block)) + { + ReleaseBlock(); + return CHIP_NO_ERROR; + } + if (mBlock.size() < block.size()) + { + if (!mBlock.empty()) + { + ReleaseBlock(); + } + /* Allocate memory for block data */ + uint8_t * mBlock_ptr = static_cast(chip::Platform::MemoryAlloc(block.size())); + if (mBlock_ptr == nullptr) + { + return CHIP_ERROR_NO_MEMORY; + } + mBlock = MutableByteSpan(mBlock_ptr, block.size()); + } + /* Store the actual block data */ + CHIP_ERROR err = CopySpanToMutableSpan(block, mBlock); + if (err != CHIP_NO_ERROR) + { + ChipLogError(SoftwareUpdate, "Cannot copy block data: %" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + return CHIP_NO_ERROR; +} + +CHIP_ERROR OTAImageProcessorImpl::ReleaseBlock() +{ + if (mBlock.data() != nullptr) + { + chip::Platform::MemoryFree(mBlock.data()); + } + + mBlock = MutableByteSpan(); + return CHIP_NO_ERROR; +} + +} // namespace chip diff --git a/src/platform/nxp/common/OTAImageProcessorImpl.h b/src/platform/nxp/common/OTAImageProcessorImpl.h new file mode 100644 index 00000000000000..5531378ca7fa16 --- /dev/null +++ b/src/platform/nxp/common/OTAImageProcessorImpl.h @@ -0,0 +1,84 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * 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. + */ + +#pragma once + +#include +#include +#include +#include + +#include "OtaSupport.h" + +/* Posted Operations Size Info */ +#define NB_PENDING_TRANSACTIONS 11 +#define TRANSACTION_SZ gOtaTransactionSz_d + +namespace chip { + +class OTAImageProcessorImpl : public OTAImageProcessorInterface +{ +public: + //////////// OTAImageProcessorInterface Implementation /////////////// + CHIP_ERROR PrepareDownload() override; + CHIP_ERROR Finalize() override; + CHIP_ERROR Apply() override; + CHIP_ERROR Abort() override; + CHIP_ERROR ProcessBlock(ByteSpan & block) override; + bool IsFirstImageRun() override; + CHIP_ERROR ConfirmCurrentImage() override; + + static void TriggerNewRequestForData(intptr_t context); + + void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; } + void SetOTAImageFile(const char * imageFile) { mImageFile = imageFile; } + +private: + //////////// Actual handlers for the OTAImageProcessorInterface /////////////// + static void HandlePrepareDownload(intptr_t context); + static void HandleFinalize(intptr_t context); + static void HandleAbort(intptr_t context); + static void HandleProcessBlock(intptr_t context); + static void HandleApply(intptr_t context); + static void HandleRestart(System::Layer * aLayer, void * context); + static void HandleBlockEraseComplete(uint32_t param); + + CHIP_ERROR ProcessHeader(ByteSpan & block); + + /** + * Called to allocate memory for mBlock if necessary and set it to block + */ + CHIP_ERROR SetBlock(ByteSpan & block); + + /** + * Called to release allocated memory for mBlock + */ + CHIP_ERROR ReleaseBlock(); + + MutableByteSpan mBlock; + OTADownloader * mDownloader; + OTAImageHeaderParser mHeaderParser; + uint32_t mSoftwareVersion; + const char * mImageFile = nullptr; + + /* Buffer used for transaction storage */ + uint8_t mPostedOperationsStorage[NB_PENDING_TRANSACTIONS * TRANSACTION_SZ]; +}; + +} // namespace chip diff --git a/src/platform/nxp/common/PlatformManagerImpl.h b/src/platform/nxp/common/PlatformManagerImpl.h new file mode 100644 index 00000000000000..86086682342ce9 --- /dev/null +++ b/src/platform/nxp/common/PlatformManagerImpl.h @@ -0,0 +1,108 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Nest Labs, Inc. + * 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 + * Provides an implementation of the PlatformManager object + * for NXP platforms using the NXP SDK. + */ + +#pragma once + +#include + +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the PlatformManager singleton object for the NXP platform. + */ +class PlatformManagerImpl final : public PlatformManager, public Internal::GenericPlatformManagerImpl_FreeRTOS +{ + // Allow the PlatformManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend PlatformManager; + + // Allow the generic implementation base class to call helper methods on + // this class. +#ifndef DOXYGEN_SHOULD_SKIP_THIS + friend Internal::GenericPlatformManagerImpl_FreeRTOS; +#endif + +public: + // ===== Platform-specific members that may be accessed directly by the application. + + void Reset(); + void ScheduleResetInIdle(void); + bool GetResetInIdleValue(void); + void HardwareInit(void); + static void IdleHook(void); + static void SaveSettings(void); + void StopBLEConnectivity(void); + CHIP_ERROR ServiceInit(void); + + System::Clock::Timestamp GetStartTime() { return mStartTime; } + +private: + // ===== Methods that implement the PlatformManager abstract interface. + + CHIP_ERROR _InitChipStack(void); + void _Shutdown(); + + CHIP_ERROR WiFiInterfaceInit(void); + CHIP_ERROR EthernetInterfaceInit(); + + // ===== Members for internal use by the following friends. + + friend PlatformManager & PlatformMgr(void); + friend PlatformManagerImpl & PlatformMgrImpl(void); + friend class Internal::BLEManagerImpl; + + System::Clock::Timestamp mStartTime = System::Clock::kZero; + + bool resetInIdle = false; + static PlatformManagerImpl sInstance; + + using Internal::GenericPlatformManagerImpl_FreeRTOS::PostEventFromISR; +}; + +/** + * Returns the public interface of the PlatformManager singleton object. + * + * chip applications should use this to access features of the PlatformManager object + * that are common to all platforms. + */ +inline PlatformManager & PlatformMgr(void) +{ + return PlatformManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the PlatformManager singleton object. + * + * chip applications can use this to gain access to features of the PlatformManager + * that are specific to the NXP platform. + */ +inline PlatformManagerImpl & PlatformMgrImpl(void) +{ + return PlatformManagerImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/SoftwareUpdateManagerImpl.cpp b/src/platform/nxp/common/SoftwareUpdateManagerImpl.cpp new file mode 100644 index 00000000000000..c464bb327c24a6 --- /dev/null +++ b/src/platform/nxp/common/SoftwareUpdateManagerImpl.cpp @@ -0,0 +1,46 @@ +/* + * + * 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. + */ +/* this file behaves like a config.h, comes first */ +#include + +#if CHIP_DEVICE_CONFIG_ENABLE_SOFTWARE_UPDATE_MANAGER + +#include +#include + +#include +#include + +namespace chip { +namespace DeviceLayer { + +SoftwareUpdateManagerImpl SoftwareUpdateManagerImpl::sInstance; + +CHIP_ERROR SoftwareUpdateManagerImpl::_Init(void) +{ + Internal::GenericSoftwareUpdateManagerImpl_BDX::DoInit(); + Internal::GenericSoftwareUpdateManagerImpl::DoInit(); + + return CHIP_NO_ERROR; +} + +} // namespace DeviceLayer +} // namespace chip + +#endif // CHIP_DEVICE_CONFIG_ENABLE_SOFTWARE_UPDATE_MANAGER diff --git a/src/platform/nxp/common/SoftwareUpdateManagerImpl.h b/src/platform/nxp/common/SoftwareUpdateManagerImpl.h new file mode 100644 index 00000000000000..5de3f03ab97b21 --- /dev/null +++ b/src/platform/nxp/common/SoftwareUpdateManagerImpl.h @@ -0,0 +1,89 @@ +/* + * + * 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. + */ + +#pragma once + +#if CHIP_DEVICE_CONFIG_ENABLE_SOFTWARE_UPDATE_MANAGER + +#include +#include + +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the SoftwareUpdateManager singleton object for the + * NXP platforms. + */ +class SoftwareUpdateManagerImpl final : public SoftwareUpdateManager, + public Internal::GenericSoftwareUpdateManagerImpl, + public Internal::GenericSoftwareUpdateManagerImpl_BDX +{ + // Allow the SoftwareUpdateManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class SoftwareUpdateManager; + + // Allow the GenericSoftwareUpdateManagerImpl base class to access helper methods + // and types defined on this class. + friend class Internal::GenericSoftwareUpdateManagerImpl; + + // Allow the GenericSoftwareUpdateManagerImpl_BDX base class to access helper methods + // and types defined on this class. + friend class Internal::GenericSoftwareUpdateManagerImpl_BDX; + +public: + // ===== Members for internal use by the following friends. + + friend ::chip::DeviceLayer::SoftwareUpdateManager & SoftwareUpdateMgr(void); + friend SoftwareUpdateManagerImpl & SoftwareUpdateMgrImpl(void); + + static SoftwareUpdateManagerImpl sInstance; + +private: + // ===== Members that implement the SoftwareUpdateManager abstract interface. + + CHIP_ERROR _Init(void); +}; + +/** + * Returns a reference to the public interface of the SoftwareUpdateManager singleton object. + * + * Internal components should use this to access features of the SoftwareUpdateManager object + * that are common to all platforms. + */ +inline SoftwareUpdateManager & SoftwareUpdateMgr(void) +{ + return SoftwareUpdateManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the SoftwareUpdateManager singleton object. + * + * Internal components can use this to gain access to features of the SoftwareUpdateManager + * that are specific to the NXP platform. + */ +inline SoftwareUpdateManagerImpl & SoftwareUpdateMgrImpl(void) +{ + return SoftwareUpdateManagerImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip + +#endif // CHIP_DEVICE_CONFIG_ENABLE_SOFTWARE_UPDATE_MANAGER diff --git a/src/platform/nxp/common/SystemNXPPlatformDefaultConfig.h b/src/platform/nxp/common/SystemNXPPlatformDefaultConfig.h new file mode 100644 index 00000000000000..cba7b8e4742e44 --- /dev/null +++ b/src/platform/nxp/common/SystemNXPPlatformDefaultConfig.h @@ -0,0 +1,87 @@ +/* + * + * Copyright (c) 2020-2022 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 + * Platform-specific configuration overrides for the CHIP System + * Layer on NXP Platforms. + * + */ + +#pragma once + +#include + +namespace chip { +namespace DeviceLayer { +struct ChipDeviceEvent; +} // namespace DeviceLayer +} // namespace chip + +// ==================== Platform Adaptations ==================== + +#ifndef CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_EVENT_FUNCTIONS +#define CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_EVENT_FUNCTIONS 1 +#endif // CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_EVENT_FUNCTIONS + +#ifndef CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_TIME +#define CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_TIME 1 +#endif // CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_TIME + +#ifndef CHIP_SYSTEM_CONFIG_LWIP_EVENT_TYPE +#define CHIP_SYSTEM_CONFIG_LWIP_EVENT_TYPE int +#endif // CHIP_SYSTEM_CONFIG_LWIP_EVENT_TYPE + +#ifndef CHIP_SYSTEM_CONFIG_LWIP_EVENT_OBJECT_TYPE +#define CHIP_SYSTEM_CONFIG_LWIP_EVENT_OBJECT_TYPE const struct ::chip::DeviceLayer::ChipDeviceEvent * +#endif // CHIP_SYSTEM_CONFIG_LWIP_EVENT_OBJECT_TYPE + +#ifndef CHIP_SYSTEM_CONFIG_ERROR_TYPE +#define CHIP_SYSTEM_CONFIG_ERROR_TYPE int32_t +#endif // CHIP_SYSTEM_CONFIG_ERROR_TYPE + +#ifndef CHIP_SYSTEM_CONFIG_NO_ERROR +#define CHIP_SYSTEM_CONFIG_NO_ERROR 0 +#endif // CHIP_SYSTEM_CONFIG_NO_ERROR + +#ifndef CHIP_SYSTEM_CONFIG_ERROR_MIN +#define CHIP_SYSTEM_CONFIG_ERROR_MIN 7000000 +#endif // CHIP_SYSTEM_CONFIG_ERROR_MIN + +#ifndef CHIP_SYSTEM_CONFIG_ERROR_MAX +#define CHIP_SYSTEM_CONFIG_ERROR_MAX 7000999 +#endif // CHIP_SYSTEM_CONFIG_ERROR_MAX + +#ifndef _CHIP_SYSTEM_CONFIG_ERROR +#define _CHIP_SYSTEM_CONFIG_ERROR(e) (CHIP_SYSTEM_CONFIG_ERROR_MIN + (e)) +#endif // _CHIP_SYSTEM_CONFIG_ERROR + +#ifndef CHIP_SYSTEM_LWIP_ERROR_MIN +#define CHIP_SYSTEM_LWIP_ERROR_MIN 3000000 +#endif // CHIP_SYSTEM_LWIP_ERROR_MIN + +#ifndef CHIP_SYSTEM_LWIP_ERROR_MAX +#define CHIP_SYSTEM_LWIP_ERROR_MAX 3000128 +#endif // CHIP_SYSTEM_LWIP_ERROR_MAX + +// ========== Platform-specific Configuration Overrides ========= + +#ifndef CHIP_SYSTEM_CONFIG_NUM_TIMERS +#define CHIP_SYSTEM_CONFIG_NUM_TIMERS 32 +#endif // CHIP_SYSTEM_CONFIG_NUM_TIMERS diff --git a/src/platform/nxp/common/ThreadStackManagerImpl.cpp b/src/platform/nxp/common/ThreadStackManagerImpl.cpp new file mode 100644 index 00000000000000..c7f8ce7a5f0538 --- /dev/null +++ b/src/platform/nxp/common/ThreadStackManagerImpl.cpp @@ -0,0 +1,122 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Nest Labs, Inc. + * 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 + * Provides an implementation of the ThreadStackManager object for + * NXP platforms using the NXP SDK and the OpenThread + * stack. + * + */ + +/* this file behaves like a config.h, comes first */ +#include + +#include +#include + +#include +#include + +#include + +#include "openthread-system.h" +#include "ot_platform_common.h" + +extern "C" CHIP_ERROR AppMatterCli_RegisterCommands(void); + +/* + * Empty content for otPlatCliUartProcess, as the openthread CLI + * is managed by the matter cli if enabled. + * An empty content is required as system.c from ot_nxp is always + * calling this function. This could be removed once system.c will + * be reworked to support more dynamically the openthread cli. + */ +extern "C" void otPlatCliUartProcess(void) {} + +namespace chip { +namespace DeviceLayer { + +using namespace ::chip::DeviceLayer::Internal; + +ThreadStackManagerImpl ThreadStackManagerImpl::sInstance; + +CHIP_ERROR ThreadStackManagerImpl::_InitThreadStack(void) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + /* Initialize the OpenThread Alarm module to make sure that if calling otInstance, + * it can schedule events + */ + otPlatAlarmInit(); + + /* Make sure to initialize the Matter CLI which will include the ot-cli first. + * In fact it is mandatory to enable first the ot-cli before initializing the Matter openthread layer + * which would modify some contexts of the openthread instance. + */ + AppMatterCli_RegisterCommands(); + + // Initialize the generic implementation base classes. + err = GenericThreadStackManagerImpl_FreeRTOS::DoInit(); + SuccessOrExit(err); + err = GenericThreadStackManagerImpl_OpenThread_LwIP::DoInit(NULL); + SuccessOrExit(err); + +exit: + return err; +} + +bool ThreadStackManagerImpl::IsInitialized() +{ + return sInstance.mThreadStackLock != NULL; +} + +} // namespace DeviceLayer +} // namespace chip + +using namespace ::chip::DeviceLayer; + +/** + * Glue function called directly by the OpenThread stack when tasklet processing work + * is pending. + */ +extern "C" void otTaskletsSignalPending(otInstance * p_instance) +{ + ThreadStackMgrImpl().SignalThreadActivityPending(); +} + +/** + * Glue function called directly by the OpenThread stack when system event processing work + * is pending. + */ +extern "C" void otSysEventSignalPending(void) +{ + BaseType_t yieldRequired = ThreadStackMgrImpl().SignalThreadActivityPendingFromISR(); + portYIELD_FROM_ISR(yieldRequired); +} + +extern "C" void * otPlatCAlloc(size_t aNum, size_t aSize) +{ + return CHIPPlatformMemoryCalloc(aNum, aSize); +} + +extern "C" void otPlatFree(void * aPtr) +{ + return CHIPPlatformMemoryFree(aPtr); +} diff --git a/src/platform/nxp/common/ThreadStackManagerImpl.h b/src/platform/nxp/common/ThreadStackManagerImpl.h new file mode 100644 index 00000000000000..6f9fae80950670 --- /dev/null +++ b/src/platform/nxp/common/ThreadStackManagerImpl.h @@ -0,0 +1,111 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020 Nest Labs, Inc. + * 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 + * Provides an implementation of the ThreadStackManager object + * for NXP platforms using the NXP SDK and the OpenThread stack. + */ + +#pragma once + +#include +#include +#include +#include + +extern "C" void otSysEventSignalPending(void); + +namespace chip { +namespace DeviceLayer { + +class ThreadStackManager; +class ThreadStackManagerImpl; + +/** + * Concrete implementation of the ThreadStackManager singleton object for NXP platforms + * using the NXP SDK and the OpenThread stack. + */ +class ThreadStackManagerImpl final : public ThreadStackManager, + public Internal::GenericThreadStackManagerImpl_OpenThread_LwIP, + public Internal::GenericThreadStackManagerImpl_FreeRTOS +{ + // Allow the ThreadStackManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class ThreadStackManager; + + // Allow the generic implementation base classes to call helper methods on + // this class. +#ifndef DOXYGEN_SHOULD_SKIP_THIS + friend Internal::GenericThreadStackManagerImpl_OpenThread; + friend Internal::GenericThreadStackManagerImpl_OpenThread_LwIP; + friend Internal::GenericThreadStackManagerImpl_FreeRTOS; +#endif + + // Allow glue functions called by OpenThread to call helper methods on this + // class. + friend void ::otTaskletsSignalPending(otInstance * otInst); + friend void ::otSysEventSignalPending(void); + +public: + // ===== Platform-specific members that may be accessed directly by the application. + +protected: + // ===== Methods that implement the ThreadStackManager abstract interface. + CHIP_ERROR _InitThreadStack(void); + +private: + // ===== Members for internal use by the following friends. + + friend ThreadStackManager & ::chip::DeviceLayer::ThreadStackMgr(void); + friend ThreadStackManagerImpl & ::chip::DeviceLayer::ThreadStackMgrImpl(void); + + static ThreadStackManagerImpl sInstance; + + static bool IsInitialized(); + + // ===== Private members for use by this class only. + + ThreadStackManagerImpl() = default; +}; + +/** + * Returns the public interface of the ThreadStackManager singleton object. + * + * chip applications should use this to access features of the ThreadStackManager object + * that are common to all platforms. + */ +inline ThreadStackManager & ThreadStackMgr(void) +{ + return ThreadStackManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the ThreadStackManager singleton object. + * + * chip applications can use this to gain access to features of the ThreadStackManager + * that are specific to NXP platforms. + */ +inline ThreadStackManagerImpl & ThreadStackMgrImpl(void) +{ + return ThreadStackManagerImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.h b/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.h new file mode 100644 index 00000000000000..411392aa3c6a8c --- /dev/null +++ b/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.h @@ -0,0 +1,31 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2020 Nest Labs, Inc. + * 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 + * Provides an implementation of the BLEManager singleton object + * for the nxp platforms. + */ + +#pragma once + +#include +#include +#include +#include diff --git a/src/platform/nxp/common/ble_zephyr/BleNXPPlatformDefaultConfig.h b/src/platform/nxp/common/ble_zephyr/BleNXPPlatformDefaultConfig.h new file mode 100644 index 00000000000000..339ee66c4ad05c --- /dev/null +++ b/src/platform/nxp/common/ble_zephyr/BleNXPPlatformDefaultConfig.h @@ -0,0 +1,53 @@ +/* + * + * Copyright (c) 2021-2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Platform-specific configuration overrides for the CHIP BLE + * Layer on NXP platforms using the NXP SDK. + * + */ + +#pragma once + +// ==================== Platform Adaptations ==================== + +struct bt_conn; + +#ifndef BLE_CONNECTION_OBJECT +#define BLE_CONNECTION_OBJECT bt_conn * +#endif // BLE_CONNECTION_OBJECT + +#ifndef BLE_CONNECTION_UNINITIALIZED +#define BLE_CONNECTION_UNINITIALIZED nullptr +#endif // BLE_CONNECTION_UNINITIALIZED + +#ifndef BLE_MAX_RECEIVE_WINDOW_SIZE +#define BLE_MAX_RECEIVE_WINDOW_SIZE 5 +#endif // BLE_MAX_RECEIVE_WINDOW_SIZE + +// ========== Platform-specific Configuration Overrides ========= + +#ifndef LOG_MODULE_DECLARE +#define LOG_MODULE_DECLARE(...) +#endif // LOG_MODULE_DECLARE + +#ifndef LOG_HEXDUMP_DBG +#define LOG_HEXDUMP_DBG(...) +#endif // LOG_HEXDUMP_DBG + +/* none so far */ diff --git a/src/platform/nxp/common/factory_data/FactoryDataProvider.cpp b/src/platform/nxp/common/factory_data/FactoryDataProvider.cpp new file mode 100644 index 00000000000000..5991a81d703ac8 --- /dev/null +++ b/src/platform/nxp/common/factory_data/FactoryDataProvider.cpp @@ -0,0 +1,357 @@ +/* + * + * Copyright (c) 2023 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. + */ + +#include +#include +#include +#include + +#ifndef FACTORY_DATA_PROVIDER_ENABLE_TESTS +#define FACTORY_DATA_PROVIDER_RUN_TESTS 0 +#endif + +#if FACTORY_DATA_PROVIDER_RUN_TESTS +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "FactoryDataProvider.h" + +#include + +#ifndef FACTORY_DATA_PROVIDER_LOG +#define FACTORY_DATA_PROVIDER_LOG 0 +#endif + +#if FACTORY_DATA_PROVIDER_LOG +#include "fsl_debug_console.h" +#define FACTORY_DATA_PROVIDER_PRINTF(...) \ + PRINTF("[%s] ", __FUNCTION__); \ + PRINTF(__VA_ARGS__); \ + PRINTF("\n\r"); +#else +#define FACTORY_DATA_PROVIDER_PRINTF(...) +#endif + +using namespace ::chip::Credentials; +using namespace ::chip::Crypto; + +namespace chip { +namespace DeviceLayer { + +CHIP_ERROR FactoryDataProvider::SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length, + uint32_t * contentAddr) +{ + return static_cast(this)->SearchForId(searchedType, pBuf, bufLength, length, contentAddr); +} + +CHIP_ERROR FactoryDataProvider::Init(void) +{ + return static_cast(this)->Init(); +} + +CHIP_ERROR FactoryDataProvider::GetCertificationDeclaration(MutableByteSpan & outBuffer) +{ + uint16_t declarationSize = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kCertDeclarationId, outBuffer.data(), outBuffer.size(), declarationSize)); + outBuffer.reduce_size(declarationSize); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer) +{ + out_firmware_info_buffer.reduce_size(0); + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetDeviceAttestationCert(MutableByteSpan & outBuffer) +{ + uint16_t certificateSize = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kDacCertificateId, outBuffer.data(), outBuffer.size(), certificateSize)); + outBuffer.reduce_size(certificateSize); + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer) +{ + uint16_t certificateSize = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kPaiCertificateId, outBuffer.data(), outBuffer.size(), certificateSize)); + outBuffer.reduce_size(certificateSize); + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::SignWithDeviceAttestationKey(const ByteSpan & digestToSign, MutableByteSpan & outSignBuffer) +{ + return static_cast(this)->SignWithDacKey(digestToSign, outSignBuffer); +} + +CHIP_ERROR FactoryDataProvider::GetSetupDiscriminator(uint16_t & setupDiscriminator) +{ + uint16_t discriminatorLen = 0; + + ReturnErrorOnFailure(SearchForId(FactoryDataId::kDiscriminatorId, (uint8_t *) &setupDiscriminator, sizeof(setupDiscriminator), + discriminatorLen)); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::SetSetupDiscriminator(uint16_t setupDiscriminator) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +CHIP_ERROR FactoryDataProvider::GetSpake2pIterationCount(uint32_t & iterationCount) +{ + uint16_t temp = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kIcId, (uint8_t *) &iterationCount, sizeof(iterationCount), temp)); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetSpake2pSalt(MutableByteSpan & saltBuf) +{ + static constexpr size_t kSpake2pSalt_MaxBase64Len = BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length) + 1; + uint8_t saltB64[kSpake2pSalt_MaxBase64Len]; + uint16_t saltB64Len = 0; + + ReturnErrorOnFailure(SearchForId(FactoryDataId::kSaltId, &saltB64[0], sizeof(saltB64), saltB64Len)); + + size_t saltLen = chip::Base64Decode32((char *) saltB64, saltB64Len, reinterpret_cast(saltB64)); + + ReturnErrorCodeIf(saltLen > saltBuf.size(), CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(saltBuf.data(), saltB64, saltLen); + saltBuf.reduce_size(saltLen); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen) +{ + static constexpr size_t kSpake2pSerializedVerifier_MaxBase64Len = + BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_VerifierSerialized_Length) + 1; + uint8_t verifierB64[kSpake2pSerializedVerifier_MaxBase64Len]; + uint16_t verifierB64Len = 0; + + ReturnErrorOnFailure(SearchForId(FactoryDataId::kVerifierId, &verifierB64[0], sizeof(verifierB64), verifierB64Len)); + + verifierLen = chip::Base64Decode32((char *) verifierB64, verifierB64Len, reinterpret_cast(verifierB64)); + ReturnErrorCodeIf(verifierLen > verifierBuf.size(), CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(verifierBuf.data(), verifierB64, verifierLen); + verifierBuf.reduce_size(verifierLen); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetSetupPasscode(uint32_t & setupPasscode) +{ + uint16_t length = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kSetupPasscodeId, (uint8_t *) &setupPasscode, sizeof(setupPasscode), length)); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::SetSetupPasscode(uint32_t setupPasscode) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +CHIP_ERROR FactoryDataProvider::GetVendorName(char * buf, size_t bufSize) +{ + uint16_t length = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kVendorNameId, (uint8_t *) buf, bufSize, length)); + buf[length] = '\0'; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetVendorId(uint16_t & vendorId) +{ + uint16_t length = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kVidId, (uint8_t *) &vendorId, sizeof(vendorId), length)); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetProductName(char * buf, size_t bufSize) +{ + uint16_t length = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kProductNameId, (uint8_t *) buf, bufSize, length)); + buf[length] = '\0'; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetProductId(uint16_t & productId) +{ + uint16_t length = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kPidId, (uint8_t *) &productId, sizeof(productId), length)); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetPartNumber(char * buf, size_t bufSize) +{ + uint16_t length = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kPartNumber, (uint8_t *) buf, bufSize, length)); + buf[length] = '\0'; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetProductURL(char * buf, size_t bufSize) +{ + uint16_t length = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kProductURL, (uint8_t *) buf, bufSize, length)); + buf[length] = '\0'; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetProductLabel(char * buf, size_t bufSize) +{ + uint16_t length = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kProductLabel, (uint8_t *) buf, bufSize, length)); + buf[length] = '\0'; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetSerialNumber(char * buf, size_t bufSize) +{ + uint16_t length = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kSerialNumberId, (uint8_t *) buf, bufSize, length)); + buf[length] = '\0'; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) +{ + uint16_t length = 0; + uint8_t date[ConfigurationManager::kMaxManufacturingDateLength]; + + ReturnErrorOnFailure( + SearchForId(FactoryDataId::kManufacturingDateId, date, ConfigurationManager::kMaxManufacturingDateLength, length)); + date[length] = '\0'; + + if (length == 10 && isdigit(date[0]) && isdigit(date[1]) && isdigit(date[2]) && isdigit(date[3]) && date[4] == '-' && + isdigit(date[5]) && isdigit(date[6]) && date[7] == '-' && isdigit(date[8]) && isdigit(date[9])) + { + year = 1000 * (date[0] - '0') + 100 * (date[1] - '0') + 10 * (date[2] - '0') + date[3] - '0'; + month = 10 * (date[5] - '0') + date[6] - '0'; + day = 10 * (date[8] - '0') + date[9] - '0'; + } + else + { + ChipLogError(DeviceLayer, "Manufacturing date is not formatted correctly: YYYY-MM-DD."); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetHardwareVersion(uint16_t & hardwareVersion) +{ + uint16_t length = 0; + ReturnErrorOnFailure( + SearchForId(FactoryDataId::kHardwareVersionId, (uint8_t *) &hardwareVersion, sizeof(hardwareVersion), length)); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetHardwareVersionString(char * buf, size_t bufSize) +{ + uint16_t length = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kHardwareVersionStrId, (uint8_t *) buf, bufSize, length)); + buf[length] = '\0'; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) +{ + CHIP_ERROR err = CHIP_ERROR_NOT_IMPLEMENTED; +#if CHIP_ENABLE_ROTATING_DEVICE_ID + static_assert(ConfigurationManager::kRotatingDeviceIDUniqueIDLength >= ConfigurationManager::kMinRotatingDeviceIDUniqueIDLength, + "Length of unique ID for rotating device ID is smaller than minimum."); + uint16_t uniqueIdLen = 0; + err = SearchForId(FactoryDataId::kUniqueId, (uint8_t *) uniqueIdSpan.data(), uniqueIdSpan.size(), uniqueIdLen); +#if defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID) + if (err != CHIP_NO_ERROR) + { + constexpr uint8_t uniqueId[] = CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID; + + ReturnErrorCodeIf(sizeof(uniqueId) > uniqueIdSpan.size(), CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(uniqueIdSpan.data(), uniqueId, sizeof(uniqueId)); + uniqueIdLen = sizeof(uniqueId); + err = CHIP_NO_ERROR; + } +#endif // CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID + ReturnErrorOnFailure(err); + uniqueIdSpan.reduce_size(uniqueIdLen); +#endif + + return err; +} + +void FactoryDataProvider::FactoryDataProviderRunTests(void) +{ +#if FACTORY_DATA_PROVIDER_RUN_TESTS + static const ByteSpan kExpectedDacPublicKey = DevelopmentCerts::kDacPublicKey; + constexpr uint8_t kExampleDigest[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, 0x17, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, + 0x26, 0x27, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 }; + + // Sign using the example attestation private key + P256ECDSASignature da_signature; + MutableByteSpan out_sig_span(da_signature.Bytes(), da_signature.Capacity()); + CHIP_ERROR err = SignWithDeviceAttestationKey(ByteSpan{ kExampleDigest }, out_sig_span); + assert(err == CHIP_NO_ERROR); + + assert(out_sig_span.size() == kP256_ECDSA_Signature_Length_Raw); + da_signature.SetLength(out_sig_span.size()); + + // Get DAC from the provider + uint8_t dac_cert_buf[kMaxDERCertLength]; + MutableByteSpan dac_cert_span(dac_cert_buf); + + memset(dac_cert_span.data(), 0, dac_cert_span.size()); + err = GetDeviceAttestationCert(dac_cert_span); + assert(err == CHIP_NO_ERROR); + + // Extract public key from DAC, prior to signature verification + P256PublicKey dac_public_key; + err = ExtractPubkeyFromX509Cert(dac_cert_span, dac_public_key); + assert(err == CHIP_NO_ERROR); + assert(dac_public_key.Length() == kExpectedDacPublicKey.size()); + assert(0 == memcmp(dac_public_key.ConstBytes(), kExpectedDacPublicKey.data(), kExpectedDacPublicKey.size())); + + // Verify round trip signature + err = dac_public_key.ECDSA_validate_msg_signature(&kExampleDigest[0], sizeof(kExampleDigest), da_signature); + assert(err == CHIP_NO_ERROR); +#endif +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/factory_data/FactoryDataProvider.h b/src/platform/nxp/common/factory_data/FactoryDataProvider.h new file mode 100644 index 00000000000000..47f85fa6ccc4b2 --- /dev/null +++ b/src/platform/nxp/common/factory_data/FactoryDataProvider.h @@ -0,0 +1,125 @@ +/* + * + * Copyright (c) 2023 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. + */ +#pragma once + +#include +#include +#include +#include +#include + +namespace chip { +namespace DeviceLayer { + +class FactoryDataProviderImpl; + +/** + * @brief This class provides Commissionable data and Device Attestation Credentials. + */ + +class FactoryDataProvider : public chip::Credentials::DeviceAttestationCredentialsProvider, + public CommissionableDataProvider, + public DeviceInstanceInfoProvider +{ + using ImplClass = ::chip::DeviceLayer::FactoryDataProviderImpl; + +public: + enum EncryptionMode + { + encrypt_none = 0U, + encrypt_ecb = 1U, + encrypt_cbc = 2U + }; + + // Default factory data IDs + enum FactoryDataId + { + kVerifierId = 1, + kSaltId, + kIcId, + kDacPrivateKeyId, + kDacCertificateId, + kPaiCertificateId, + kDiscriminatorId, + kSetupPasscodeId, + kVidId, + kPidId, + kCertDeclarationId, + kVendorNameId, + kProductNameId, + kSerialNumberId, + kManufacturingDateId, + kHardwareVersionId, + kHardwareVersionStrId, + kUniqueId, + kPartNumber, + kProductURL, + kProductLabel, + kMaxId + }; + + CHIP_ERROR Init(void); + + // ===== Members functions that implement the DeviceAttestationCredentialsProvider + CHIP_ERROR GetCertificationDeclaration(MutableByteSpan & outBuffer) override; + CHIP_ERROR GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer) override; + CHIP_ERROR GetDeviceAttestationCert(MutableByteSpan & outBuffer) override; + CHIP_ERROR GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer) override; + CHIP_ERROR SignWithDeviceAttestationKey(const ByteSpan & digestToSign, MutableByteSpan & outSignBuffer) override; + + // ===== Members functions that implement the CommissionableDataProvider + CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override; + CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override; + CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override; + CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) override; + CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen) override; + CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override; + CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override; + + // ===== Members functions that implement the DeviceInstanceInfoProvider + CHIP_ERROR GetVendorName(char * buf, size_t bufSize) override; + CHIP_ERROR GetVendorId(uint16_t & vendorId) override; + CHIP_ERROR GetPartNumber(char * buf, size_t bufSize) override; + CHIP_ERROR GetProductURL(char * buf, size_t bufSize) override; + CHIP_ERROR GetProductLabel(char * buf, size_t bufSize) override; + + CHIP_ERROR GetProductName(char * buf, size_t bufSize) override; + CHIP_ERROR GetProductId(uint16_t & productId) override; + CHIP_ERROR GetSerialNumber(char * buf, size_t bufSize) override; + CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override; + CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override; + CHIP_ERROR GetHardwareVersionString(char * buf, size_t bufSize) override; + CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override; + + void FactoryDataProviderRunTests(void); + +protected: + // Methods to be implemented by impl class delegate. + CHIP_ERROR SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length, + uint32_t * contentAddr = NULL); + CHIP_ERROR SignWithDacKey(const ByteSpan & digestToSign, MutableByteSpan & outSignBuffer); +}; + +extern FactoryDataProvider & FactoryDataPrvd(); + +extern FactoryDataProviderImpl & FactoryDataPrvdImpl(); + +} // namespace DeviceLayer +} // namespace chip + +#include EXTERNAL_FACTORY_DATA_PROVIDER_IMPL_HEADER diff --git a/src/platform/nxp/common/factory_data/FactoryDataProviderFwkImpl.cpp b/src/platform/nxp/common/factory_data/FactoryDataProviderFwkImpl.cpp new file mode 100644 index 00000000000000..7da95e29b4e027 --- /dev/null +++ b/src/platform/nxp/common/factory_data/FactoryDataProviderFwkImpl.cpp @@ -0,0 +1,136 @@ +/* + * + * Copyright (c) 2023 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. + */ + +#include "FactoryDataProviderFwkImpl.h" +#include "fwk_factory_data_provider.h" + +namespace chip { +namespace DeviceLayer { + +FactoryDataProviderImpl FactoryDataProviderImpl::sInstance; + +CHIP_ERROR FactoryDataProviderImpl::SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length, + uint32_t * contentAddr) +{ + CHIP_ERROR err = CHIP_ERROR_NOT_FOUND; + uint32_t readLen = 0; + + uint8_t * ramBufferAddr = FDP_SearchForId(searchedType, pBuf, bufLength, &readLen); + + if (ramBufferAddr != NULL) + { + if (contentAddr != NULL) + *contentAddr = (uint32_t) ramBufferAddr; + err = CHIP_NO_ERROR; + } + length = readLen; + + return err; +} + +CHIP_ERROR FactoryDataProviderImpl::SignWithDacKey(const ByteSpan & digestToSign, MutableByteSpan & outSignBuffer) +{ + Crypto::P256ECDSASignature signature; + Crypto::P256Keypair keypair; + + VerifyOrReturnError(IsSpanUsable(outSignBuffer), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(IsSpanUsable(digestToSign), 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 + // Crypto::P256Keypair is only (currently) constructable from raw keys if both private/public keys are present. + Crypto::P256PublicKey dacPublicKey; + uint16_t certificateSize = 0; + uint32_t certificateAddr; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kDacCertificateId, NULL, 0, certificateSize, &certificateAddr)); + MutableByteSpan dacCertSpan((uint8_t *) certificateAddr, certificateSize); + + /* Extract Public Key of DAC certificate from itself */ + ReturnErrorOnFailure(Crypto::ExtractPubkeyFromX509Cert(dacCertSpan, dacPublicKey)); + + /* Get private key of DAC certificate from reserved section */ + uint16_t keySize = 0; + uint32_t keyAddr; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kDacPrivateKeyId, NULL, 0, keySize, &keyAddr)); + MutableByteSpan dacPrivateKeySpan((uint8_t *) keyAddr, keySize); + + ReturnErrorOnFailure(LoadKeypairFromRaw(ByteSpan(dacPrivateKeySpan.data(), dacPrivateKeySpan.size()), + ByteSpan(dacPublicKey.Bytes(), dacPublicKey.Length()), keypair)); + + ReturnErrorOnFailure(keypair.ECDSA_sign_msg(digestToSign.data(), digestToSign.size(), signature)); + + return CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer); +} + +CHIP_ERROR FactoryDataProviderImpl::LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P256Keypair & keypair) +{ + Crypto::P256SerializedKeypair serialized_keypair; + ReturnErrorOnFailure(serialized_keypair.SetLength(privateKey.size() + publicKey.size())); + memcpy(serialized_keypair.Bytes(), publicKey.data(), publicKey.size()); + memcpy(serialized_keypair.Bytes() + publicKey.size(), privateKey.data(), privateKey.size()); + return keypair.Deserialize(serialized_keypair); +} + +CHIP_ERROR FactoryDataProviderImpl::Init(void) +{ + /* + * Currently the fwk_factory_data_provider module supports only ecb mode. + * Therefore return an error if encrypt mode is not ecb + */ + if (pAesKey == NULL || encryptMode != encrypt_ecb) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + + if (FDP_Init(pAesKey) < 0) + { + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProviderImpl::SetAes128Key(const uint8_t * keyAes128) +{ + CHIP_ERROR error = CHIP_ERROR_INVALID_ARGUMENT; + if (keyAes128 != nullptr) + { + pAesKey = keyAes128; + error = CHIP_NO_ERROR; + } + return error; +} + +CHIP_ERROR FactoryDataProviderImpl::SetEncryptionMode(EncryptionMode mode) +{ + CHIP_ERROR error = CHIP_ERROR_INVALID_ARGUMENT; + + /* + * Currently the fwk_factory_data_provider module supports only ecb mode. + * Therefore return an error if encrypt mode is not ecb + */ + if (mode == encrypt_ecb) + { + encryptMode = mode; + error = CHIP_NO_ERROR; + } + return error; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/factory_data/FactoryDataProviderFwkImpl.h b/src/platform/nxp/common/factory_data/FactoryDataProviderFwkImpl.h new file mode 100644 index 00000000000000..885e5ffdbfff63 --- /dev/null +++ b/src/platform/nxp/common/factory_data/FactoryDataProviderFwkImpl.h @@ -0,0 +1,65 @@ +/* + * + * Copyright (c) 2023 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. + */ +#pragma once + +#include + +namespace chip { +namespace DeviceLayer { + +/** + * @brief This class provides Commissionable data and Device Attestation Credentials. + * + * This implementation is using the SDK fwk_factory_data_provider module. + * + * For more information on this module, the interface description available in + * FactoryDataProvider/fwk_factory_data_provider.h inside the SDK can be checked. + */ + +class FactoryDataProviderImpl : public FactoryDataProvider +{ +public: + static FactoryDataProviderImpl sInstance; + + CHIP_ERROR Init(void); + CHIP_ERROR SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length, + uint32_t * contentAddr = NULL); + CHIP_ERROR SignWithDacKey(const ByteSpan & digestToSign, MutableByteSpan & outSignBuffer); + + CHIP_ERROR SetAes128Key(const uint8_t * keyAes128); + CHIP_ERROR SetEncryptionMode(EncryptionMode mode); + +private: + CHIP_ERROR LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P256Keypair & keypair); + + const uint8_t * pAesKey = nullptr; + EncryptionMode encryptMode = encrypt_ecb; +}; + +inline FactoryDataProvider & FactoryDataPrvd() +{ + return FactoryDataProviderImpl::sInstance; +} + +inline FactoryDataProviderImpl & FactoryDataPrvdImpl() +{ + return FactoryDataProviderImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/common/ram_storage.c b/src/platform/nxp/common/ram_storage.c new file mode 100644 index 00000000000000..bfd1869710ebf6 --- /dev/null +++ b/src/platform/nxp/common/ram_storage.c @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2021-2022, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include + +#include "FunctionLib.h" +#include "fsl_debug_console.h" +#include "fsl_os_abstraction.h" +#include "fwk_filesystem.h" +#include "ram_storage.h" + +#ifndef RAM_STORAGE_LOG +#define RAM_STORAGE_LOG 0 +#endif + +#ifndef KEY_BYTE_MAX_SIZE +#define KEY_BYTE_MAX_SIZE 28 +#endif + +#if RAM_STORAGE_LOG +#define RAM_STORAGE_PRINTF(key, size, ...) \ + PRINTF("[%s] ", __FUNCTION__); \ + uint8_t printIt; \ + PRINTF("[key = "); \ + for (printIt = 0; printIt < size; printIt++) \ + { \ + PRINTF("0x%x ", key[printIt]); \ + } \ + PRINTF("]"); \ + PRINTF(__VA_ARGS__); \ + PRINTF("\n\r"); +#else +#define RAM_STORAGE_PRINTF(...) +#endif + +struct settingsBlock +{ + uint8_t keyBytes[KEY_BYTE_MAX_SIZE]; + uint8_t keyBytesLen; + uint16_t length; +} __attribute__((packed)); + +static OSA_MUTEX_HANDLE_DEFINE(mRamStorageMutexId); + +static rsError ramStorageAdd(ramBufferDescriptor * pBuffer, const uint8_t * pAKey, uint8_t keySize, const uint8_t * aValue, + uint16_t aValueLength) +{ + rsError error; + struct settingsBlock * currentBlock; + const uint16_t newBlockLength = sizeof(struct settingsBlock) + aValueLength; + + (void) OSA_MutexLock((osa_mutex_handle_t) mRamStorageMutexId, osaWaitForever_c); + + if (*(pBuffer->ramBufferLen) + newBlockLength <= pBuffer->ramBufferMaxLen) + { + currentBlock = (struct settingsBlock *) &pBuffer->pRamBuffer[*(pBuffer->ramBufferLen)]; + memset(currentBlock, 0x0, sizeof(struct settingsBlock)); + memcpy(currentBlock->keyBytes, pAKey, keySize); + currentBlock->keyBytesLen = keySize; + currentBlock->length = aValueLength; + + memcpy(&pBuffer->pRamBuffer[*(pBuffer->ramBufferLen) + sizeof(struct settingsBlock)], aValue, aValueLength); + *(pBuffer->ramBufferLen) += newBlockLength; + + assert(*(pBuffer->ramBufferLen) <= pBuffer->ramBufferMaxLen); + + error = RS_ERROR_NONE; + } + else + { + assert(0); + error = RS_ERROR_NO_BUFS; + } + + (void) OSA_MutexUnlock((osa_mutex_handle_t) mRamStorageMutexId); + + RAM_STORAGE_PRINTF(pAKey, keySize, "lengthWriten = %d err = %d, newLen = %d", aValueLength, error, *(pBuffer->ramBufferLen)); + + return error; +} + +rsError ramStorageGet(const ramBufferDescriptor * pBuffer, const uint8_t * pAKey, uint8_t keySize, int aIndex, uint8_t * aValue, + uint16_t * aValueLength) +{ + uint16_t i = 0; + uint16_t valueLength = 0; + uint16_t readLength; + int currentIndex = 0; + const struct settingsBlock * currentBlock; + rsError error = RS_ERROR_NOT_FOUND; + + if (keySize <= KEY_BYTE_MAX_SIZE) + { + (void) OSA_MutexLock((osa_mutex_handle_t) mRamStorageMutexId, osaWaitForever_c); + + while (i < *(pBuffer->ramBufferLen)) + { + currentBlock = (struct settingsBlock *) &pBuffer->pRamBuffer[i]; + + /* Assert allowing to make sure that the dataset is not corrupted */ + assert(currentBlock->length <= pBuffer->ramBufferMaxLen); + + if (currentBlock->keyBytesLen == keySize && memcmp(pAKey, currentBlock->keyBytes, keySize) == 0) + { + if (currentIndex == aIndex) + { + readLength = currentBlock->length; + + // Perform read only if an input buffer was passed in + if (aValue != NULL && aValueLength != NULL) + { + // Adjust read length if input buffer size is smaller + if (readLength > *aValueLength) + { + readLength = *aValueLength; + } + + memcpy(aValue, &pBuffer->pRamBuffer[i + sizeof(struct settingsBlock)], readLength); + } + + valueLength = currentBlock->length; + error = RS_ERROR_NONE; + break; + } + + currentIndex++; + } + + i += sizeof(struct settingsBlock) + currentBlock->length; + } + + (void) OSA_MutexUnlock((osa_mutex_handle_t) mRamStorageMutexId); + } + else + { + error = RS_ERROR_WRONG_ARG; + } + + if (aValueLength != NULL) + { + *aValueLength = valueLength; + } + + RAM_STORAGE_PRINTF(pAKey, keySize, "err = %d", error); + + return error; +} + +rsError ramStorageSet(ramBufferDescriptor * pBuffer, const uint8_t * pAKey, uint8_t keySize, const uint8_t * aValue, + uint16_t aValueLength) +{ + uint16_t i = 0; + uint16_t currentBlockLength; + uint16_t nextBlockStart; + const struct settingsBlock * currentBlock; + rsError error = RS_ERROR_WRONG_ARG; + + assert(keySize <= KEY_BYTE_MAX_SIZE); + + if (keySize <= KEY_BYTE_MAX_SIZE) + { + (void) OSA_MutexLock((osa_mutex_handle_t) mRamStorageMutexId, osaWaitForever_c); + + // Delete all entries of aKey + while (i < *(pBuffer->ramBufferLen)) + { + currentBlock = (struct settingsBlock *) &pBuffer->pRamBuffer[i]; + currentBlockLength = sizeof(struct settingsBlock) + currentBlock->length; + + if (currentBlock->keyBytesLen == keySize && memcmp(pAKey, currentBlock->keyBytes, keySize) == 0) + { + nextBlockStart = i + currentBlockLength; + + if (nextBlockStart < *(pBuffer->ramBufferLen)) + { + memmove(&pBuffer->pRamBuffer[i], &pBuffer->pRamBuffer[nextBlockStart], + *(pBuffer->ramBufferLen) - nextBlockStart); + } + + assert(*(pBuffer->ramBufferLen) >= currentBlockLength); + *(pBuffer->ramBufferLen) -= currentBlockLength; + } + else + { + i += currentBlockLength; + } + } + error = ramStorageAdd(pBuffer, pAKey, keySize, aValue, aValueLength); + (void) OSA_MutexUnlock((osa_mutex_handle_t) mRamStorageMutexId); + } + + return error; +} + +rsError ramStorageDelete(ramBufferDescriptor * pBuffer, const uint8_t * pAKey, uint8_t keySize, int aIndex) +{ + uint16_t i = 0; + int currentIndex = 0; + uint16_t nextBlockStart; + uint16_t currentBlockLength; + const struct settingsBlock * currentBlock; + rsError error = RS_ERROR_NOT_FOUND; + + if (keySize <= KEY_BYTE_MAX_SIZE) + { + (void) OSA_MutexLock((osa_mutex_handle_t) mRamStorageMutexId, osaWaitForever_c); + + while (i < *(pBuffer->ramBufferLen)) + { + currentBlock = (struct settingsBlock *) &pBuffer->pRamBuffer[i]; + currentBlockLength = sizeof(struct settingsBlock) + currentBlock->length; + + if (currentBlock->keyBytesLen == keySize && memcmp(pAKey, currentBlock->keyBytes, keySize) == 0) + { + if (currentIndex == aIndex) + { + nextBlockStart = i + currentBlockLength; + + if (nextBlockStart < *(pBuffer->ramBufferLen)) + { + memmove(&pBuffer->pRamBuffer[i], &pBuffer->pRamBuffer[nextBlockStart], + *(pBuffer->ramBufferLen) - nextBlockStart); + } + + assert(*(pBuffer->ramBufferLen) >= currentBlockLength); + *(pBuffer->ramBufferLen) -= currentBlockLength; + + error = RS_ERROR_NONE; + break; + } + else + { + currentIndex++; + } + } + + i += currentBlockLength; + } + + (void) OSA_MutexUnlock((osa_mutex_handle_t) mRamStorageMutexId); + } + else + { + error = RS_ERROR_WRONG_ARG; + assert(0); + } + RAM_STORAGE_PRINTF(pAKey, keySize, "err = %d", error); + return error; +} + +void ramStorageInit(void) +{ + /* Mutex create */ + (void) OSA_MutexCreate(mRamStorageMutexId); + assert(NULL != mRamStorageMutexId); +} + +int ramStorageReadFromFlash(const char * file_name, uint8_t * buffer, uint32_t buf_length) +{ + int res; + + (void) OSA_MutexLock((osa_mutex_handle_t) mRamStorageMutexId, osaWaitForever_c); + + res = FS_ReadBufferFromFile(file_name, buffer, buf_length); + + (void) OSA_MutexUnlock((osa_mutex_handle_t) mRamStorageMutexId); + + return res; +} + +/* Buffer size must be superior to the max ram buffer size CHIP_CONFIG_RAM_BUFFER_KEY_STRING_SIZE */ +static uint8_t bufferIdleWriteToFlash[4 * 5000]; + +int ramStorageSavetoFlash(const char * file_name, uint8_t * buffer, uint32_t buf_length) +{ + int res; + + assert(sizeof(bufferIdleWriteToFlash) >= buf_length); + + /** + * Copy buffer to minimise the task lock duration + * TODO : Improve ram buffer management to minimize ram buffer usage + */ + (void) OSA_MutexLock((osa_mutex_handle_t) mRamStorageMutexId, osaWaitForever_c); + memcpy(bufferIdleWriteToFlash, buffer, buf_length); + (void) OSA_MutexUnlock((osa_mutex_handle_t) mRamStorageMutexId); + + res = FS_WriteBufferToFile(file_name, bufferIdleWriteToFlash, buf_length); + + return res; +} + +void ramStorageDump(const ramBufferDescriptor * pBuffer) +{ + uint16_t i = 0; + uint16_t j = 0; + uint16_t valueLength = 0; + uint16_t readLength; + int currentIndex = 0; + const struct settingsBlock * currentBlock; + rsError error = RS_ERROR_NOT_FOUND; + + (void) OSA_MutexLock((osa_mutex_handle_t) mRamStorageMutexId, osaWaitForever_c); + + while (i < *(pBuffer->ramBufferLen)) + { + currentBlock = (struct settingsBlock *) &pBuffer->pRamBuffer[i]; + PRINTF("key = "); + for (j = 0; j < currentBlock->keyBytesLen; j++) + { + PRINTF("%c", currentBlock->keyBytes[j]); + } + PRINTF("\nlen = %d\n", currentBlock->length); + i += sizeof(struct settingsBlock) + currentBlock->length; + } + (void) OSA_MutexUnlock((osa_mutex_handle_t) mRamStorageMutexId); +} diff --git a/src/platform/nxp/common/ram_storage.h b/src/platform/nxp/common/ram_storage.h new file mode 100644 index 00000000000000..cb900f5b33c7fe --- /dev/null +++ b/src/platform/nxp/common/ram_storage.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2021, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RAM_STORAGE_H +#define RAM_STORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + RS_ERROR_NONE, + RS_ERROR_NOT_FOUND, + RS_ERROR_NO_BUFS, + RS_ERROR_WRONG_ARG, +} rsError; + +typedef struct +{ + uint16_t * ramBufferLen; + uint16_t ramBufferMaxLen; + uint8_t * pRamBuffer; +} ramBufferDescriptor; + +rsError ramStorageGet(const ramBufferDescriptor * pBuffer, const uint8_t * pAKey, uint8_t keySize, int aIndex, uint8_t * aValue, + uint16_t * aValueLength); + +rsError ramStorageSet(ramBufferDescriptor * pBuffer, const uint8_t * pAKey, uint8_t keySize, const uint8_t * aValue, + uint16_t aValueLength); + +rsError ramStorageDelete(ramBufferDescriptor * pBuffer, const uint8_t * pAKey, uint8_t keySize, int aIndex); + +void ramStorageInit(void); + +int ramStorageReadFromFlash(const char * file_name, uint8_t * buffer, uint32_t buf_length); + +int ramStorageSavetoFlash(const char * file_name, uint8_t * buffer, uint32_t buf_length); + +void ramStorageDump(const ramBufferDescriptor * pBuffer); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // RAM_STORAGE_H diff --git a/src/platform/nxp/rt/rw61x/BUILD.gn b/src/platform/nxp/rt/rw61x/BUILD.gn new file mode 100644 index 00000000000000..d8a72d1e449718 --- /dev/null +++ b/src/platform/nxp/rt/rw61x/BUILD.gn @@ -0,0 +1,153 @@ +# Copyright (c) 2021 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/chip.gni") +import("//build_overrides/nxp_sdk.gni") +import("//build_overrides/openthread.gni") +import("${chip_root}/src/platform/device.gni") +import("${nxp_sdk_build_root}/${nxp_sdk_name}/${nxp_sdk_name}.gni") +import("${nxp_sdk_build_root}/nxp_sdk.gni") + +assert(chip_device_platform == "nxp") + +config("nxp_platform_config") { + defines = [ "EXTERNAL_BLEMANAGERIMPL_HEADER=\"platform/nxp/common/ble_zephyr/BLEManagerImpl.h\"" ] + include_dirs = [ + ".", + "../../common", + ] + if (chip_with_factory_data == 1) { + include_dirs += [ + ".", + "../../common/factory_data", + ] + defines += [ "CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA=1" ] + defines += [ "EXTERNAL_FACTORY_DATA_PROVIDER_IMPL_HEADER=\"platform/nxp/common/factory_data/FactoryDataProviderFwkImpl.h\"" ] + } +} + +static_library("nxp_platform") { + deps = [] + defines = [] + sources = [ + "../../../FreeRTOS/SystemTimeSupport.cpp", + "../../../SingletonConfigurationManager.cpp", + "../../common/CHIPDevicePlatformEvent.h", + "../../common/ConfigurationManagerImpl.cpp", + "../../common/ConfigurationManagerImpl.h", + "../../common/ConnectivityManagerImpl.cpp", + "../../common/ConnectivityManagerImpl.h", + "../../common/DiagnosticDataProviderImpl.cpp", + "../../common/DiagnosticDataProviderImpl.h", + "../../common/KeyValueStoreManagerImpl.cpp", + "../../common/KeyValueStoreManagerImpl.h", + "../../common/Logging.cpp", + "../../common/NXPConfig.h", + "../../common/NetworkProvisioningServerImpl.h", + "../../common/PlatformManagerImpl.h", + "../../common/SoftwareUpdateManagerImpl.h", + "CHIPDevicePlatformConfig.h", + "PlatformManagerImpl.cpp", + ] + + if (rt_nvm_component == "nvm_fwk" || rt_nvm_component == "littlefs") { + sources += [ + "../../common/NXPConfig.cpp", + "../../common/ram_storage.c", + "../../common/ram_storage.h", + ] + } else { + sources += [ "../../common/NXPConfigKS.cpp" ] + } + + public_deps = [ "${chip_root}/src/platform:platform_base" ] + + if (chip_enable_ble) { + sources += [ + # Adding rand32 file which defines the function sys_csrand_get which is called by BLEManagerImpl from Zephyr + "${nxp_sdk_build_root}/${nxp_sdk_name}/sdk_hook/zephyr/random/rand32.cpp", + "../../../Zephyr/BLEAdvertisingArbiter.cpp", + "../../../Zephyr/BLEManagerImpl.cpp", + "../../common/ble_zephyr/BLEManagerImpl.h", + ] + } + + # define CHIP_PLAT_NVM_SUPPORT - See NXPConfig.cpp for definition + if (rt_nvm_component == "nvm_fwk") { + defines += [ "CHIP_PLAT_NVM_SUPPORT=1" ] + } else if (rt_nvm_component == "littlefs") { + defines += [ "CHIP_PLAT_NVM_SUPPORT=2" ] + } else if (rt_nvm_component == "key_storage") { + defines += [ "CHIP_PLAT_NVM_SUPPORT=3" ] + } + + if (chip_enable_wifi) { + sources += [ + "../../common/NetworkCommissioningDriver.h", + "../../common/NetworkCommissioningWiFiDriver.cpp", + ] + } + if (chip_enable_ota_requestor) { + sources += [ + "../../common/OTAImageProcessorImpl.cpp", + "../../common/OTAImageProcessorImpl.h", + ] + include_dirs = + [ "${chip_root}/examples/platform/nxp/common/mcuboot_app_support/" ] + } + + if (chip_enable_openthread) { + sources += [ + "../../../OpenThread/OpenThreadUtils.cpp", + "../../common/ThreadStackManagerImpl.cpp", + "../../common/ThreadStackManagerImpl.h", + ] + + deps += [ "${chip_root}/third_party/openthread:openthread" ] + + if (chip_mdns == "platform") { + sources += [ + "../../../OpenThread/DnssdImpl.cpp", + "../../../OpenThread/OpenThreadDnssdImpl.cpp", + "../../../OpenThread/OpenThreadDnssdImpl.h", + ] + deps += [ "${chip_root}/src/lib/dnssd:platform_header" ] + } + } + + if (chip_with_factory_data == 1) { + sources += [ + "../../common/factory_data/FactoryDataProvider.cpp", + "../../common/factory_data/FactoryDataProvider.h", + "../../common/factory_data/FactoryDataProviderFwkImpl.cpp", + "../../common/factory_data/FactoryDataProviderFwkImpl.h", + ] + } + + deps += [ "${nxp_sdk_build_root}:nxp_sdk" ] + + public_deps += [ + "${chip_root}/examples/platform/nxp/common/app/support:freertos_memory_utils", + "${chip_root}/src/crypto", + "${chip_root}/src/platform:syscalls_stub", + ] + + public_configs = [ + ":nxp_platform_config", + + # address_resolve config needed by the include of server.h in ConfigurationManagerImpl.cpp + "${chip_root}/src/lib/address_resolve:default_address_resolve_config", + ] +} diff --git a/src/platform/nxp/rt/rw61x/BlePlatformConfig.h b/src/platform/nxp/rt/rw61x/BlePlatformConfig.h new file mode 100644 index 00000000000000..fdd79a53501f12 --- /dev/null +++ b/src/platform/nxp/rt/rw61x/BlePlatformConfig.h @@ -0,0 +1,37 @@ +/* + * + * Copyright (c) 2021-2022 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. + */ + +/** + * @file + * Platform-specific configuration overrides for the CHIP BLE + * Layer on RW61x platform using the NXP SDK. + * + */ + +#pragma once + +// ==================== Platform Adaptations ==================== + +/* Default NXP Platform adaptations are used */ + +// ========== Platform-specific Configuration Overrides ========= + +/* Default NXP Platform configuration overrides are used */ + +// Include default nxp platform configurations +#include "platform/nxp/common/ble_zephyr/BleNXPPlatformDefaultConfig.h" diff --git a/src/platform/nxp/rt/rw61x/CHIPDevicePlatformConfig.h b/src/platform/nxp/rt/rw61x/CHIPDevicePlatformConfig.h new file mode 100644 index 00000000000000..026c4a37dadb33 --- /dev/null +++ b/src/platform/nxp/rt/rw61x/CHIPDevicePlatformConfig.h @@ -0,0 +1,43 @@ +/* + * + * Copyright (c) 2020-2022 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 + * Platform-specific configuration overrides for the chip Device Layer + * on NXP platforms using the NXP SDK. + */ + +#pragma once + +// ==================== Platform Adaptations ==================== + +/* Default NXP Platform adaptations are used */ + +// ========== Platform-specific Configuration ========= + +// These are configuration options that are unique to the NXP platform. +// These can be overridden by the application as needed. + +// ========== Platform-specific Configuration Overrides ========= + +/* Default NXP Platform configuration overrides are used */ + +// Include default nxp platform configurations +#include "platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h" diff --git a/src/platform/nxp/rt/rw61x/CHIPPlatformConfig.h b/src/platform/nxp/rt/rw61x/CHIPPlatformConfig.h new file mode 100644 index 00000000000000..eedd1101802b3f --- /dev/null +++ b/src/platform/nxp/rt/rw61x/CHIPPlatformConfig.h @@ -0,0 +1,55 @@ +/* + * + * Copyright (c) 2020-2022 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 + * Platform-specific configuration overrides for CHIP on + * NXP RW61x platform. + */ + +#pragma once + +#include + +// ==================== General Platform Adaptations ==================== + +/* Default NXP platform adaptations are used */ + +// ==================== Security Adaptations ==================== + +/* Default NXP Platform security adaptations are used */ + +// ==================== General Configuration Overrides ==================== + +/* Default NXP Platform general configuration overrides are used */ + +/* For now on RW610, due to the current file system implementation only 5 fabrics are supported */ +#define CHIP_CONFIG_MAX_FABRICS 5 + +// ==================== Security Configuration Overrides ==================== + +/* Default NXP Platform security configuration overrides are used */ + +// ==================== WDM Configuration Overrides ==================== + +/* Default NXP Platform WDM Configuration overrides are used */ + +// Include default nxp platform configurations +#include "platform/nxp/common/CHIPNXPPlatformDefaultConfig.h" diff --git a/src/platform/nxp/rt/rw61x/InetPlatformConfig.h b/src/platform/nxp/rt/rw61x/InetPlatformConfig.h new file mode 100644 index 00000000000000..656876b876ffa7 --- /dev/null +++ b/src/platform/nxp/rt/rw61x/InetPlatformConfig.h @@ -0,0 +1,41 @@ +/* + * + * Copyright (c) 2020-2022 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 + * Platform-specific configuration overrides for the CHIP Inet + * Layer on RW61x platform using the NXP SDK. + * + */ + +#pragma once + +#include + +// ==================== Platform Adaptations ==================== + +/* Default NXP Platform adaptations are used */ + +// ========== Platform-specific Configuration Overrides ========= + +/* Default NXP Platform configuration overrides are used */ + +// Include default nxp platform configurations +#include "platform/nxp/common/InetNXPPlatformDefaultConfig.h" diff --git a/src/platform/nxp/rt/rw61x/PlatformManagerImpl.cpp b/src/platform/nxp/rt/rw61x/PlatformManagerImpl.cpp new file mode 100644 index 00000000000000..fb5b900f345b5d --- /dev/null +++ b/src/platform/nxp/rt/rw61x/PlatformManagerImpl.cpp @@ -0,0 +1,346 @@ +/* + * + * Copyright (c) 2020-2022 Project CHIP Authors + * Copyright (c) 2020 Nest Labs, Inc. + * 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 + * Provides an implementation of the PlatformManager object + * for RW61x platform using the NXP RW610 SDK. + */ +/* this file behaves like a config.h, comes first */ +#include + +#include "DiagnosticDataProviderImpl.h" +#include "fsl_adapter_rng.h" +#include "fsl_os_abstraction.h" +#include "fwk_platform_coex.h" +#include +#include +#include +#include +#include + +#include + +#include MBEDTLS_PORT_INCLUDE + +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +#include "OtaSupport.h" +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +#include "fwk_platform_ot.h" +#include "ot_platform_common.h" +#endif + +extern "C" void BOARD_InitHardware(void); + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + +#include "wlan_bt_fw.h" + +extern "C" { +#include "wlan.h" +#include "wm_net.h" +} + +#ifdef gPlatformMonolithicApp_d +extern const uint32_t fw_cpu1[]; +#define WIFI_FW_BIN_ADDRESS (uint32_t) & fw_cpu1[0] +#else +#define WIFI_FW_BIN_ADDRESS wlan_fw_bin +#endif + +#endif /* CHIP_DEVICE_CONFIG_ENABLE_WPA */ + +extern "C" void vApplicationMallocFailedHook(void) +{ + ChipLogError(DeviceLayer, "Malloc Failure"); +} + +#if !CHIP_DEVICE_CONFIG_ENABLE_WPA +extern "C" void vApplicationIdleHook(void) +{ + chip::DeviceLayer::PlatformManagerImpl::IdleHook(); +} +#endif + +extern "C" void __wrap_exit(int __status) +{ + ChipLogError(DeviceLayer, "======> error exit function !!!"); + assert(0); +} + +/* wlan_event_callback should be defined here because it is + * referenced in wlan.c but only defined in main.c of sdk examples */ +#if CHIP_DEVICE_CONFIG_ENABLE_WPA +extern "C" int wlan_event_callback(enum wlan_event_reason reason, void * data) +{ + return 0; +} +#endif /* CHIP_DEVICE_CONFIG_ENABLE_WPA */ + +namespace chip { +namespace DeviceLayer { + +PlatformManagerImpl PlatformManagerImpl::sInstance; + +void PlatformManagerImpl::HardwareInit(void) +{ + BOARD_InitHardware(); + SysTick_Config(SystemCoreClock / configTICK_RATE_HZ); +} + +CHIP_ERROR PlatformManagerImpl::ServiceInit(void) +{ + status_t status; + hal_rng_status_t rngStatus; + CHIP_ERROR chipRes = CHIP_NO_ERROR; + + status = CRYPTO_InitHardware(); + + if (status != 0) + { + chipRes = CHIP_ERROR_INTERNAL; + ChipLogError(DeviceLayer, "Crypto hardware init error"); + } + + return chipRes; +} + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA +CHIP_ERROR PlatformManagerImpl::WiFiInterfaceInit(void) +{ + CHIP_ERROR result = CHIP_NO_ERROR; + int wifi_status = WM_SUCCESS; + + ChipLogProgress(DeviceLayer, "Initialize WLAN"); + + wifi_status = wlan_init((uint8_t *) WIFI_FW_BIN_ADDRESS, wlan_fw_bin_len); + if (wifi_status != WM_SUCCESS) + { + ChipLogError(DeviceLayer, "WLAN initialization failed"); + result = CHIP_ERROR_INTERNAL; + } + else + { + ChipLogProgress(DeviceLayer, "WLAN initialized"); + } + + return result; +} +#endif + +CHIP_ERROR PlatformManagerImpl::_InitChipStack(void) +{ + CHIP_ERROR err = CHIP_ERROR_INTERNAL; + int osError; + + /* Mask of combined controllers to initialize */ + uint8_t controllerMask = 0U; + + // Initialize the configuration system. + err = Internal::NXPConfig::Init(); + SuccessOrExit(err); + + SetConfigurationMgr(&ConfigurationManagerImpl::GetDefaultInstance()); + SetDiagnosticDataProvider(&DiagnosticDataProviderImpl::GetDefaultInstance()); + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + /* Initialize LwIP via Wi-Fi layer. */ + net_ipv4stack_init(); +#else + /* Initialize LwIP directly. */ + tcpip_init(NULL, NULL); +#endif + + /* + * Initialize controllers here before initializing BLE/OT/WIFI, + * this will load the firmware in CPU1/CPU2 depending on the + * connectivity used + */ + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + controllerMask |= conn802_15_4_c; +#endif /* CHIP_DEVICE_CONFIG_ENABLE_THREAD */ +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + controllerMask |= connBle_c; +#endif /* CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE */ +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + controllerMask |= connWlan_c; +#endif /* CHIP_DEVICE_CONFIG_ENABLE_WPA */ + + PLATFORM_InitControllers(controllerMask); + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + + /* Initialize platform services */ + err = ServiceInit(); + SuccessOrExit(err); + +#ifdef SPINEL_INTERFACE_RPMSG + otPlatRadioInitSpinelInterface(); +#endif /* SPINEL_INTERFACE_RPMSG */ + PLATFORM_InitOt(); + /* + * Initialize the RCP here: the WiFi initialization requires to enable/disable + * coexistence through the Spinel interface; as such, the otPlatRadioInit() call + * will fail if done afterwards + */ + otPlatLogInit(); + otPlatRadioInit(); +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + osError = os_setup_idle_function(chip::DeviceLayer::PlatformManagerImpl::IdleHook); + if (osError != WM_SUCCESS) + { + ChipLogError(DeviceLayer, "Failed to setup idle function"); + err = CHIP_ERROR_NO_MEMORY; + goto exit; + } + + err = WiFiInterfaceInit(); + + if (err != CHIP_NO_ERROR) + { + ChipLogProgress(DeviceLayer, + "Wi-Fi module initialization failed. Make sure the Wi-Fi/BLE module is properly configured and connected " + "with the board and start again!"); + chipDie(); + } + ChipLogProgress(DeviceLayer, "Wi-Fi module initialization done."); + + /* Initialize platform services */ + err = ServiceInit(); + SuccessOrExit(err); + +#endif + + // Call _InitChipStack() on the generic implementation base class + // to finish the initialization process. + err = Internal::GenericPlatformManagerImpl_FreeRTOS::_InitChipStack(); + SuccessOrExit(err); + + err = System::Clock::InitClock_RealTime(); + SuccessOrExit(err); + + mStartTime = System::SystemClock().GetMonotonicTimestamp(); + +exit: + return err; +} + +void PlatformManagerImpl::SaveSettings(void) +{ +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + otPlatSaveSettingsIdle(); +#endif +} + +void PlatformManagerImpl::IdleHook(void) +{ + bool isResetScheduled = PlatformMgrImpl().GetResetInIdleValue(); + if (isResetScheduled) + { + /* + * In case a reset in IDLE has been scheduled + * Disable IRQs so that the idle task won't be preempted until the reset + */ + OSA_InterruptDisable(); + } + + chip::DeviceLayer::Internal::NXPConfig::RunSystemIdleTask(); + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + SaveSettings(); +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + /* Resume OTA Transactions in Idle task */ + OTA_TransactionResume(); +#endif + + /* + * In case a reset in idle operation has been posted, + * reset the device after having run the idle function + */ + if (isResetScheduled) + { + PlatformMgrImpl().Reset(); + } +} + +void PlatformManagerImpl::Reset(void) +{ + ChipLogProgress(DeviceLayer, "System restarting"); + // Restart the system. + NVIC_SystemReset(); + while (1) + { + } +} + +void PlatformManagerImpl::ScheduleResetInIdle(void) +{ + resetInIdle = true; +} + +bool PlatformManagerImpl::GetResetInIdleValue(void) +{ + return resetInIdle; +} + +void PlatformManagerImpl::StopBLEConnectivity(void) {} + +void PlatformManagerImpl::_Shutdown() +{ + uint64_t upTime = 0; + + if (GetDiagnosticDataProvider().GetUpTime(upTime) == CHIP_NO_ERROR) + { + uint32_t totalOperationalHours = 0; + + if (ConfigurationMgr().GetTotalOperationalHours(totalOperationalHours) == CHIP_NO_ERROR) + { + ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours + static_cast(upTime / 3600)); + } + else + { + ChipLogError(DeviceLayer, "Failed to get total operational hours of the Node"); + } + } + else + { + ChipLogError(DeviceLayer, "Failed to get current uptime since the Node’s last reboot"); + } + + /* Handle the server shutting down & emit the ShutDown event*/ + PlatformMgr().HandleServerShuttingDown(); + /* Shutdown all layers */ + Internal::GenericPlatformManagerImpl_FreeRTOS::_Shutdown(); +} + +} // namespace DeviceLayer +} // namespace chip + +extern "C" void mt_wipe(void) +{ + chip::DeviceLayer::Internal::NXPConfig::FactoryResetConfig(); +} diff --git a/src/platform/nxp/rt/rw61x/SystemPlatformConfig.h b/src/platform/nxp/rt/rw61x/SystemPlatformConfig.h new file mode 100644 index 00000000000000..226392a94dacff --- /dev/null +++ b/src/platform/nxp/rt/rw61x/SystemPlatformConfig.h @@ -0,0 +1,41 @@ +/* + * + * Copyright (c) 2020-2022 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 + * Platform-specific configuration overrides for the CHIP System + * Layer on NXP RW61x Platform. + * + */ + +#pragma once + +#include + +// ==================== Platform Adaptations ==================== + +/* Default NXP Platform adaptations are used */ + +// ========== Platform-specific Configuration Overrides ========= + +/* Default NXP Platform configuration overrides are used */ + +// Include default nxp platform configurations +#include "platform/nxp/common/SystemNXPPlatformDefaultConfig.h" diff --git a/src/platform/nxp/rt/rw61x/args.gni b/src/platform/nxp/rt/rw61x/args.gni new file mode 100644 index 00000000000000..9e7cf8a37d0292 --- /dev/null +++ b/src/platform/nxp/rt/rw61x/args.gni @@ -0,0 +1,69 @@ +# 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/chip.gni") +import("//build_overrides/nxp_sdk.gni") + +rt_platform = "rw61x" +rt_fwk_platform = "rw61x" +nxp_platform = "rt/${rt_platform}" +nxp_sdk_name = "rt_sdk" +chip_device_platform = "nxp" +lwip_platform = "nxp" + +# ARM architecture flags will be set based on NXP board. +arm_platform_config = "${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_arm.gni" + +chip_device_project_config_include = "" +chip_project_config_include = "" +chip_inet_project_config_include = "" +chip_system_project_config_include = "" +chip_ble_project_config_include = "" + +chip_build_tests = false + +#This enables the EventList global attribute +enable_eventlist_attribute = true + +declare_args() { + spinel_interface_rpmsg = true + + # if rw610_mbedtls_port_els_pkc is set to false software mbedtls is used instead + rw610_mbedtls_port_els_pkc = true +} + +# TODO : Enable the OTA Requestor by default. +# This requires the mcuboot bootloader to be used, which reserves the first 128 kB of the flash. +# If mcuboot is not used, "no_mcuboot" must be set to true in the gn gen build command +# in order for the application to be linked at the base of the flash. +#chip_enable_ota_requestor = true +declare_args() { + # TODO : set no_mcuboot to false by default when enabling ota requestor by default + no_mcuboot = true +} + +# As a temporary workaround, we are disabling the session resumption because currently +# the mbedtls port does not support this. +# If not disabled, reconnecting to the OTA Provider node will fail. +chip_enable_session_resumption = false + +mbedtls_target = "${nxp_sdk_build_root}:nxp_mbedtls" + +openthread_external_mbedtls = mbedtls_target +openthread_project_core_config_file = "OpenThreadConfig.h" +openthread_core_config_deps = [ "${chip_root}/third_party/openthread/platforms/nxp/${nxp_platform}:openthread_core_config_rw61x" ] +openthread_core_config_platform_check_file = + "openthread-core-rw612-config-check.h" +openthread_external_platform = "${chip_root}/third_party/openthread/platforms/nxp/${nxp_platform}:libopenthread-rw61x" diff --git a/src/system/BUILD.gn b/src/system/BUILD.gn index 6c036a73d920b6..86e02725e261c6 100644 --- a/src/system/BUILD.gn +++ b/src/system/BUILD.gn @@ -58,6 +58,8 @@ if (chip_device_platform == "cc13x2_26x2") { import("//build_overrides/k32w0_sdk.gni") } else if (chip_device_platform == "k32w1") { import("//build_overrides/k32w1_sdk.gni") +} else if (chip_device_platform == "nxp") { + import("//build_overrides/nxp_sdk.gni") } else if (chip_device_platform == "psoc6") { import("//build_overrides/psoc6.gni") } else if (chip_device_platform == "cyw30739") { @@ -181,6 +183,9 @@ source_set("system_config_header") { if (chip_device_platform == "k32w1") { public_deps += [ "${k32w1_sdk_build_root}:k32w1_sdk" ] } + if (chip_device_platform == "nxp") { + public_deps += [ "${nxp_sdk_build_root}:nxp_sdk" ] + } if (chip_device_platform == "cyw30739") { public_deps += [ "${cyw30739_sdk_build_root}:cyw30739_sdk" ] } diff --git a/third_party/nxp/BUILD.gn b/third_party/nxp/BUILD.gn new file mode 100644 index 00000000000000..f35b5f9c852ba5 --- /dev/null +++ b/third_party/nxp/BUILD.gn @@ -0,0 +1,34 @@ +# Copyright (c) 2022 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/chip.gni") +import("//build_overrides/nxp_sdk.gni") +import("${nxp_sdk_build_root}/nxp_sdk.gni") + +group("nxp_sdk") { + public_deps = [ "${nxp_sdk_build_root}/${nxp_sdk_name}:nxp_sdk" ] +} + +if (nxp_use_lwip) { + group("nxp_lwip") { + public_deps = [ "${nxp_sdk_build_root}/${nxp_sdk_name}:nxp_lwip" ] + } +} + +if (nxp_use_mbedtls_port) { + group("nxp_mbedtls") { + public_deps = [ "${nxp_sdk_build_root}/${nxp_sdk_name}:nxp_mbedtls" ] + } +} diff --git a/third_party/nxp/nxp_sdk.gni b/third_party/nxp/nxp_sdk.gni new file mode 100644 index 00000000000000..d87d99d2911ae2 --- /dev/null +++ b/third_party/nxp/nxp_sdk.gni @@ -0,0 +1,55 @@ +# Copyright (c) 2022 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. + +declare_args() { + # Indicates the name of the nxp platform targeted + nxp_platform = "" + + # Specifies the CHIP_DEVICE_LAYER_TARGET in src/platform/BUILD.gn + nxp_device_layer = "nxp/common" + + # Enables target nxp_lwip. Used by RT platforms. + nxp_use_lwip = true + + # Enables target nxp_mbedtls. Used by RT platforms. + nxp_use_mbedtls_port = true + + # Enables the support of the Matter CLI + chip_enable_matter_cli = false + + # Enables the support of factory data + chip_with_factory_data = 0 + + # Enables the auto pairing advertisement at boot + chip_enable_pairing_autostart = 1 + + # Indicates if the nxp SDK used has the SDK package format + is_sdk_package = false + + # Indicates if the nxp SDK used has the nxp SDK internal format + is_sdk_internal = false + + # Defines the current software version + nxp_software_version = 1 + + # Defines the current software string version + nxp_software_version_string = "1.1" +} + +declare_args() { + nxp_sdk_name = "${nxp_platform}_sdk" +} + +assert(nxp_platform != "", "nxp_platform should be defined") diff --git a/third_party/nxp/rt_sdk/BUILD.gn b/third_party/nxp/rt_sdk/BUILD.gn new file mode 100644 index 00000000000000..90640e8b1eb2ed --- /dev/null +++ b/third_party/nxp/rt_sdk/BUILD.gn @@ -0,0 +1,177 @@ +# 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/nxp_sdk.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( + "${nxp_sdk_build_root}/${nxp_sdk_name}/${rt_platform}/${rt_platform}.gni") +import("${nxp_sdk_build_root}/${nxp_sdk_name}/bt_ble/bt_ble.gni") +import("${nxp_sdk_build_root}/${nxp_sdk_name}/lwip/lwip.gni") +import("${nxp_sdk_build_root}/${nxp_sdk_name}/mbedtls/mbedtls.gni") + +import("//build_overrides/openthread.gni") + +import("${chip_root}/src/platform/device.gni") +import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") + +mbedtls_root = "${rt_sdk_root}/middleware/mbedtls" + +group("nxp_sdk") { + public_deps = [ + ":nxp_transceiver", + nxp_sdk_driver_target, + nxp_sdk_target, + ] + + if (chip_enable_ble) { + public_deps += [ ":nxp_bt_ble" ] + } + + if (chip_enable_wifi) { + public_deps += [ ":nxp_wifi" ] + } + if (chip_enable_openthread) { + public_deps += [ "${openthread_root}/src/core:libopenthread_core_headers" ] + } +} + +config("mbedtls_ksdk_config") { + include_dirs = [ "${mbedtls_root}/port/ksdk" ] + defines = [ "MBEDTLS_PORT_INCLUDE=" ] + if (chip_enable_openthread) { + defines += [ "MBEDTLS_CONFIG_FILE=" ] + } else { + defines += [ "MBEDTLS_CONFIG_FILE=" ] + include_dirs += [ "${nxp_sdk_build_root}/${nxp_sdk_name}/mbedtls/config" ] + } +} + +config("mbedtls_els_pkc_config") { + include_dirs = [ + "${mbedtls_root}/port/els", + "${mbedtls_root}/port/pkc", + ] + defines = [ "MBEDTLS_PORT_INCLUDE=" ] + + if (chip_enable_openthread) { + defines += [ "MBEDTLS_CONFIG_FILE=" ] + } else { + defines += [ "MBEDTLS_CONFIG_FILE=" ] + } +} + +mbedtls_target("nxp_els_pkc_mbedtls") { + sources = [] + public_deps = [ ":nxp_sdk" ] + public_configs = [ ":mbedtls_els_pkc_config" ] + sources += [ + # els port + "${mbedtls_root}/port/els/aes_alt.c", + "${mbedtls_root}/port/els/cbc_mac_alt.c", + "${mbedtls_root}/port/els/cmac_alt.c", + "${mbedtls_root}/port/els/ctr_drbg_alt.c", + "${mbedtls_root}/port/els/els_mbedtls.c", + "${mbedtls_root}/port/els/entropy_poll_alt.c", + "${mbedtls_root}/port/els/gcm_alt.c", + "${mbedtls_root}/port/els/sha256_alt.c", + "${mbedtls_root}/port/els/sha512_alt.c", + + # pkc port + "${mbedtls_root}/port/pkc/ecc_alt.c", + "${mbedtls_root}/port/pkc/ecdh_alt.c", + "${mbedtls_root}/port/pkc/ecdsa_alt.c", + "${mbedtls_root}/port/pkc/els_pkc_mbedtls.c", + "${mbedtls_root}/port/pkc/rsa_alt.c", + ] +} + +mbedtls_target("nxp_ksdk_mbedtls") { + sources = [] + public_deps = [ ":nxp_sdk" ] + public_configs = [ ":mbedtls_ksdk_config" ] + sources += [ + "${mbedtls_root}/port/ksdk/aes_alt.c", + "${mbedtls_root}/port/ksdk/des_alt.c", + "${mbedtls_root}/port/ksdk/ecp_alt.c", + "${mbedtls_root}/port/ksdk/ecp_alt_ksdk.c", + "${mbedtls_root}/port/ksdk/ecp_curves_alt.c", + "${mbedtls_root}/port/ksdk/ksdk_mbedtls.c", + ] + + # Allow a platform to use a software implementation of ksdk_mbedtls.c if provided + if (defined(ksdk_mbedtls_sw_impl)) { + sources -= [ "${mbedtls_root}/port/ksdk/ksdk_mbedtls.c" ] + sources += [ "${ksdk_mbedtls_sw_impl}" ] + } +} + +group("nxp_mbedtls") { + public_deps = + [ "${nxp_sdk_build_root}/${nxp_sdk_name}/${rt_platform}:nxp_mbedtls" ] +} + +config("lwip_rt_config") { + include_dirs = [ + "${rt_sdk_root}/middleware/lwip/src/include", + "${rt_sdk_root}/middleware/lwip/port", + "lwip/common", + ] + if (chip_enable_ethernet) { + include_dirs += [ "lwip/ethernet" ] + } else if (chip_enable_openthread && chip_enable_wifi) { + include_dirs += [ "lwip/wifi_openthread" ] + } else if (chip_enable_openthread) { + include_dirs += [ "lwip/openthread" ] + } else if (chip_enable_wifi) { + include_dirs += [ "lwip/wifi" ] + } +} + +lwip_target("nxp_lwip") { + public = [] + sources = [ + #lwip port file + "${rt_sdk_root}/middleware/lwip/port/sys_arch.c", + ] + if (chip_enable_ethernet) { + sources += [ + "${rt_sdk_root}/middleware/lwip/port/enet_ethernetif.c", + "${rt_sdk_root}/middleware/lwip/port/enet_ethernetif_kinetis.c", + ] + } + public_configs = [ ":lwip_rt_config" ] + + public_deps = [ ":nxp_sdk" ] + rt_sdk_root = rt_sdk_root +} + +bt_ble_target("nxp_bt_ble") { + public_deps = [ nxp_sdk_target ] + rt_sdk_root = rt_sdk_root +} + +rt_transceiver("nxp_transceiver") { + public_deps = [ nxp_sdk_target ] +} + +rt_wifi("nxp_wifi") { + public_deps = [ nxp_sdk_target ] +} diff --git a/third_party/nxp/rt_sdk/bt_ble/bt_ble.gni b/third_party/nxp/rt_sdk/bt_ble/bt_ble.gni new file mode 100644 index 00000000000000..e039a6072d38f5 --- /dev/null +++ b/third_party/nxp/rt_sdk/bt_ble/bt_ble.gni @@ -0,0 +1,228 @@ +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/nxp_sdk.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") +template("bt_ble_target") { + if (defined(invoker.rt_sdk_root)) { + rt_sdk_root = invoker.rt_sdk_root + } + + assert(rt_sdk_root != "", "rt_sdk_root must be specified") + bt_ble_target_name = target_name + + config("${bt_ble_target_name}_warnings") { + cflags = [ + "-Wno-maybe-uninitialized", + "-Wno-string-concatenation", + ] + } + + config("${bt_ble_target_name}_config") { + cflags = [] + defines = [] + if (defined(invoker.cflags)) { + cflags += invoker.cflags + } + + bt_ble_include_dirs = [ + #fatfs required for ethermind + "${rt_sdk_root}/middleware/fatfs/source", + + #edgefast_bluetooth + "${rt_sdk_root}/middleware/edgefast_bluetooth/include", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/porting", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/platform", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/platform/configs", + + #ethermind + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/export/include", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/export/eOSAL", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/export/extension", + "${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux/bluetooth", + "${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux/bluetooth/controller", + "${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux/ethal", + "${rt_sdk_root}/middleware/wireless/ethermind/port/osal/src/freertos", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/lib/mcux/default/config", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/protocols/sm", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/protocols/sdp", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/protocols/dbase", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/protocols/rfcomm", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/protocols/bnep", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/protocols/avdtp", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/protocols/avctp", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/protocols/smp", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/protocols/obex", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/protocols/mcap", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/protocols/att", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/protocols/hci_1.2", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/utils/aes_cmac", + + # Common edgeFast config file + "${rt_sdk_root}/middleware/edgefast_bluetooth/output/templates/config", + + # Transceiver + "${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux/bluetooth/controller", + + # SDK hook requires to build the BLEManagerImpl.cpp from Zephyr + "${nxp_sdk_build_root}/${nxp_sdk_name}/sdk_hook", + ] + libs = [] + + if (hci_spinel_single_uart) { + # Allows to wrap hci_uart functions to another implementation. + # The goal is to have hci and spinel encapsulated in hdlc frames. + # To view the content of new implementations, the code of spinel_hci_hdlc.cpp should be checked + ldflags = [ + "-Wl,--defsym,hci_uart_write_data=__wrap_hci_uart_write_data", + "-Wl,--wrap=hci_uart_bt_init", + "-Wl,--wrap=hci_uart_bt_shutdown", + "-Wl,--wrap=hci_uart_init", + ] + bt_ble_include_dirs += [ + "${rt_sdk_root}/middleware/wireless/ethermind/port/pal", + + # SDK hook to be able to undef the value of EM_HAVE_STATIC_DECL + # so that we can do an extern of the hci_uart_state variable + "${nxp_sdk_build_root}/${nxp_sdk_name}/sdk_hook/bt_pal", + ] + } else { + defines += [ "HAL_UART_DMA_ENABLE=1" ] + bt_ble_include_dirs += + [ "${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux" ] + } + + defines += [ + #BT config, + "CONFIG_BT_PERIPHERAL=1", + "CONFIG_BT_GATT_DYNAMIC_DB=1", + "CONFIG_BT_SETTINGS=0", + "CONFIG_BT_HOST_CRYPTO=1", + "CONFIG_BT_KEYS_OVERWRITE_OLDEST=1", + "BT_BLE_PLATFORM_INIT_ESCAPE", + "BT_CHIP_SUPPORT", + + #increase the Max transmission Unit (MTU) to 247 as defined in the Matter specific + # BT_L2CAP_RX_MTU = CONFIG_BT_BUF_ACL_RX_SIZE - BT_L2CAP_HDR_SIZE with BT_L2CAP_HDR_SIZE = 4 + # therefore define CONFIG_BT_BUF_ACL_RX_SIZE to 251 + "CONFIG_BT_BUF_ACL_RX_SIZE=251", + + #BT_L2CAP_TX_MTU = CONFIG_BT_L2CAP_TX_MTU + # so define CONFIG_BT_L2CAP_TX_MTU to 247 + "CONFIG_BT_L2CAP_TX_MTU=247", + ] + + #Define ZEPHYR to 1 to have the function MapErrorZephyr linked + defines += [ "__ZEPHYR__=1" ] + + # Now add our "system-header" include dirs + foreach(include_dir, bt_ble_include_dirs) { + cflags += [ "-isystem" + rebase_path(include_dir, root_build_dir) ] + } + } + + source_set(bt_ble_target_name) { + forward_variables_from(invoker, "*") + sources = [ + # SDK hook for ethermind + #"${nxp_sdk_build_root}/${nxp_sdk_name}/sdk_hook/btsnoop_pl.c", + #edgefast_bluetooth + "${nxp_sdk_build_root}/${nxp_sdk_name}/sdk_hook/littlefs_pl.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/bt_db_gen.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/common/addr.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/host/bt_pal_addr.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/host/bt_pal_adv.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/host/bt_pal_att.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/host/bt_pal_buf.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/host/bt_pal_conn.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/host/bt_pal_crypto.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/host/bt_pal_gatt.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/host/bt_pal_hci_core.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/host/bt_pal_id.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/host/bt_pal_l2cap.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/host/bt_pal_settings.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/host/bt_pal_smp.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/host/bt_pal_smp_null.c", + + #"${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/host/bt_pal_ecc.c", + #"${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/host/bt_pal_keys.c", + #"${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/host/bt_pal_keys_br.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/host/bt_pal_uuid.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/platform/bt_ble_platform.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/impl/ethermind/platform/bt_ble_settings.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/porting/atomic_c.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/porting/buf.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/porting/porting.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/porting/slist.c", + "${rt_sdk_root}/middleware/edgefast_bluetooth/source/porting/work_queue.c", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/export/extension/BT_common_pl.c", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/export/extension/aes_cmac_pl.c", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/export/extension/device_queue_pl.c", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/export/extension/sm_pl.c", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/export/extension/sm_ssp_pl.c", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/export/extension/smp_pl.c", + "${rt_sdk_root}/middleware/wireless/ethermind/port/osal/src/freertos/EM_serial.c", + "${rt_sdk_root}/middleware/wireless/ethermind/port/osal/src/freertos/EM_timer.c", + "${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux/bluetooth/BT_status_pl.c", + "${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux/bluetooth/BT_storage_pl.c", + "${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux/bluetooth/btsnoop_pl.c", + "${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux/bluetooth/ht_read_task_pl.c", + + #ethermind files + "${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux/bluetooth/sco_audio_pl.c", + "${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux/bluetooth/write_task_pl.c", + "${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux/ethal/ethal_config.c", + + #"${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux/bluetooth/littlefs_pl.c", + "${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux/ethal/ethal_debug.c", + + #"${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux/ethal/ethal_fops.c", + "${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux/ethal/ethal_os.c", + ] + + if (!defined(configs)) { + configs = [] + } + + # Relax warnings for third_party code. + configs += [ + ":${bt_ble_target_name}_warnings", + + # Dependencies required to have the rand32.cpp file building + # A dependency to is required therefore add a dependency to below components + "${chip_root}/src:includes", + "${nxp_sdk_build_root}/${nxp_sdk_name}:lwip_rt_config", + "${chip_root}/third_party/nlassert:nlassert_config", + ] + + if (!defined(deps)) { + deps = [] + } + + # Adding a dependency to platform_buildconfig to make sure that the file platform_buildconfig.h is generated first + # In fact depending on the build order, issue could happen if the file platform_buildconfig.h is not generated before building rand32.cpp + deps += [ "${chip_root}/src/platform:platform_buildconfig" ] + + if (!defined(public_configs)) { + public_configs = [] + } + + public_configs += [ ":${bt_ble_target_name}_config" ] + } +} diff --git a/third_party/nxp/rt_sdk/lwip/common/lwipopts_common.h b/third_party/nxp/rt_sdk/lwip/common/lwipopts_common.h new file mode 100644 index 00000000000000..0cd0675469cc49 --- /dev/null +++ b/third_party/nxp/rt_sdk/lwip/common/lwipopts_common.h @@ -0,0 +1,595 @@ +/* + * Copyright (c) 2020 Nest Labs, Inc. + * 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 + * Compile-time configuration for LwIP on NXP platforms using the + * NXP SDK. + * + */ + +#ifndef __LWIPOPTS_COMMON_H__ +#define __LWIPOPTS_COMMON_H__ + +#if CHIP_HAVE_CONFIG_H +#include +#endif + +#include + +#define LWIP_PROVIDE_ERRNO + +#ifndef CONFIG_NETWORK_HIGH_PERF +#define CONFIG_NETWORK_HIGH_PERF 1 +#endif + +#if USE_RTOS + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#define SYS_LIGHTWEIGHT_PROT 1 + +/** + * NO_SYS==0: Use RTOS + */ +#define NO_SYS 0 +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#define LWIP_NETCONN 1 +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#define LWIP_SOCKET 1 + +/** + * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and + * SO_RCVTIMEO processing. + */ +#define LWIP_SO_RCVTIMEO 1 + +#else +/** + * NO_SYS==1: Bare metal lwIP + */ +#define NO_SYS 1 +/** + * LWIP_NETCONN==0: Disable Netconn API (require to use api_lib.c) + */ +#define LWIP_NETCONN 0 +/** + * LWIP_SOCKET==0: Disable Socket API (require to use sockets.c) + */ +#define LWIP_SOCKET 0 + +#endif + +/* ---------- Multicast DNS options ---------- */ +/* Multicast DNS module */ +#ifndef LWIP_MDNS_RESPONDER +#define LWIP_MDNS_RESPONDER 1 +#endif + +/** + * The maximum number of services per netif + * recommended to be two times greater than number of matter fabrics supported + */ +#ifndef MDNS_MAX_SERVICES +#define MDNS_MAX_SERVICES 10 +#endif + +/* Search over multicast DNS module */ +#ifndef LWIP_MDNS_SEARCH +#define LWIP_MDNS_SEARCH 0 +#endif + +/* Provide strncasecmp to lwIP so it does not provide it's own lwip_strnicmp implementation along the strncasecmp from toolchain */ +#ifndef lwip_strnicmp +#define lwip_strnicmp strncasecmp +#endif + +/* ---------- Core locking ---------- */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define LWIP_TCPIP_CORE_LOCKING 1 + +void sys_lock_tcpip_core(void); +#define LOCK_TCPIP_CORE() sys_lock_tcpip_core() + +void sys_unlock_tcpip_core(void); +#define UNLOCK_TCPIP_CORE() sys_unlock_tcpip_core() + +// void sys_check_core_locking(void); +// #define LWIP_ASSERT_CORE_LOCKED() sys_check_core_locking() + +// void sys_mark_tcpip_thread(void); +// #define LWIP_MARK_TCPIP_THREAD() sys_mark_tcpip_thread() + +#ifdef __cplusplus +} +#endif + +#define LWIP_NETIF_HOSTNAME 1 + +/* ---------- Memory options ---------- */ +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#ifndef MEM_ALIGNMENT +#define MEM_ALIGNMENT 4 +#endif + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#ifndef MEM_SIZE +#define MEM_SIZE (22 * 1024) +#endif + +/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application + sends a lot of data out of ROM (or other static memory), this + should be set high. */ +#ifndef MEMP_NUM_PBUF +#if CONFIG_NETWORK_HIGH_PERF +#define MEMP_NUM_PBUF 30 +#else +#define MEMP_NUM_PBUF 15 +#endif +#endif + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_INPKT +#if CONFIG_NETWORK_HIGH_PERF +#define MEMP_NUM_TCPIP_MSG_INPKT 32 +#else +#define MEMP_NUM_TCPIP_MSG_INPKT 16 +#endif +#endif + +/** MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used + for sequential API communication and incoming packets. Used in + src/api/tcpip.c. */ +#ifndef MEMP_NUM_TCPIP_MSG_API +#if CONFIG_NETWORK_HIGH_PERF +#define MEMP_NUM_TCPIP_MSG_API 64 +#else +#define MEMP_NUM_TCPIP_MSG_API 16 +#endif +#endif + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETBUF +#if CONFIG_NETWORK_HIGH_PERF +#define MEMP_NUM_NETBUF 32 +#else +#define MEMP_NUM_NETBUF 16 +#endif +#endif + +/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + per active UDP "connection". */ +#ifndef MEMP_NUM_UDP_PCB +#define MEMP_NUM_UDP_PCB (6 + (LWIP_MDNS_RESPONDER)) +#endif +/* MEMP_NUM_TCP_PCB: the number of simultaneously active TCP + connections. */ +#ifndef MEMP_NUM_TCP_PCB +#define MEMP_NUM_TCP_PCB 10 +#endif +/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP + connections. */ +#ifndef MEMP_NUM_TCP_PCB_LISTEN +#define MEMP_NUM_TCP_PCB_LISTEN 6 +#endif +/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP + segments. */ +#ifndef MEMP_NUM_TCP_SEG +#if CONFIG_NETWORK_HIGH_PERF +#define MEMP_NUM_TCP_SEG 48 +#else +#define MEMP_NUM_TCP_SEG 22 +#endif +#endif +/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active + timeouts. */ +#ifndef MEMP_NUM_SYS_TIMEOUT +#define MEMP_NUM_SYS_TIMEOUT (10 + (7 * (LWIP_MDNS_RESPONDER))) +#endif + +/* ---------- Pbuf options ---------- */ +/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ +#ifndef PBUF_POOL_SIZE +#define PBUF_POOL_SIZE 40 +#endif + +/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ +/* Default value is defined in lwip\src\include\lwip\opt.h as + * LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN)*/ + +/* ---------- TCP options ---------- */ +#ifndef LWIP_TCP +#define LWIP_TCP 1 +#endif + +#ifndef TCP_TTL +#define TCP_TTL 255 +#endif + +/* Controls if TCP should queue segments that arrive out of + order. Define to 0 if your device is low on memory. */ +#ifndef TCP_QUEUE_OOSEQ +#define TCP_QUEUE_OOSEQ 0 +#endif + +/* TCP Maximum segment size. */ +#ifndef TCP_MSS +#define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */ +#endif + +/* TCP sender buffer space (bytes). */ +#ifndef TCP_SND_BUF +#if CONFIG_NETWORK_HIGH_PERF +#define TCP_SND_BUF (12 * TCP_MSS) +#else +#define TCP_SND_BUF (6 * TCP_MSS) +#endif +#endif + +/* TCP sender buffer space (pbufs). This must be at least = 2 * + TCP_SND_BUF/TCP_MSS for things to work. */ +#ifndef TCP_SND_QUEUELEN +#define TCP_SND_QUEUELEN (3 * TCP_SND_BUF) / TCP_MSS +#endif + +/* TCP receive window. */ +#ifndef TCP_WND +#if CONFIG_NETWORK_HIGH_PERF +#define TCP_WND (15 * TCP_MSS) +#else +#define TCP_WND (2 * TCP_MSS) +#endif +#endif + +/* Enable backlog*/ +#ifndef TCP_LISTEN_BACKLOG +#define TCP_LISTEN_BACKLOG 1 +#endif + +/* ---------- Network Interfaces options ---------- */ +/* Support netif api (in netifapi.c). */ +#ifndef LWIP_NETIF_API +#define LWIP_NETIF_API 1 +#endif + +/* Support an extended callback function + * for several netif related event that supports multiple subscribers. */ +#ifndef LWIP_NETIF_EXT_STATUS_CALLBACK +#define LWIP_NETIF_EXT_STATUS_CALLBACK 1 +#endif + +/* Number of clients that may store data in client_data member array of struct netif (max. 256). */ +#ifndef LWIP_NUM_NETIF_CLIENT_DATA +#define LWIP_NUM_NETIF_CLIENT_DATA (LWIP_MDNS_RESPONDER) +#endif + +/* ---------- ICMP options ---------- */ +#ifndef LWIP_ICMP +#define LWIP_ICMP 1 +#endif + +/* ---------- DHCP options ---------- */ +/* Enable DHCP module. */ +#ifndef LWIP_DHCP +#define LWIP_DHCP 1 +#endif + +/* ---------- IGMP options ---------- */ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#define LWIP_IGMP 1 + +/* ---------- UDP options ---------- */ +#ifndef LWIP_UDP +#define LWIP_UDP 1 +#endif +#ifndef UDP_TTL +#define UDP_TTL 255 +#endif + +/* ---------- Statistics options ---------- */ +#ifndef LWIP_STATS +#define LWIP_STATS 0 +#endif +#ifndef LWIP_PROVIDE_ERRNO +#define LWIP_PROVIDE_ERRNO 1 +#endif + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ + +/* +Some MCU allow computing and verifying the IP, UDP, TCP and ICMP checksums by hardware: + - To use this feature let the following define uncommented. + - To disable it and process by CPU comment the the checksum. +*/ +// #define CHECKSUM_BY_HARDWARE + +#ifdef CHECKSUM_BY_HARDWARE +/* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/ +#define CHECKSUM_GEN_IP 0 +/* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/ +#define CHECKSUM_GEN_UDP 0 +/* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/ +#define CHECKSUM_GEN_TCP 0 +/* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/ +#define CHECKSUM_CHECK_IP 0 +/* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/ +#define CHECKSUM_CHECK_UDP 0 +/* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/ +#define CHECKSUM_CHECK_TCP 0 +#else +/* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/ +#define CHECKSUM_GEN_IP 1 +/* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/ +#define CHECKSUM_GEN_UDP 1 +/* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/ +#define CHECKSUM_GEN_TCP 1 +/* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/ +#define CHECKSUM_CHECK_IP 1 +/* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/ +#define CHECKSUM_CHECK_UDP 1 +/* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/ +#define CHECKSUM_CHECK_TCP 1 +#endif + +/** + * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_STACKSIZE +#define DEFAULT_THREAD_STACKSIZE 3000 +#endif + +/** + * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_PRIO +#define DEFAULT_THREAD_PRIO 8 +#endif + +#define LWIP_TIMEVAL_PRIVATE (0) +#define LWIP_COMPAT_MUTEX (0) + +#define LWIP_SOCKET_SET_ERRNO 0 +#define IP_REASS_MAX_PBUFS 0 +#define IP_REASSEMBLY 0 +#define MEMP_NUM_REASSDATA 0 + +#define SO_REUSE (0) +#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS (0) + +#define TCP_QUEUE_OOSEQ 0 +#define ARP_QUEUEING (0) + +// TODO: seems like this is unnecessary on Thread-only platforms +#define LWIP_RAW 1 +#define MEMP_NUM_RAW_PCB (1) + +// TODO: verify count + +#define LWIP_HAVE_LOOPIF (0) + +// TODO: not sure why this is disabled +#define LWIP_NETIF_LOOPBACK (0) + +#ifndef MEMP_NUM_NETCONN +#define MEMP_NUM_NETCONN (0) +#endif + +#ifndef LWIP_IPV4 +#define LWIP_IPV4 0 +#endif +// LWIP IPV6 is mandatory to build matter application +#define LWIP_IPV6 1 +#define LWIP_ARP (1) +#ifndef LWIP_DNS +#define LWIP_DNS (1) +#endif + +#if LWIP_IPV6 +// #define LWIP_IPV6_REASS (0) +// #define LWIP_IPV6_DHCP6 0 +// #define LWIP_IPV6_AUTOCONFIG (1) +// #define LWIP_IPV6_ROUTER_SUPPORT 0 +// #define LWIP_ND6_LISTEN_RA 0 + +// #define LWIP_ND6_NUM_NEIGHBORS (0) +// #define LWIP_ND6_NUM_DESTINATIONS (0) +// #define LWIP_ND6_NUM_PREFIXES (0) +// #define LWIP_ND6_NUM_ROUTERS (0) +// #define LWIP_ND6_MAX_MULTICAST_SOLICIT (0) +// #define LWIP_ND6_MAX_UNICAST_SOLICIT (0) +// #define LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT (0) +// #define LWIP_ND6_TCP_REACHABILITY_HINTS (0) +#endif /* LWIP_IPV6 */ + +#define MEMP_SEPARATE_POOLS (0) +#define LWIP_PBUF_FROM_CUSTOM_POOLS (0) +#define MEMP_USE_CUSTOM_POOLS (0) + +#define MEM_LIBC_MALLOC 1 +#define mem_clib_malloc pvPortMalloc +#define mem_clib_free vPortFree + +#define mem_clib_calloc pvPortCalloc + +#define PBUF_CUSTOM_POOL_IDX_START (MEMP_NUM_PBUF) +#define PBUF_CUSTOM_POOL_IDX_END (MEMP_NUM_PBUF) + +#define ETH_PAD_SIZE (0) +#define SUB_ETHERNET_HEADER_SPACE (0) +#define PBUF_LINK_HLEN (14) + +#if LWIP_IPV6 +#define LWIP_IPV6_NUM_ADDRESSES 5 + +#define LWIP_IPV6_MLD 1 +#define LWIP_ND6_QUEUEING 0 +#define LWIP_IPV6_SCOPES 0 +#endif /* LWIP_IPV6 */ + +#define LWIP_MULTICAST_PING 0 + +#define LWIP_DNS_FOUND_CALLBACK_TYPE dns_found_callback + +// TODO: make LWIP_DEBUG conditional on build type + +#define MEMP_OVERFLOW_CHECK (0) +#define MEMP_SANITY_CHECK (0) +#define MDNS_DEBUG (LWIP_DBG_OFF) +#define MEM_DEBUG (LWIP_DBG_OFF) +#define MEMP_DEBUG (LWIP_DBG_OFF) +#define PBUF_DEBUG (LWIP_DBG_OFF) +#define API_LIB_DEBUG (LWIP_DBG_OFF) +#define API_MSG_DEBUG (LWIP_DBG_OFF) +#define TCPIP_DEBUG (LWIP_DBG_OFF) +#define NETIF_DEBUG (LWIP_DBG_OFF) +#define SOCKETS_DEBUG (LWIP_DBG_OFF) +#define DEMO_DEBUG (LWIP_DBG_OFF) +#define DHCP_DEBUG (LWIP_DBG_OFF) +#define AUTOIP_DEBUG (LWIP_DBG_OFF) +#define ETHARP_DEBUG (LWIP_DBG_OFF) +#define IP_DEBUG (LWIP_DBG_OFF) +#define IP_REASS_DEBUG (LWIP_DBG_OFF) +#define IP6_DEBUG (LWIP_DBG_OFF) +#define RAW_DEBUG (LWIP_DBG_OFF) +#define ICMP_DEBUG (LWIP_DBG_OFF) +#define UDP_DEBUG (LWIP_DBG_OFF) +#define TCP_DEBUG (LWIP_DBG_OFF) +#define TCP_INPUT_DEBUG (LWIP_DBG_OFF) +#define TCP_OUTPUT_DEBUG (LWIP_DBG_OFF) +#define TCP_RTO_DEBUG (LWIP_DBG_OFF) +#define TCP_CWND_DEBUG (LWIP_DBG_OFF) +#define TCP_WND_DEBUG (LWIP_DBG_OFF) +#define TCP_FR_DEBUG (LWIP_DBG_OFF) +#define TCP_QLEN_DEBUG (LWIP_DBG_OFF) +#define TCP_RST_DEBUG (LWIP_DBG_OFF) +#define PPP_DEBUG (LWIP_DBG_OFF) + +#define LWIP_DBG_TYPES_ON \ + (LWIP_DBG_ON | LWIP_DBG_TRACE) /* (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH|LWIP_DBG_HALT) */ + +/* + ------------------------------------ + ---------- Debugging options ---------- + ------------------------------------ +*/ + +#ifdef LWIP_DEBUG +#define U8_F "c" +#define S8_F "c" +#define X8_F "02x" +#define U16_F "u" +#define S16_F "d" +#define X16_F "x" +#define U32_F "u" +#define S32_F "d" +#define X32_F "x" +#define SZT_F "u" +#endif + +#ifndef TCPIP_MBOX_SIZE +#if CONFIG_NETWORK_HIGH_PERF +#define TCPIP_MBOX_SIZE 64 +#else +#define TCPIP_MBOX_SIZE 32 +#endif +#endif + +#define TCPIP_THREAD_STACKSIZE 1024 +#define TCPIP_THREAD_PRIO 8 + +/** + * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#define DEFAULT_RAW_RECVMBOX_SIZE 12 + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#define DEFAULT_UDP_RECVMBOX_SIZE 12 + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#define DEFAULT_TCP_RECVMBOX_SIZE 32 + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#define DEFAULT_ACCEPTMBOX_SIZE 12 + +#if (LWIP_DNS || LWIP_IGMP || LWIP_IPV6) && !defined(LWIP_RAND) +/* When using IGMP or IPv6, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value*/ +#include "lwip/arch.h" +u32_t lwip_rand(void); +#define LWIP_RAND() lwip_rand() +#endif + +/** + * DAC macro (initially defined in MIMXRT1176_cm7_features.h) must be undefined + * in the use case of RT1170 platform. + * This is due to DAC name being used by Matter, which causes a conflict + * resulting in a compilation failure. + */ +#ifdef MIMXRT1176_cm7_SERIES +#undef DAC +#endif + +#endif /* __LWIPOPTS_COMMON_H__ */ diff --git a/third_party/nxp/rt_sdk/lwip/common/lwippools.h b/third_party/nxp/rt_sdk/lwip/common/lwippools.h new file mode 100644 index 00000000000000..80a6e755709ec1 --- /dev/null +++ b/third_party/nxp/rt_sdk/lwip/common/lwippools.h @@ -0,0 +1,30 @@ +/* @file lwippools.h + * + * @brief This file contains custom LwIP memory pool definitions + * + * Copyright 2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __LWIPPOOLS_H__ +#define __LWIPPOOLS_H__ + +#ifdef MEMP_USE_CUSTOM_POOLS + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + +/* + * We explicitly move certain large LwIP memory pools to the custom defined + * .wlan_data section in (flash) memory to avoid memory overflow in the + * m_data section (RAM). + */ +extern unsigned char __attribute__((section(".wlan_data"))) memp_memory_PBUF_POOL_base[]; +extern unsigned char __attribute__((section(".wlan_data"))) memp_memory_TCP_PCB_POOL_base[]; + +#endif /* CHIP_DEVICE_CONFIG_ENABLE_WPA */ + +#endif /* MEMP_USE_CUSTOM_POOLS */ + +#endif /* __LWIPPOOLS_H__ */ diff --git a/third_party/nxp/rt_sdk/lwip/lwip.gni b/third_party/nxp/rt_sdk/lwip/lwip.gni new file mode 100644 index 00000000000000..22f9d64bb13f01 --- /dev/null +++ b/third_party/nxp/rt_sdk/lwip/lwip.gni @@ -0,0 +1,252 @@ +# 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. + +# Defines a lwIP build target. +# +# lwIP depends on external header files to compile. This template defines +# a combined build of the lwIP sources plus target configuration. +template("lwip_target") { + lwip_sdk_root = invoker.rt_sdk_root + + _lwip_root = "${lwip_sdk_root}/middleware/lwip" + + lwip_target_name = target_name + + # Apply overrides for lwIP features. + forward_variables_from(invoker, + [ + "lwip_ipv4", + "lwip_ipv6", + "lwip_api", + "lwip_ethernet", + "lwip_slip", + "lwip_6lowpan", + ]) + + if (!defined(lwip_ipv4)) { + lwip_ipv4 = true + } + if (!defined(lwip_ipv6)) { + lwip_ipv6 = true + } + if (!defined(lwip_api)) { + lwip_api = true + } + if (!defined(lwip_ethernet)) { + lwip_ethernet = true + } + if (!defined(lwip_slip)) { + lwip_slip = false + } + if (!defined(lwip_6lowpan)) { + lwip_6lowpan = false + } + + config("${lwip_target_name}_base_config") { + include_dirs = [ "${lwip_sdk_root}/middleware/lwip/src/include" ] + } + + source_set(lwip_target_name) { + forward_variables_from(invoker, + [ + "sources", + "public", + "public_configs", + "public_deps", + ]) + + # lwIP headers become empty if the relevant feature is disabled, so the + # whole interface can be public regardless of build options. + public += [ + "${_lwip_root}/src/include/lwip/acd.h", + "${_lwip_root}/src/include/lwip/altcp.h", + "${_lwip_root}/src/include/lwip/altcp_tcp.h", + "${_lwip_root}/src/include/lwip/altcp_tls.h", + "${_lwip_root}/src/include/lwip/api.h", + "${_lwip_root}/src/include/lwip/apps/mdns.h", + "${_lwip_root}/src/include/lwip/apps/mdns_domain.h", + "${_lwip_root}/src/include/lwip/apps/mdns_opts.h", + "${_lwip_root}/src/include/lwip/apps/mdns_out.h", + "${_lwip_root}/src/include/lwip/apps/mdns_priv.h", + "${_lwip_root}/src/include/lwip/arch.h", + "${_lwip_root}/src/include/lwip/autoip.h", + "${_lwip_root}/src/include/lwip/debug.h", + "${_lwip_root}/src/include/lwip/def.h", + "${_lwip_root}/src/include/lwip/dhcp.h", + "${_lwip_root}/src/include/lwip/dhcp6.h", + "${_lwip_root}/src/include/lwip/dns.h", + "${_lwip_root}/src/include/lwip/err.h", + "${_lwip_root}/src/include/lwip/errno.h", + "${_lwip_root}/src/include/lwip/etharp.h", + "${_lwip_root}/src/include/lwip/ethip6.h", + "${_lwip_root}/src/include/lwip/icmp.h", + "${_lwip_root}/src/include/lwip/icmp6.h", + "${_lwip_root}/src/include/lwip/if_api.h", + "${_lwip_root}/src/include/lwip/igmp.h", + "${_lwip_root}/src/include/lwip/inet.h", + "${_lwip_root}/src/include/lwip/inet_chksum.h", + "${_lwip_root}/src/include/lwip/init.h", + "${_lwip_root}/src/include/lwip/ip.h", + "${_lwip_root}/src/include/lwip/ip4.h", + "${_lwip_root}/src/include/lwip/ip4_addr.h", + "${_lwip_root}/src/include/lwip/ip4_frag.h", + "${_lwip_root}/src/include/lwip/ip6.h", + "${_lwip_root}/src/include/lwip/ip6_addr.h", + "${_lwip_root}/src/include/lwip/ip6_frag.h", + "${_lwip_root}/src/include/lwip/ip6_zone.h", + "${_lwip_root}/src/include/lwip/ip_addr.h", + "${_lwip_root}/src/include/lwip/mem.h", + "${_lwip_root}/src/include/lwip/memp.h", + "${_lwip_root}/src/include/lwip/mld6.h", + "${_lwip_root}/src/include/lwip/nd6.h", + "${_lwip_root}/src/include/lwip/netbuf.h", + "${_lwip_root}/src/include/lwip/netdb.h", + "${_lwip_root}/src/include/lwip/netif.h", + "${_lwip_root}/src/include/lwip/netifapi.h", + "${_lwip_root}/src/include/lwip/opt.h", + "${_lwip_root}/src/include/lwip/pbuf.h", + "${_lwip_root}/src/include/lwip/priv/tcp_priv.h", + "${_lwip_root}/src/include/lwip/priv/tcpip_priv.h", + "${_lwip_root}/src/include/lwip/prot/acd.h", + "${_lwip_root}/src/include/lwip/prot/autoip.h", + "${_lwip_root}/src/include/lwip/prot/dhcp.h", + "${_lwip_root}/src/include/lwip/prot/dhcp6.h", + "${_lwip_root}/src/include/lwip/prot/dns.h", + "${_lwip_root}/src/include/lwip/prot/etharp.h", + "${_lwip_root}/src/include/lwip/prot/ethernet.h", + "${_lwip_root}/src/include/lwip/prot/iana.h", + "${_lwip_root}/src/include/lwip/prot/icmp.h", + "${_lwip_root}/src/include/lwip/prot/icmp6.h", + "${_lwip_root}/src/include/lwip/prot/ieee.h", + "${_lwip_root}/src/include/lwip/prot/igmp.h", + "${_lwip_root}/src/include/lwip/prot/ip.h", + "${_lwip_root}/src/include/lwip/prot/ip4.h", + "${_lwip_root}/src/include/lwip/prot/ip6.h", + "${_lwip_root}/src/include/lwip/prot/mld6.h", + "${_lwip_root}/src/include/lwip/prot/nd6.h", + "${_lwip_root}/src/include/lwip/prot/tcp.h", + "${_lwip_root}/src/include/lwip/prot/udp.h", + "${_lwip_root}/src/include/lwip/raw.h", + "${_lwip_root}/src/include/lwip/sio.h", + "${_lwip_root}/src/include/lwip/snmp.h", + "${_lwip_root}/src/include/lwip/sockets.h", + "${_lwip_root}/src/include/lwip/stats.h", + "${_lwip_root}/src/include/lwip/sys.h", + "${_lwip_root}/src/include/lwip/tcp.h", + "${_lwip_root}/src/include/lwip/tcpbase.h", + "${_lwip_root}/src/include/lwip/tcpip.h", + "${_lwip_root}/src/include/lwip/timeouts.h", + "${_lwip_root}/src/include/lwip/udp.h", + ] + + sources += [ + "${_lwip_root}/src/apps/mdns/mdns.c", + "${_lwip_root}/src/apps/mdns/mdns_domain.c", + "${_lwip_root}/src/apps/mdns/mdns_out.c", + "${_lwip_root}/src/core/altcp.c", + "${_lwip_root}/src/core/altcp_alloc.c", + "${_lwip_root}/src/core/altcp_tcp.c", + "${_lwip_root}/src/core/def.c", + "${_lwip_root}/src/core/dns.c", + "${_lwip_root}/src/core/inet_chksum.c", + "${_lwip_root}/src/core/init.c", + "${_lwip_root}/src/core/ip.c", + "${_lwip_root}/src/core/mem.c", + "${_lwip_root}/src/core/memp.c", + "${_lwip_root}/src/core/netif.c", + "${_lwip_root}/src/core/pbuf.c", + "${_lwip_root}/src/core/raw.c", + "${_lwip_root}/src/core/stats.c", + "${_lwip_root}/src/core/sys.c", + "${_lwip_root}/src/core/tcp.c", + "${_lwip_root}/src/core/tcp_in.c", + "${_lwip_root}/src/core/tcp_out.c", + "${_lwip_root}/src/core/timeouts.c", + "${_lwip_root}/src/core/udp.c", + "${_lwip_root}/src/include/lwip/priv/altcp_priv.h", + "${_lwip_root}/src/include/lwip/priv/api_msg.h", + "${_lwip_root}/src/include/lwip/priv/api_msg.h", + "${_lwip_root}/src/include/lwip/priv/mem_priv.h", + "${_lwip_root}/src/include/lwip/priv/memp_priv.h", + "${_lwip_root}/src/include/lwip/priv/memp_std.h", + "${_lwip_root}/src/include/lwip/priv/nd6_priv.h", + "${_lwip_root}/src/include/lwip/priv/raw_priv.h", + "${_lwip_root}/src/include/lwip/priv/sockets_priv.h", + ] + + if (lwip_ipv4) { + sources += [ + "${_lwip_root}/src/core/ipv4/acd.c", + "${_lwip_root}/src/core/ipv4/autoip.c", + "${_lwip_root}/src/core/ipv4/dhcp.c", + "${_lwip_root}/src/core/ipv4/etharp.c", + "${_lwip_root}/src/core/ipv4/icmp.c", + "${_lwip_root}/src/core/ipv4/igmp.c", + "${_lwip_root}/src/core/ipv4/ip4.c", + "${_lwip_root}/src/core/ipv4/ip4_addr.c", + "${_lwip_root}/src/core/ipv4/ip4_frag.c", + ] + } + + if (lwip_ipv6) { + sources += [ + "${_lwip_root}/src/core/ipv6/dhcp6.c", + "${_lwip_root}/src/core/ipv6/ethip6.c", + "${_lwip_root}/src/core/ipv6/icmp6.c", + "${_lwip_root}/src/core/ipv6/inet6.c", + "${_lwip_root}/src/core/ipv6/ip6.c", + "${_lwip_root}/src/core/ipv6/ip6_addr.c", + "${_lwip_root}/src/core/ipv6/ip6_frag.c", + "${_lwip_root}/src/core/ipv6/mld6.c", + "${_lwip_root}/src/core/ipv6/nd6.c", + ] + } + + if (lwip_api) { + sources += [ + "${_lwip_root}/src/api/api_lib.c", + "${_lwip_root}/src/api/api_msg.c", + "${_lwip_root}/src/api/err.c", + "${_lwip_root}/src/api/if_api.c", + "${_lwip_root}/src/api/netbuf.c", + "${_lwip_root}/src/api/netdb.c", + "${_lwip_root}/src/api/netifapi.c", + "${_lwip_root}/src/api/sockets.c", + "${_lwip_root}/src/api/tcpip.c", + ] + } + + if (lwip_ethernet) { + sources += [ "${_lwip_root}/src/netif/ethernet.c" ] + } + + if (lwip_slip) { + sources += [ "${_lwip_root}/src/netif/slipif.c" ] + } + + if (lwip_6lowpan) { + sources += [ "${_lwip_root}/src/netif/lowpan6.c" ] + } + + if (defined(lwip_remove_configs)) { + configs -= lwip_remove_configs + } + if (defined(lwip_add_configs)) { + configs += lwip_add_configs + } + + public_configs += [ ":${lwip_target_name}_base_config" ] + } +} diff --git a/third_party/nxp/rt_sdk/lwip/openthread/lwipopts.h b/third_party/nxp/rt_sdk/lwip/openthread/lwipopts.h new file mode 100644 index 00000000000000..268b9fb6b21a11 --- /dev/null +++ b/third_party/nxp/rt_sdk/lwip/openthread/lwipopts.h @@ -0,0 +1,37 @@ +/* + * + * Copyright (c) 2020 Nest Labs, Inc. + * 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 + * Compile-time configuration for LwIP + */ + +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +#define CONFIG_NETWORK_HIGH_PERF 0 + +#define LWIP_DNS 0 +#define LWIP_IPV4 0 +#define PBUF_POOL_SIZE 20 +#define NETIF_MAX_HWADDR_LEN 8U + +#include "lwipopts_common.h" + +#endif /* __LWIPOPTS_H__ */ diff --git a/third_party/nxp/rt_sdk/lwip/wifi/lwipopts.h b/third_party/nxp/rt_sdk/lwip/wifi/lwipopts.h new file mode 100644 index 00000000000000..ba7d6ca0f199ae --- /dev/null +++ b/third_party/nxp/rt_sdk/lwip/wifi/lwipopts.h @@ -0,0 +1,31 @@ +/* + * + * Copyright (c) 2020 Nest Labs, Inc. + * 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 + * Compile-time configuration for LwIP + */ + +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +#define LWIP_IPV4 1 + +#include "lwipopts_common.h" + +#endif /* __LWIPOPTS_H__ */ diff --git a/third_party/nxp/rt_sdk/lwip/wifi_openthread/lwipopts.h b/third_party/nxp/rt_sdk/lwip/wifi_openthread/lwipopts.h new file mode 100644 index 00000000000000..92439d19d3e2ed --- /dev/null +++ b/third_party/nxp/rt_sdk/lwip/wifi_openthread/lwipopts.h @@ -0,0 +1,33 @@ +/* + * + * Copyright (c) 2020 Nest Labs, Inc. + * 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 + * Compile-time configuration for LwIP + */ + +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +#define LWIP_IPV4 1 +#define MEMP_NUM_NETCONN (4) +#define NETIF_MAX_HWADDR_LEN 8U + +#include "lwipopts_common.h" + +#endif /* __LWIPOPTS_H__ */ diff --git a/third_party/nxp/rt_sdk/mbedtls/config/matter_ksdk_mbedtls_config.h b/third_party/nxp/rt_sdk/mbedtls/config/matter_ksdk_mbedtls_config.h new file mode 100644 index 00000000000000..f5f3d61606b149 --- /dev/null +++ b/third_party/nxp/rt_sdk/mbedtls/config/matter_ksdk_mbedtls_config.h @@ -0,0 +1,16 @@ +/* + * Copyright 2022 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MATTER_MBEDTLS_CONFIG_H +#define MATTER_MBEDTLS_CONFIG_H + +/* SDK mbetdls config include */ +#include "ksdk_mbedtls_config.h" + +#undef MBEDTLS_FREESCALE_FREERTOS_CALLOC_ALT + +#endif // MATTER_MBEDTLS_CONFIG_H diff --git a/third_party/nxp/rt_sdk/mbedtls/mbedtls.gni b/third_party/nxp/rt_sdk/mbedtls/mbedtls.gni new file mode 100644 index 00000000000000..d5595ab2683f2b --- /dev/null +++ b/third_party/nxp/rt_sdk/mbedtls/mbedtls.gni @@ -0,0 +1,138 @@ +# Copyright (c) 2022 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. + +template("mbedtls_target") { + if (defined(invoker.rt_sdk_root)) { + rt_sdk_root = invoker.rt_sdk_root + } + + assert(rt_sdk_root != "", "rt_sdk_root must be specified") + mbedtls_sdk_root = rt_sdk_root + mbedtls_target_name = target_name + _mbedtls_root = "${mbedtls_sdk_root}/middleware/mbedtls" + + config("${mbedtls_target_name}_warnings") { + cflags = [ + "-Wno-maybe-uninitialized", + "-Wno-string-concatenation", + ] + } + + config("${mbedtls_target_name}_config") { + include_dirs = [ + "${_mbedtls_root}/include", + "${rt_sdk_root}/middleware/mbedtls/library", + ] + } + + static_library(mbedtls_target_name) { + forward_variables_from(invoker, "*") + if (!defined(sources)) { + sources = [] + } + sources += [ + "${_mbedtls_root}/library/aes.c", + "${_mbedtls_root}/library/aesni.c", + "${_mbedtls_root}/library/arc4.c", + "${_mbedtls_root}/library/asn1parse.c", + "${_mbedtls_root}/library/asn1write.c", + "${_mbedtls_root}/library/base64.c", + "${_mbedtls_root}/library/bignum.c", + "${_mbedtls_root}/library/blowfish.c", + "${_mbedtls_root}/library/camellia.c", + "${_mbedtls_root}/library/ccm.c", + "${_mbedtls_root}/library/certs.c", + "${_mbedtls_root}/library/chacha20.c", + "${_mbedtls_root}/library/chachapoly.c", + "${_mbedtls_root}/library/cipher.c", + "${_mbedtls_root}/library/cipher_wrap.c", + "${_mbedtls_root}/library/cmac.c", + "${_mbedtls_root}/library/constant_time.c", + "${_mbedtls_root}/library/ctr_drbg.c", + "${_mbedtls_root}/library/debug.c", + "${_mbedtls_root}/library/des.c", + "${_mbedtls_root}/library/dhm.c", + "${_mbedtls_root}/library/ecdh.c", + "${_mbedtls_root}/library/ecdsa.c", + "${_mbedtls_root}/library/ecjpake.c", + "${_mbedtls_root}/library/ecp.c", + "${_mbedtls_root}/library/ecp_curves.c", + "${_mbedtls_root}/library/entropy.c", + "${_mbedtls_root}/library/entropy_poll.c", + "${_mbedtls_root}/library/error.c", + "${_mbedtls_root}/library/gcm.c", + "${_mbedtls_root}/library/hkdf.c", + "${_mbedtls_root}/library/hmac_drbg.c", + "${_mbedtls_root}/library/md.c", + "${_mbedtls_root}/library/md5.c", + "${_mbedtls_root}/library/oid.c", + "${_mbedtls_root}/library/padlock.c", + "${_mbedtls_root}/library/pem.c", + "${_mbedtls_root}/library/pk.c", + "${_mbedtls_root}/library/pk_wrap.c", + "${_mbedtls_root}/library/pkcs12.c", + "${_mbedtls_root}/library/pkcs5.c", + "${_mbedtls_root}/library/pkparse.c", + "${_mbedtls_root}/library/pkwrite.c", + "${_mbedtls_root}/library/platform.c", + "${_mbedtls_root}/library/platform_util.c", + "${_mbedtls_root}/library/poly1305.c", + "${_mbedtls_root}/library/ripemd160.c", + "${_mbedtls_root}/library/rsa.c", + "${_mbedtls_root}/library/rsa_internal.c", + "${_mbedtls_root}/library/sha1.c", + "${_mbedtls_root}/library/sha256.c", + "${_mbedtls_root}/library/sha512.c", + "${_mbedtls_root}/library/ssl_cache.c", + "${_mbedtls_root}/library/ssl_ciphersuites.c", + "${_mbedtls_root}/library/ssl_cli.c", + "${_mbedtls_root}/library/ssl_cookie.c", + "${_mbedtls_root}/library/ssl_srv.c", + "${_mbedtls_root}/library/ssl_ticket.c", + "${_mbedtls_root}/library/ssl_tls.c", + "${_mbedtls_root}/library/threading.c", + "${_mbedtls_root}/library/version.c", + "${_mbedtls_root}/library/version_features.c", + "${_mbedtls_root}/library/x509.c", + "${_mbedtls_root}/library/x509_create.c", + "${_mbedtls_root}/library/x509_crl.c", + "${_mbedtls_root}/library/x509_crt.c", + "${_mbedtls_root}/library/x509_csr.c", + "${_mbedtls_root}/library/x509write_crt.c", + "${_mbedtls_root}/library/x509write_csr.c", + "${_mbedtls_root}/library/xtea.c", + ] + + if (current_os != "freertos") { + sources += [ "${_mbedtls_root}/library/timing.c" ] + } + + if (!defined(configs)) { + configs = [] + } + + # Relax warnings for third_party code. + configs += [ ":${mbedtls_target_name}_warnings" ] + + if (!defined(public_configs)) { + public_configs = [] + } + + public_configs += [ ":${mbedtls_target_name}_config" ] + + output_name = "lib${mbedtls_target_name}" + output_dir = "${root_out_dir}/lib" + } +} diff --git a/third_party/nxp/rt_sdk/nxp_arm.gni b/third_party/nxp/rt_sdk/nxp_arm.gni new file mode 100644 index 00000000000000..560b076ef57a0d --- /dev/null +++ b/third_party/nxp/rt_sdk/nxp_arm.gni @@ -0,0 +1,34 @@ +# 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/nxp_sdk.gni") +import("${nxp_sdk_build_root}/nxp_sdk.gni") + +assert(nxp_platform == "rt/rt1060" || nxp_platform == "rt/rt1170" || + nxp_platform == "rt/rw61x", + "${nxp_platform} must be one of: rt/rt1060, rt/rt1170, rt/rw61x.") + +if (nxp_platform == "rt/rt1060" || nxp_platform == "rt/rt1170") { + arm_arch = "armv7e-m" + arm_abi = "aapcs" + arm_cpu = "cortex-m7" + arm_fpu = "fpv5-d16" + arm_float_abi = "hard" +} else if (nxp_platform == "rt/rw61x") { + arm_arch = "armv8-m.main" + arm_abi = "aapcs" + arm_cpu = "cortex-m33+nodsp" + arm_fpu = "fpv5-sp-d16" + arm_float_abi = "hard" +} diff --git a/third_party/nxp/rt_sdk/nxp_executable.gni b/third_party/nxp/rt_sdk/nxp_executable.gni new file mode 100644 index 00000000000000..2acfe190a2d960 --- /dev/null +++ b/third_party/nxp/rt_sdk/nxp_executable.gni @@ -0,0 +1,34 @@ +# 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") + +import("${build_root}/toolchain/flashable_executable.gni") + +template("rt_executable") { + output_base_name = get_path_info(invoker.output_name, "name") + objcopy_image_name = output_base_name + ".hex" + objcopy_image_format = "srec" + objcopy = "arm-none-eabi-objcopy" + + # Copy flashing dependencies to the output directory so that the output + # is collectively self-contained; this allows flashing to work reliably + # even if the build and flashing steps take place on different machines + # or in different containers. + + flashable_executable(target_name) { + forward_variables_from(invoker, "*") + } +} diff --git a/third_party/nxp/rt_sdk/rt_executable.gni b/third_party/nxp/rt_sdk/rt_executable.gni new file mode 100644 index 00000000000000..2acfe190a2d960 --- /dev/null +++ b/third_party/nxp/rt_sdk/rt_executable.gni @@ -0,0 +1,34 @@ +# 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") + +import("${build_root}/toolchain/flashable_executable.gni") + +template("rt_executable") { + output_base_name = get_path_info(invoker.output_name, "name") + objcopy_image_name = output_base_name + ".hex" + objcopy_image_format = "srec" + objcopy = "arm-none-eabi-objcopy" + + # Copy flashing dependencies to the output directory so that the output + # is collectively self-contained; this allows flashing to work reliably + # even if the build and flashing steps take place on different machines + # or in different containers. + + flashable_executable(target_name) { + forward_variables_from(invoker, "*") + } +} diff --git a/third_party/nxp/rt_sdk/rt_sdk.gni b/third_party/nxp/rt_sdk/rt_sdk.gni new file mode 100644 index 00000000000000..20cffacc1a150e --- /dev/null +++ b/third_party/nxp/rt_sdk/rt_sdk.gni @@ -0,0 +1,648 @@ +# 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/chip.gni") +import("//build_overrides/openthread.gni") + +import("${chip_root}/src/platform/device.gni") # declares chip_enable_wifi +import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") # declares all + # rt local + # args +import("${nxp_sdk_build_root}/nxp_sdk.gni") # declares some sdk args such as + # chip_with_ot_cli + +declare_args() { + # Location of the rt SDK. + rt_sdk_root = "${chip_root}/third_party/nxp/rt_sdk/repo" + + # Enables Matter over Ethernet support + chip_enable_ethernet = false + + # transceiver lists + iw416_transceiver = false + k32w0_transceiver = false + k32w0_transceiver_bin_path = rebase_path( + "${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") + w8801_transceiver = false + iwx12_transceiver = false + + # Enables hci and spinel communication on single UART + # Could be used only if k32w0_transceiver is enabled + hci_spinel_single_uart = false + + # Allows to enable OTW logs to see + # firmware download logs for K32W0 transceiver + otw_logs_enabled = false + + # Defines the RT NVM component supported + rt_nvm_component = "littlefs" + + #rt_nvm_component = "key_storage" + + # Enable wifi PTA support + wifi_enable_pta = false + + # RT platform name + rt_platform = "" + + # Support or not assert component from the SDK + sdk_fsl_assert_support = true + + # Defines the name of the nxp SDK target instance + nxp_sdk_target = "" + + # Defines the name of the nxp SDK driver target instance + nxp_sdk_driver_target = "" + + # Enables Watchdog support + use_watchdog = 0 +} + +declare_args() { + rt_core_sdk_root = "${rt_sdk_root}/core" +} + +if (is_sdk_package || is_sdk_internal) { + rt_core_sdk_root = getenv("NXP_SDK_ROOT") + rt_sdk_root = getenv("NXP_SDK_ROOT") +} + +if (!defined(rt_fwk_platform)) { + rt_fwk_platform = rt_platform +} + +assert(rt_sdk_root != "", "rt_sdk_root must be specified") + +rt_sdk_freertos_kernel = "${rt_sdk_root}/rtos/freertos/freertos-kernel" + +template("rt_transceiver") { + config("${target_name}_config") { + include_dirs = [] + _transceiver_include_dirs = [] + + if (defined(invoker.include_dirs)) { + include_dirs += invoker.include_dirs + } + + if (iw416_transceiver || w8801_transceiver || iwx12_transceiver) { + _transceiver_include_dirs += [ + # Transceiver files + "${rt_sdk_root}/middleware/wifi_nxp/wifi_bt_firmware", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver", + "${rt_sdk_root}/middleware/sdmmc/common", + "${rt_sdk_root}/middleware/sdmmc/sdio", + "${rt_sdk_root}/middleware/sdmmc/host/usdhc", + "${rt_sdk_root}/middleware/sdmmc/osa", + "${rt_sdk_root}/middleware/wifi_nxp/incl/wifidriver", + "${rt_sdk_root}/middleware/wifi_nxp/incl", + "${rt_sdk_root}/middleware/wifi_nxp/incl/wlcmgr", + "${rt_sdk_root}/middleware/wifi_nxp/incl/port/os", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/incl", + ] + } + + libs = [] + + if (defined(invoker.defines)) { + defines += invoker.defines + } + + cflags = [] + + if (defined(invoker.cflags)) { + cflags += invoker.cflags + } + + # Now add our "system-header" include dirs + foreach(include_dir, _transceiver_include_dirs) { + cflags += [ "-isystem" + rebase_path(include_dir, root_build_dir) ] + } + } + + source_set(target_name) { + forward_variables_from(invoker, "*") + + if (!defined(sources)) { + sources = [] + } + + if (iw416_transceiver || w8801_transceiver || iwx12_transceiver) { + sources += [ + # Transceiver files + "${rt_sdk_root}/middleware/sdmmc/common/fsl_sdmmc_common.c", + "${rt_sdk_root}/middleware/sdmmc/host/usdhc/non_blocking/fsl_sdmmc_host.c", + "${rt_sdk_root}/middleware/sdmmc/osa/fsl_sdmmc_osa.c", + "${rt_sdk_root}/middleware/sdmmc/sdio/fsl_sdio.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/firmware_dnld.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_sdio.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/sdio.c", + ] + } + + if (!defined(public_configs)) { + public_configs = [] + } + + public_configs += [ ":${target_name}_config" ] + } +} + +template("rt_wifi") { + config("${target_name}_config") { + include_dirs = [] + + if (defined(invoker.include_dirs)) { + include_dirs += invoker.include_dirs + } + + _wifi_include_dirs = [ + # Wi-Fi + "${rt_sdk_root}/middleware/wifi_nxp/incl/port/lwip", + "${rt_sdk_root}/middleware/wifi_nxp/port/lwip", + "${rt_sdk_root}/middleware/wifi_nxp/incl", + "${rt_sdk_root}/middleware/wifi_nxp/incl/port/os", + "${rt_sdk_root}/middleware/wifi_nxp/incl/wifidriver", + "${rt_sdk_root}/middleware/wifi_nxp/incl/wlcmgr", + "${rt_sdk_root}/middleware/wifi_nxp/wifi_bt_firmware", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/incl", + ] + + libs = [] + + if (defined(invoker.defines)) { + defines += invoker.defines + } else { + defines = [] + } + + defines += [ + "CHIP_DEVICE_CONFIG_ENABLE_WPA", + "CONFIG_IPV6=1", # missing in wifi_config.h + "CONFIG_MAX_IPV6_ADDRESSES=5", # missing in wifi_config.h + ] + + if (wifi_enable_pta) { + defines += [ "WIFI_PTA_ENABLED=1" ] + } + + cflags = [] + + if (defined(invoker.cflags)) { + cflags += invoker.cflags + } + + # Now add our "system-header" include dirs + foreach(include_dir, _wifi_include_dirs) { + cflags += [ "-isystem" + rebase_path(include_dir, root_build_dir) ] + } + } + + source_set(target_name) { + forward_variables_from(invoker, "*") + + if (!defined(sources)) { + sources = [] + } + + sources += [ + # Wi-Fi + "${rt_sdk_root}/middleware/wifi_nxp/cli/cli_utils.c", + "${rt_sdk_root}/middleware/wifi_nxp/dhcpd/dhcp-server-main.c", + "${rt_sdk_root}/middleware/wifi_nxp/dhcpd/dhcp-server.c", + "${rt_sdk_root}/middleware/wifi_nxp/dhcpd/dns-server.c", + "${rt_sdk_root}/middleware/wifi_nxp/port/lwip/net.c", + "${rt_sdk_root}/middleware/wifi_nxp/port/lwip/wifi_netif.c", + "${rt_sdk_root}/middleware/wifi_nxp/port/os/os.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_11ac.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_11d.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_11h.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_11n.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_11n_aggr.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_11n_rxreorder.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_api.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_cfp.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_cmdevt.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_glue.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_init.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_join.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_misc.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_scan.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_shim.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_sta_cmd.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_sta_cmdresp.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_sta_event.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_sta_ioctl.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_sta_rx.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_txrx.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_uap_cmdevent.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_uap_ioctl.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_wmm.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/wifi-debug.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/wifi-mem.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/wifi-uap.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/wifi.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/wifi_pwrmgr.c", + "${rt_sdk_root}/middleware/wifi_nxp/wlcmgr/wlan.c", + "${rt_sdk_root}/middleware/wifi_nxp/wlcmgr/wlan_txpwrlimit_cfg.c", + ] + + if (!defined(public_configs)) { + public_configs = [] + } + + public_configs += [ ":${target_name}_config" ] + } +} + +template("rt_sdk") { + sdk_target_name = target_name + + config("${sdk_target_name}_config") { + include_dirs = [] + + if (defined(invoker.include_dirs)) { + include_dirs += invoker.include_dirs + } + + # We want to treat SDK headers as system headers, so that warnings in those + # headers are not fatal. Therefore don't add them directly to include_dirs; + # we will add them to cflags below instead. + _sdk_include_dirs = [ + #freertos includes + "${rt_sdk_freertos_kernel}/include", + + #CMSIS includes + "${rt_core_sdk_root}/CMSIS/Core/Include", + + #SDK components + "${rt_core_sdk_root}/components/uart", + "${rt_core_sdk_root}/components/spi", + "${rt_core_sdk_root}/components/serial_manager", + "${rt_core_sdk_root}/components/lists", + "${rt_core_sdk_root}/components/osa", + "${rt_core_sdk_root}/components/common_task", + "${rt_core_sdk_root}/components/log", + "${rt_core_sdk_root}/components/timer_manager", + "${rt_core_sdk_root}/components/timer", + "${rt_core_sdk_root}/components/internal_flash", + "${rt_core_sdk_root}/components/button", + "${rt_core_sdk_root}/components/gpio", + "${rt_core_sdk_root}/components/phy/device/phyksz8081", + "${rt_core_sdk_root}/components/phy", + "${rt_core_sdk_root}/components/wifi_bt_module/AzureWave/tx_pwr_limits", + "${rt_core_sdk_root}/components/wifi_bt_module/Murata/tx_pwr_limits", + "${rt_core_sdk_root}/components/wifi_bt_module/template", + "${rt_core_sdk_root}/components/messaging", + "${rt_core_sdk_root}/components/mem_manager", + "${rt_core_sdk_root}/components/flash/mflash", + "${rt_core_sdk_root}/components/time_stamp", + + #Framework files + "${rt_sdk_root}/middleware/wireless/framework/FunctionLib", + "${rt_sdk_root}/middleware/wireless/framework/Common", + "${rt_sdk_root}/middleware/wireless/framework/platform/${rt_fwk_platform}", + "${rt_sdk_root}/middleware/wireless/framework/platform/include", + "${rt_sdk_root}/middleware/wireless/framework/FileSystem", + "${rt_sdk_root}/middleware/wireless/framework/FileCache", + "${rt_sdk_root}/middleware/wireless/framework/FSAbstraction", + "${rt_sdk_root}/middleware/wireless/framework/KeyStorage", + + #littlefs + "${rt_sdk_root}/middleware/littlefs", + ] + + #OtaSupport + if (chip_enable_ota_requestor) { + _sdk_include_dirs += [ + "${rt_sdk_root}/middleware/wireless/framework/OtaSupport/Interface", + "${rt_sdk_root}/middleware/wireless/framework/OtaSupport/Source", + ] + } + + if (rt_nvm_component == "nvm_fwk") { + _sdk_include_dirs += + [ "${rt_sdk_root}/middleware/wireless/framework/NVM/Interface" ] + } + + libs = [] + + defines = [ + "__STARTUP_CLEAR_BSS", + "__STARTUP_INITIALIZE_NONCACHEDATA", + "__STARTUP_INITIALIZE_RAMFUNCTION", + + #"SERIAL_MANAGER_NON_BLOCKING_MODE=1", + "SERIAL_MANAGER_TASK_HANDLE_RX_AVAILABLE_NOTIFY=1", + "SERIAL_MANAGER_RING_BUFFER_FLOWCONTROL=1", + "SDK_OS_FREE_RTOS", + + #Enable the OSA startup task + "OSA_USED", + "FSL_OSA_TASK_ENABLE", + + #Startup task stack size todo :to remove + "gMainThreadStackSize_c=4096", + "XIP_EXTERNAL_FLASH=1", + "XIP_BOOT_HEADER_ENABLE=1", + "FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL=1", + "SDK_COMPONENT_INTEGRATION=1", + "FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ=0", + + # Serial Manager already in Non blocking state by default + # but can be changed with other compile switch (DEBUG_CONSOLE_TRANSFER_NON_BLOCKING), + # so better to explicitly set to 1 here except when DEBUG_CONSOLE_TRANSFER_NON_BLOCKING is set + # "SERIAL_MANAGER_NON_BLOCKING_MODE=1", + # For Debug Console, This flag is not use for Debug Console Light + "DEBUG_CONSOLE_TRANSFER_NON_BLOCKING", + "HAL_UART_ADAPTER_FIFO=1", + "SDK_DEBUGCONSOLE_UART=1", + "SERIAL_PORT_TYPE_UART=1", + "CONFIG_ARM=1", + "SERIAL_MANAGER_TASK_STACK_SIZE=4048", + + #LWIP common options + "USE_RTOS=1", + "BUTTON_SHORT_PRESS_THRESHOLD=500", + "BUTTON_LONG_PRESS_THRESHOLD=2000", + + #Multithread tests + "PRINTF_ADVANCED_ENABLE=1", + ] + + if (rt_platform != "rw61x") { + # This adds a temporary workakound to fix mbdetls concurrent access to crypto hardware + defines += [ "RT_MATTER_SUPPORT" ] + } + + if (use_watchdog != 0) { + defines += [ "WATCHDOG_ALLOWED" ] + } + + if (rt_nvm_component == "nvm_fwk") { + defines += [ + #NVM flags + "gNvStorageIncluded_d=1", + "gNvTableKeptInRam_d=1", + "NVM_NO_COMPONNET=1", + ] + } + + if (rt_nvm_component == "littlefs" || rt_nvm_component == "key_storage") { + defines += [ + "LFS_THREADSAFE=1", + "LFS_NO_DEBUG", + "LFS_NO_ERROR", + "LFS_NO_WARN", + ] + } + + if (chip_enable_wifi || chip_enable_ethernet) { + defines += [ + "SDK_DEBUGCONSOLE=1", + "MCUXPRESSO_SDK", + "PRINTF_FLOAT_ENABLE=0", + "DEBUG", + "__GCC", + "__USE_CMSIS", + "PRINT_FLOAT_ENABLE=0", + "CR_INTEGER_PRINTF", + + # No OSA main task + "FSL_OSA_MAIN_FUNC_ENABLE=0", + ] + } + + if (chip_enable_ethernet) { + defines += [ "FSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE" ] + } + + if (chip_enable_pairing_autostart == 1) { + defines += [ "CHIP_DEVICE_CONFIG_ENABLE_PAIRING_AUTOSTART=1" ] + } else { + defines += [ "CHIP_DEVICE_CONFIG_ENABLE_PAIRING_AUTOSTART=0" ] + } + + if (iw416_transceiver) { + defines += [ + "WIFI_IW416_BOARD_AW_AM510_USD", + "SDIO_ENABLED", + ] + } + + if (w8801_transceiver) { + defines += [ + "WIFI_88W8801_BOARD_MURATA_2DS_USD", + "SDIO_ENABLED", + ] + } + + if (iwx12_transceiver) { + defines += [ + "WIFI_IW61x_BOARD_RD_USD", + "SDIO_ENABLED", + ] + } + + if (k32w0_transceiver) { + defines += [ "K32W061_TRANSCEIVER" ] + defines += [ "BOARD_OTW_K32W0_PIN_INIT" ] + + #Framework OTW defines to locate transceiver binary header + defines += [ "K32W0_RCP_BINARY_H_FILE=\"${k32w0_transceiver_bin_path}\"" ] + + #SDK defines for OTW + defines += [ "HAL_UART_DMA_ENABLE=1" ] + _sdk_include_dirs += + [ "${rt_sdk_root}/middleware/wireless/framework/OTW/Interface" ] + if (otw_logs_enabled) { + defines += [ "OTW_LOG_ENABLED=1" ] + } + } + + if (nxp_software_version != "") { + defines += + [ "NXP_CONFIG_DEVICE_SOFTWARE_VERSION=${nxp_software_version}" ] + } + + if (nxp_software_version_string != "") { + defines += [ "NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING=\"${nxp_software_version_string}\"" ] + } + + if (defined(invoker.defines)) { + defines += invoker.defines + } + cflags = [] + + if (defined(invoker.cflags)) { + cflags += invoker.cflags + } + + cflags += [ + "-Wno-unused-function", + "-Wno-conversion", + "-Wno-sign-compare", + "-Wno-shadow", + "-Wno-empty-body", + "-Wno-implicit-fallthrough", + "-Wno-stringop-truncation", + "-Wno-unused-variable", + "-Wno-format-truncation", + ] + + if (chip_enable_openthread) { + defines += [ "CHIP_DEVICE_CONFIG_ENABLE_THREAD=1" ] + } + + if (chip_enable_ble) { + defines += [ "CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE=1" ] + } + + if (chip_enable_wifi) { + if (!w8801_transceiver) { + defines += [ "CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION=1" ] + } else { + defines += [ "CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION=0" ] + } + } + + # Now add our "system-header" include dirs + foreach(include_dir, _sdk_include_dirs) { + cflags += [ "-isystem" + rebase_path(include_dir, root_build_dir) ] + } + + #Adding pre-include files + cflags += [ "-include" + rebase_path( + "${nxp_sdk_build_root}/${nxp_sdk_name}/transceiver/app_transceiver_config.h", + root_build_dir) ] + } + + # TODO - Break up this monolith and make it configurable. + source_set(sdk_target_name) { + forward_variables_from(invoker, "*") + + if (!defined(sources)) { + sources = [] + } + + sources += [ + #freertos files + "${rt_sdk_freertos_kernel}/croutine.c", + "${rt_sdk_freertos_kernel}/event_groups.c", + "${rt_sdk_freertos_kernel}/list.c", + "${rt_sdk_freertos_kernel}/queue.c", + "${rt_sdk_freertos_kernel}/stream_buffer.c", + "${rt_sdk_freertos_kernel}/tasks.c", + "${rt_sdk_freertos_kernel}/timers.c", + + #SDK components + "${rt_core_sdk_root}/components/button/fsl_component_button.c", + "${rt_core_sdk_root}/components/lists/fsl_component_generic_list.c", + "${rt_core_sdk_root}/components/log/fsl_component_log.c", + "${rt_core_sdk_root}/components/log/fsl_component_log_backend_debugconsole.c", + "${rt_core_sdk_root}/components/messaging/fsl_component_messaging.c", + "${rt_core_sdk_root}/components/osa/fsl_os_abstraction_free_rtos.c", + "${rt_core_sdk_root}/components/phy/device/phyksz8081/fsl_phyksz8081.c", + "${rt_core_sdk_root}/components/serial_manager/fsl_component_serial_manager.c", + "${rt_core_sdk_root}/components/serial_manager/fsl_component_serial_port_uart.c", + "${rt_core_sdk_root}/components/timer_manager/fsl_component_timer_manager.c", + + #Framework files + "${rt_sdk_root}/middleware/wireless/framework/FunctionLib/FunctionLib.c", + ] + + #OtaSupport files + if (chip_enable_ota_requestor) { + sources += [ + "${rt_sdk_root}/middleware/wireless/framework/OtaSupport/Source/OtaExternalFlash.c", + "${rt_sdk_root}/middleware/wireless/framework/OtaSupport/Source/OtaPrivate.h", + "${rt_sdk_root}/middleware/wireless/framework/OtaSupport/Source/OtaSupport.c", + "${rt_sdk_root}/middleware/wireless/framework/platform/${rt_fwk_platform}/fwk_platform_extflash.c", + "${rt_sdk_root}/middleware/wireless/framework/platform/${rt_fwk_platform}/fwk_platform_ota.c", + ] + } + + if (rt_nvm_component == "nvm_fwk") { + sources += [ + "${rt_sdk_root}/middleware/wireless/framework/FileSystem/fwk_filesystem.c", + "${rt_sdk_root}/middleware/wireless/framework/NVM/Source/NV_Flash.c", + "${rt_sdk_root}/middleware/wireless/framework/platform/${rt_fwk_platform}/fwk_platform_flash.c", + ] + } + + if (rt_nvm_component == "key_storage") { + sources += [ + "${rt_sdk_root}/middleware/wireless/framework/FSAbstraction/fwk_fs_abstraction.c", + "${rt_sdk_root}/middleware/wireless/framework/FSAbstraction/fwk_lfs_mflash.c", + "${rt_sdk_root}/middleware/wireless/framework/FileCache/fwk_file_cache.c", + "${rt_sdk_root}/middleware/wireless/framework/KeyStorage/fwk_key_storage.c", + ] + } + + if (rt_nvm_component == "littlefs") { + sources += [ + "${rt_sdk_root}/middleware/wireless/framework/FileSystem/fwk_filesystem.c", + "${rt_sdk_root}/middleware/wireless/framework/platform/${rt_fwk_platform}/fwk_platform_flash.c", + ] + sources += [ + #littlefs + "${rt_sdk_root}/middleware/littlefs/lfs.c", + "${rt_sdk_root}/middleware/littlefs/lfs_util.c", + ] + } + + if (iwx12_transceiver) { + sources += [ "${rt_sdk_root}/middleware/wireless/framework/platform/imx_rt/iw612/fwk_platform_coex.c" ] + } + + if (k32w0_transceiver) { + sources += [ + "${rt_sdk_root}/middleware/wireless/framework/OTW/k32w0_transceiver/fwk_otw.c", + "${rt_sdk_root}/middleware/wireless/framework/platform/imx_rt/k32w0/fwk_platform_coex.c", + ] + } + + if (!defined(public_configs)) { + public_configs = [] + } + + if (!defined(public_deps)) { + public_deps = [] + } + + public_configs += [ ":${sdk_target_name}_config" ] + + public_configs += + [ "${nxp_sdk_build_root}/${nxp_sdk_name}:nxp_transceiver_config" ] + + public_configs += [ + "${nxp_sdk_build_root}/${nxp_sdk_name}:nxp_lwip_base_config", + "${nxp_sdk_build_root}/${nxp_sdk_name}:lwip_rt_config", + ] + + public_configs += [ "" + nxp_sdk_driver_target + "_config" ] + + if (chip_enable_ble) { + public_configs += + [ "${nxp_sdk_build_root}/${nxp_sdk_name}:nxp_bt_ble_config" ] + } + if (chip_enable_wifi) { + public_configs += + [ "${nxp_sdk_build_root}/${nxp_sdk_name}:nxp_wifi_config" ] + } + + all_dependent_configs = public_configs + } +} diff --git a/third_party/nxp/rt_sdk/rw61x/BUILD.gn b/third_party/nxp/rt_sdk/rw61x/BUILD.gn new file mode 100644 index 00000000000000..007d83ee40c036 --- /dev/null +++ b/third_party/nxp/rt_sdk/rw61x/BUILD.gn @@ -0,0 +1,53 @@ +# Copyright (c) 2022 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/nxp_sdk.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}/${nxp_sdk_name}.gni") + +#allows to get common NXP SDK gn options +import("${nxp_sdk_build_root}/nxp_sdk.gni") +group("nxp_mbedtls") { + public_deps = [] + + # mbedtls port + if (rw610_mbedtls_port_els_pkc) { + public_deps += + [ "${nxp_sdk_build_root}/${nxp_sdk_name}:nxp_els_pkc_mbedtls" ] + } else { + public_deps += [ "${nxp_sdk_build_root}/${nxp_sdk_name}:nxp_ksdk_mbedtls" ] + } +} + +group("nxp_sdk_mbedtls_config") { + public_configs = [] + + # mbedtls port + if (rw610_mbedtls_port_els_pkc) { + public_configs += + [ "${nxp_sdk_build_root}/${nxp_sdk_name}:nxp_els_pkc_mbedtls_config" ] + public_configs += + [ "${nxp_sdk_build_root}/${nxp_sdk_name}:mbedtls_els_pkc_config" ] + } else { + public_configs += + [ "${nxp_sdk_build_root}/${nxp_sdk_name}:nxp_ksdk_mbedtls_config" ] + public_configs += + [ "${nxp_sdk_build_root}/${nxp_sdk_name}:mbedtls_ksdk_config" ] + } +} diff --git a/third_party/nxp/rt_sdk/rw61x/rw61x.gni b/third_party/nxp/rt_sdk/rw61x/rw61x.gni new file mode 100644 index 00000000000000..24251d3a6def36 --- /dev/null +++ b/third_party/nxp/rt_sdk/rw61x/rw61x.gni @@ -0,0 +1,686 @@ +# Copyright (c) 2022 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/nxp_sdk.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") +declare_args() { + board_version = "A1" + deviceBoardName = "RW612" + cpu1_cpu2_fw_type = "sb" +} + +if (is_sdk_internal) { + DRIVER_FILES_PATH = "${rt_sdk_root}/platform/drivers" + UTILITIES_FILES_PATH = "${rt_sdk_root}/platform/utilities" +} else { + if (!is_sdk_package) { + # sdk github is used (default sdk type) # + DRIVER_FILES_PATH = "${rt_core_sdk_root}/drivers" + UTILITIES_FILES_PATH = "${rt_core_sdk_root}/utilities" + } +} + +if (is_sdk_package) { + COMPONENT_FILES_PATH = "${rt_sdk_root}/components" + DRIVER_FILES_PATH = "${rt_sdk_root}/devices/${deviceBoardName}/drivers" + DRIVER_USART_FILES_PATH = "${DRIVER_FILES_PATH}" + DRIVER_DMA_FILES_PATH = "${DRIVER_FILES_PATH}" + DRIVER_MRT_FILES_PATH = "${DRIVER_FILES_PATH}" + DRIVER_TRNG_FILES_PATH = "${DRIVER_FILES_PATH}" + DRIVER_FLEXSPI_FILES_PATH = "${DRIVER_FILES_PATH}" + DRIVER_LPC_GPIO_FILES_PATH = "${DRIVER_FILES_PATH}" + DRIVER_ENET_FILES_PATH = "${DRIVER_FILES_PATH}" + DRIVER_DCP_FILES_PATH = "${DRIVER_FILES_PATH}" + DRIVER_CACHE_FILES_PATH = "${DRIVER_FILES_PATH}" + DRIVER_COMMON_FILES_PATH = "${DRIVER_FILES_PATH}" + DRIVER_DEVICE_FILES_PATH = "${DRIVER_FILES_PATH}" + DRIVER_FLEXCOMM_FILES_PATH = "${DRIVER_FILES_PATH}" + DRIVER_IMU_FILES_PATH = "${DRIVER_FILES_PATH}" + DRIVER_GDMA_FILES_PATH = "${DRIVER_FILES_PATH}" + DRIVER_INPUTMUX_FILES_PATH = "${DRIVER_FILES_PATH}" + DRIVER_PINT_FILES_PATH = "${DRIVER_FILES_PATH}" + COMPONENT_CRC_FILES_PATH = "${COMPONENT_FILES_PATH}/crc" + COMPONENT_RNG_FILES_PATH = "${COMPONENT_FILES_PATH}/rng" + COMPONENT_RPMSG_FILES_PATH = "${COMPONENT_FILES_PATH}/rpmsg" + COMPONENT_UART_FILES_PATH = "${COMPONENT_FILES_PATH}/uart" + COMPONENT_TIMER_FILES_PATH = "${COMPONENT_FILES_PATH}/timer" + COMPONENT_GPIO_FILES_PATH = "${COMPONENT_FILES_PATH}/gpio" + COMPONENT_SILICON_ID_FILES_PATH = "${COMPONENT_FILES_PATH}/silicon_id" + COMPONENT_SILICON_ID_SOCS_FILES_PATH = + "${COMPONENT_SILICON_ID_FILES_PATH}/socs" + COMPONENT_MEM_MANAGER_FILES_PATH = "${COMPONENT_FILES_PATH}/mem_manager" + UTILITIES_FILES_PATH = "${rt_sdk_root}/utilities" + UTILITIES_DEVICE_FILES_PATH = + "${rt_sdk_root}/devices/${deviceBoardName}/utilities" + UTILITIES_ASSERT_FILES_PATH = "${UTILITIES_DEVICE_FILES_PATH}" + UTILITIES_SHELL_FILES_PATH = "${UTILITIES_DEVICE_FILES_PATH}" + DEBUG_CONSOLE_FILES_PATH = "${UTILITIES_DEVICE_FILES_PATH}/debug_console_lite" + FORMAT_FILES_PATH = "${UTILITIES_DEVICE_FILES_PATH}/format" + STR_FILES_PATH = "${UTILITIES_DEVICE_FILES_PATH}/str" + WIFI_BT_TEMPLATE_PATH = "${COMPONENT_FILES_PATH}/wifi_bt_module/template" +} else { + # sdk github or internal sdk (bitbucket) are used # + COMPONENT_FILES_PATH = "${rt_core_sdk_root}/components" + DRIVER_FLEXCOMM_FILES_PATH = "${DRIVER_FILES_PATH}/flexcomm" + DRIVER_USART_FILES_PATH = "${DRIVER_FLEXCOMM_FILES_PATH}/usart" + DRIVER_DMA_FILES_PATH = "${DRIVER_FILES_PATH}/lpc_dma" + DRIVER_MRT_FILES_PATH = "${DRIVER_FILES_PATH}/mrt" + DRIVER_TRNG_FILES_PATH = "${DRIVER_FILES_PATH}/trng" + DRIVER_FLEXSPI_FILES_PATH = "${DRIVER_FILES_PATH}/flexspi" + DRIVER_LPC_GPIO_FILES_PATH = "${DRIVER_FILES_PATH}/lpc_gpio" + DRIVER_ENET_FILES_PATH = "${DRIVER_FILES_PATH}/enet" + DRIVER_DCP_FILES_PATH = "${DRIVER_FILES_PATH}/dcp" + DRIVER_CACHE_FILES_PATH = "${DRIVER_FILES_PATH}/cache/cache64" + DRIVER_COMMON_FILES_PATH = "${DRIVER_FILES_PATH}/common" + DRIVER_DEVICE_FILES_PATH = + "${rt_core_sdk_root}/devices/${deviceBoardName}/drivers" + DRIVER_IMU_FILES_PATH = "${DRIVER_FILES_PATH}/imu" + DRIVER_GDMA_FILES_PATH = "${DRIVER_FILES_PATH}/gdma" + DRIVER_INPUTMUX_FILES_PATH = "${DRIVER_FILES_PATH}/inputmux" + DRIVER_PINT_FILES_PATH = "${DRIVER_FILES_PATH}/pint" + COMPONENT_CRC_FILES_PATH = "${COMPONENT_FILES_PATH}/crc" + COMPONENT_RNG_FILES_PATH = "${COMPONENT_FILES_PATH}/rng" + COMPONENT_RPMSG_FILES_PATH = "${COMPONENT_FILES_PATH}/rpmsg" + COMPONENT_UART_FILES_PATH = "${COMPONENT_FILES_PATH}/uart" + COMPONENT_TIMER_FILES_PATH = "${COMPONENT_FILES_PATH}/timer" + COMPONENT_GPIO_FILES_PATH = "${COMPONENT_FILES_PATH}/gpio" + COMPONENT_MEM_MANAGER_FILES_PATH = "${COMPONENT_FILES_PATH}/mem_manager" + COMPONENT_SILICON_ID_FILES_PATH = "${COMPONENT_FILES_PATH}/silicon_id" + COMPONENT_SILICON_ID_SOCS_FILES_PATH = + "${COMPONENT_SILICON_ID_FILES_PATH}/socs" + UTILITIES_DEVICE_FILES_PATH = + "${rt_core_sdk_root}/devices/${deviceBoardName}/utilities" + UTILITIES_ASSERT_FILES_PATH = "${UTILITIES_FILES_PATH}/assert" + UTILITIES_SHELL_FILES_PATH = "${UTILITIES_FILES_PATH}/shell" + DEBUG_CONSOLE_FILES_PATH = "${UTILITIES_FILES_PATH}/debug_console_lite" + FORMAT_FILES_PATH = "${UTILITIES_FILES_PATH}/misc_utilities" + STR_FILES_PATH = "${UTILITIES_FILES_PATH}/str" + WIFI_BT_TEMPLATE_PATH = "${COMPONENT_FILES_PATH}/wifi_bt_module/template" +} + +ELS_PKC_CL_PATH = "${rt_sdk_root}/components/els_pkc/" + +template("rw61x_sdk_drivers") { + # Convert the CPU1/CPU2 fw binaries into src files + fw_bin_path = "${rt_sdk_root}/components/conn_fwloader" + fw_args = [ + "-t", + cpu1_cpu2_fw_type, + rebase_path(fw_bin_path, root_build_dir), + ] + + #In case A0 target board version, explicitly generate A0 fw binaries + if (board_version == "A0") { + fw_args += [ + "-r", + board_version, + ] + } + + print(exec_script( + "${rt_sdk_root}/components/conn_fwloader/script/fw_bin2c_conv.py", + fw_args, + "list lines")) + + config("${target_name}_config") { + include_dirs = [] + + if (defined(invoker.include_dirs)) { + include_dirs += invoker.include_dirs + } + + _rw61x_sdk_drivers_include_dirs = [ + #Drivers files + "${DRIVER_DEVICE_FILES_PATH}", + "${rt_core_sdk_root}/devices/${deviceBoardName}", + "${COMPONENT_CRC_FILES_PATH}", + "${COMPONENT_RNG_FILES_PATH}", + "${COMPONENT_RPMSG_FILES_PATH}", + "${COMPONENT_UART_FILES_PATH}", + "${COMPONENT_TIMER_FILES_PATH}", + "${COMPONENT_GPIO_FILES_PATH}", + "${COMPONENT_SILICON_ID_FILES_PATH}", + "${COMPONENT_SILICON_ID_SOCS_FILES_PATH}", + "${COMPONENT_MEM_MANAGER_FILES_PATH}", + "${DRIVER_COMMON_FILES_PATH}", + "${DRIVER_FLEXCOMM_FILES_PATH}", + "${DRIVER_USART_FILES_PATH}", + "${DRIVER_LPC_GPIO_FILES_PATH}", + "${DRIVER_DCP_FILES_PATH}", + "${DRIVER_ENET_FILES_PATH}", + "${DRIVER_CACHE_FILES_PATH}", + "${DRIVER_MRT_FILES_PATH}", + "${DRIVER_TRNG_FILES_PATH}", + "${DRIVER_FLEXSPI_FILES_PATH}", + "${DRIVER_DMA_FILES_PATH}", + "${UTILITIES_FILES_PATH}", + "${UTILITIES_DEVICE_FILES_PATH}", + "${DEBUG_CONSOLE_FILES_PATH}", + "${FORMAT_FILES_PATH}", + "${STR_FILES_PATH}", + "${DRIVER_IMU_FILES_PATH}", + "${DRIVER_GDMA_FILES_PATH}", + "${DRIVER_INPUTMUX_FILES_PATH}", + "${DRIVER_PINT_FILES_PATH}", + + # XIP + "${rt_core_sdk_root}/components/flash/mflash", + "${rt_core_sdk_root}/components/flash/mflash/rdrw612bga", + + # loader files + "${rt_core_sdk_root}/components/conn_fwloader/include", + + #power manager + "${rt_core_sdk_root}/components/power_manager/core", + "${rt_core_sdk_root}/components/power_manager/devices/RW612", + + #flash config + "${rt_core_sdk_root}/boards/rdrw612bga/flash_config", + + # freertos + "${rt_sdk_freertos_kernel}/portable/GCC/ARM_CM33_NTZ/non_secure", + + # framework + "${rt_sdk_root}/middleware/wireless/framework/platform/${rt_fwk_platform}/configs", + "${rt_sdk_root}/middleware/wireless/framework/FactoryDataProvider", + ] + + libs = [] + + if (defined(invoker.defines)) { + defines += invoker.defines + } else { + defines = [] + } + + defines += [ + "CPU_RW612ETA1I", + "CPU3", + "FSL_RTOS_FREE_RTOS", + + # when DEBUG_CONSOLE_TRANSFER_NON_BLOCKING is defined + # SERIAL_MANAGER_NON_BLOCKING_MODE is set to 1 by default + #"SERIAL_MANAGER_NON_BLOCKING_MODE=1", + "IMU_TASK_STACK_SIZE=1024", + "RPMSG_TXQ_BUFSIZE=16", + "RPMSG_TXQ_BUFLENGTH=256", + "gMemManagerLightExtendHeapAreaUsage=1", + "APP_FLEXSPI_AMBA_BASE=0x08000000", + "gAspCapability_d=1", + "FFU_CNS_TX_PWR_TABLE_CALIBRATION=1", + "USE_RTOS=1", + "BOOT_HEADER_ENABLE=1", + "WIFI_BOARD_RW610", + + # This allows the CPU1/CPU2 fw to be embedded in the application + "gPlatformMonolithicApp_d=1", + ] + + if (board_version != "A1") { + defines += [ "RW610_A1=0" ] + } + + if (rw610_mbedtls_port_els_pkc) { + defines += [ + # needed to compile els_pkc port for mbedtls + "MBEDTLS_MCUX_ELS_PKC_API", + ] + _rw61x_sdk_drivers_include_dirs += [ + "${ELS_PKC_CL_PATH}", + "${ELS_PKC_CL_PATH}/src/platforms/redfinchSdk_sample", + "${ELS_PKC_CL_PATH}/src/platforms/redfinchSdk_sample/inc", + "${ELS_PKC_CL_PATH}/src/inc", + "${ELS_PKC_CL_PATH}/src/inc/impl", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEls/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEls/inc/internal", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClHash/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClSession/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClSession/inc/internal", + "${ELS_PKC_CL_PATH}/src/comps/mcuxCsslFlowProtection/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClCore/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxCsslSecureCounter/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxCsslCPreProcessor/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMemory/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxCsslMemory/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxCsslParamIntegrity/inc", + "${ELS_PKC_CL_PATH}/src/compiler", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRandom/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRandom/inc/internal", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRandomModes/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRandomModes/inc/internal", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClAes/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClAes/inc/internal", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClKey/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/inc/internal", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClTrng/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClTrng/inc/internal", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClPrng/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClPrng/inc/internal", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMath/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMath/inc/internal", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClPkc/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMacModes/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMacModes/inc/internal", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMac/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMac/inc/internal", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClPadding/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClPadding/inc/internal", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClAeadModes/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClAeadModes/inc/internal", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClAead/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClAead/inc/internal", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClCipherModes/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClCipherModes/inc/internal", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClCipher/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClCipher/inc/internal", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClTrng/inc", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClTrng/inc/internal", + ] + } + + if (chip_enable_wifi) { + _rw61x_sdk_drivers_include_dirs += [ + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver", + + # Include lpm.h and host_sleep.h files + "${rt_sdk_root}/boards/rdrw612bga/wifi_examples/wifi_cli", + + # wifi config file path + "${WIFI_BT_TEMPLATE_PATH}", + ] + } + + if (chip_enable_ble) { + libs += [ + #ethermind bt libs + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/lib/mcux/default/ble/cm33nodsp/gcc/libethermind_ble_core.a", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/lib/mcux/default/ble/cm33nodsp/gcc/libethermind_ble_gatt.a", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/lib/mcux/default/ble/cm33nodsp/gcc/libethermind_ble_protocol.a", + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/private/lib/mcux/default/ble/cm33nodsp/gcc/libethermind_ble_util.a", + ] + defines += [ + "gPlatformDisableBleLowPower_d=1", + "BT_PLATFORM", + "GATT_DB", + "CFG_BLE", + ] + } + + if (chip_enable_matter_cli) { + #When the CLI is enabled the debug console should be moved in UART0 for RW61x + defines += [ "DEBUG_CONSOLE_UART_INDEX=0" ] + } + + if (chip_enable_openthread) { + if (!spinel_interface_rpmsg) { + _rw61x_sdk_drivers_include_dirs += [ + "${rt_sdk_root}/middleware/wireless/ieee-802.15.4/ieee_802_15_4/phy/interface", + "${rt_sdk_root}/middleware/wireless/ieee-802.15.4/ieee_802_15_4/phy/source/RW610N/RW610_RPMSG", + "${rt_sdk_root}/middleware/wireless/ieee-802.15.4/utils", + ] + } else { + defines += [ "SPINEL_INTERFACE_RPMSG" ] + } + } + + cflags = [] + cflags_c = [] + + if (defined(invoker.cflags)) { + cflags += invoker.cflags + } + + cflags_c += [ + "-Wno-unused-variable", + "-Wno-int-in-bool-context", + "-Wno-memset-elt-size", + "-Wno-parentheses", + "-Wno-vla", + "-Wno-cpp", + "-Wno-int-conversion", + "-Wno-error", + ] + + # Now add our "system-header" include dirs + foreach(include_dir, _rw61x_sdk_drivers_include_dirs) { + cflags += [ "-isystem" + rebase_path(include_dir, root_build_dir) ] + } + } + + source_set(target_name) { + forward_variables_from(invoker, "*") + + if (!defined(sources)) { + sources = [] + } + + sources += [ + "${COMPONENT_CRC_FILES_PATH}/fsl_adapter_software_crc.c", + "${COMPONENT_GPIO_FILES_PATH}/fsl_adapter_lpc_gpio.c", + "${COMPONENT_MEM_MANAGER_FILES_PATH}/fsl_component_mem_manager_light.c", + + #"${COMPONENT_RNG_FILES_PATH}/fsl_adapter_trng.c", + "${COMPONENT_RNG_FILES_PATH}/fsl_adapter_software_rng.c", + "${COMPONENT_RPMSG_FILES_PATH}/fsl_adapter_rfimu.c", + "${COMPONENT_SILICON_ID_FILES_PATH}/fsl_silicon_id.c", + "${COMPONENT_TIMER_FILES_PATH}/fsl_adapter_mrt.c", + "${COMPONENT_UART_FILES_PATH}/fsl_adapter_usart.c", + "${DEBUG_CONSOLE_FILES_PATH}/fsl_debug_console.c", + "${DRIVER_CACHE_FILES_PATH}/fsl_cache.c", + "${DRIVER_COMMON_FILES_PATH}/fsl_common.c", + "${DRIVER_COMMON_FILES_PATH}/fsl_common_arm.c", + "${DRIVER_DEVICE_FILES_PATH}/fsl_clock.c", + "${DRIVER_DEVICE_FILES_PATH}/fsl_ocotp.c", + "${DRIVER_DEVICE_FILES_PATH}/fsl_power.c", + "${DRIVER_DEVICE_FILES_PATH}/fsl_reset.c", + "${DRIVER_ENET_FILES_PATH}/fsl_enet.c", + "${DRIVER_FLEXCOMM_FILES_PATH}/fsl_flexcomm.c", + "${DRIVER_FLEXSPI_FILES_PATH}/fsl_flexspi.c", + "${DRIVER_GDMA_FILES_PATH}/fsl_gdma.c", + "${DRIVER_IMU_FILES_PATH}/fsl_imu.c", + "${DRIVER_INPUTMUX_FILES_PATH}/fsl_inputmux.c", + "${DRIVER_LPC_GPIO_FILES_PATH}/fsl_gpio.c", + "${DRIVER_MRT_FILES_PATH}/fsl_mrt.c", + "${DRIVER_PINT_FILES_PATH}/fsl_pint.c", + "${DRIVER_TRNG_FILES_PATH}/fsl_trng.c", + "${DRIVER_USART_FILES_PATH}/fsl_usart.c", + "${DRIVER_USART_FILES_PATH}/fsl_usart_dma.c", + "${FORMAT_FILES_PATH}/fsl_format.c", + "${UTILITIES_SHELL_FILES_PATH}/fsl_shell.c", + + #sdk hook + "${nxp_sdk_build_root}/${nxp_sdk_name}/sdk_hook/zephyr/kernel.c", + "${rt_core_sdk_root}/boards/rdrw612bga/flash_config/flash_config.c", + + # Loader files + "${rt_core_sdk_root}/components/conn_fwloader/fsl_loader.c", + "${rt_core_sdk_root}/components/conn_fwloader/life_cycle.c", + "${rt_core_sdk_root}/components/conn_fwloader/nboot_hal.c", + "${rt_core_sdk_root}/components/flash/mflash/rdrw612bga/mflash_drv.c", + + # comment fsl_str.c if using debug console light + #"${STR_FILES_PATH}/fsl_str.c", + # flash + "${rt_core_sdk_root}/components/internal_flash/rdrw612bga/fsl_adapter_flexspi_nor_flash.c", + + # power manager + "${rt_core_sdk_root}/components/power_manager/core/fsl_pm_core.c", + + #startup files + "${rt_core_sdk_root}/devices/${deviceBoardName}/gcc/startup_${deviceBoardName}.S", + "${rt_core_sdk_root}/devices/${deviceBoardName}/system_${deviceBoardName}.c", + + # freertos files + "${rt_sdk_freertos_kernel}/portable/GCC/ARM_CM33_NTZ/non_secure/port.c", + "${rt_sdk_freertos_kernel}/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c", + "${rt_sdk_freertos_kernel}/portable/MemMang/heap_4.c", + + # fw binaries for cpu1/cpu2 + "${rt_sdk_root}/components/conn_fwloader/${board_version}/fw_cpu1.c", + "${rt_sdk_root}/components/conn_fwloader/${board_version}/fw_cpu2_ble.c", + "${rt_sdk_root}/components/conn_fwloader/${board_version}/fw_cpu2_combo.c", + + # this platform file is needed for BLE/15.4 Controller wake up + "${rt_sdk_root}/middleware/wireless/framework/platform/${rt_fwk_platform}/fwk_platform_ble.c", + + # framework coex file to initialize controllers + "${rt_sdk_root}/middleware/wireless/framework/platform/${rt_fwk_platform}/fwk_platform_coex.c", + + # other framework files + "${rt_sdk_root}/middleware/wireless/framework/FactoryDataProvider/fwk_factory_data_provider.c", + ] + + if (sdk_fsl_assert_support) { + sources += [ "${UTILITIES_ASSERT_FILES_PATH}/fsl_assert.c" ] + } + + if (rw610_mbedtls_port_els_pkc) { + # els_pkc component for mbedtls els_pkc port + sources += [ + "${ELS_PKC_CL_PATH}/src/comps/mcuxClAead/src/mcuxClAead.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClAeadModes/src/mcuxClAeadModes_ELS_AesCcm.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClAeadModes/src/mcuxClAeadModes_ELS_AesGcm.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClAeadModes/src/mcuxClAeadModes_ELS_CcmEngineAes.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClAeadModes/src/mcuxClAeadModes_ELS_Constants.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClAeadModes/src/mcuxClAeadModes_ELS_GcmEngineAes.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClAeadModes/src/mcuxClAeadModes_ELS_MultiPart.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClAeadModes/src/mcuxClAeadModes_ELS_OneShot.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClAes/src/mcuxClAes_KeyTypes.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClCipher/src/mcuxClCipher.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClCipherModes/src/mcuxClCipherModes_ELS_Aes.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClCipherModes/src/mcuxClCipherModes_ELS_EngineAes.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClCipherModes/src/mcuxClCipherModes_Helper.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClCipherModes/src/mcuxClCipherModes_Modes.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Constants.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_EdDSA_GenerateKeyPair.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_EdDSA_GenerateKeyPair_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_EdDSA_GenerateSignature.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_EdDSA_Internal_SetupEnvironment.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_EdDSA_VerifySignature.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Internal_BlindedScalarMult.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Internal_Convert_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Internal_GenerateMultiplicativeBlinding.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Internal_InterleaveTwoScalars.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Internal_Interleave_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Internal_RecodeAndReorderScalar.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Internal_SetupEnvironment.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Internal_SetupEnvironment_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Internal_Types.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_KeyTypes.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Mont_DhKeyAgreement.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Mont_DhKeyGeneration.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Mont_Internal_DhSetupEnvironment.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Mont_Internal_MontDhX.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Mont_Internal_MontDhX_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Mont_Internal_SecureScalarMult_XZMontLadder.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Mont_Internal_SecureScalarMult_XZMontLadder_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_SignatureMechanisms.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_TwEd_Internal_FixScalarMult.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_TwEd_Internal_PlainFixScalarMult25519.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_TwEd_Internal_PlainPtrSelectComb.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_TwEd_Internal_PlainPtrSelectML.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_TwEd_Internal_PlainVarScalarMult.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_TwEd_Internal_PointArithmeticEd25519.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_TwEd_Internal_PointArithmeticEd25519_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_TwEd_Internal_PointValidation_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_TwEd_Internal_PrecPointImportAndValidate.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_TwEd_Internal_VarScalarMult.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_TwEd_Internal_VarScalarMult_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_WeierECC_Internal_GenerateCustomKeyType.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_WeierECC_Internal_GenerateDomainParams.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_WeierECC_Internal_GenerateDomainParams_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_WeierECC_Internal_SetupEnvironment.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_Internal_ConvertPoint_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_Internal_KeyGen.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_Internal_KeyGen_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_Internal_PointArithmetic.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_Internal_PointArithmetic_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_Internal_PointCheck.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_Internal_PointCheck_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_Internal_PointMult.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_Internal_SecurePointMult_CoZMontLadder.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_Internal_SecurePointMult_CoZMontLadder_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_Internal_SetupEnvironment.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_KeyGen.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_PointMult.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_PointMult_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_Sign.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_Sign_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_Verify.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEcc/src/mcuxClEcc_Weier_Verify_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEls/src/mcuxClEls_Aead.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEls/src/mcuxClEls_Cipher.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEls/src/mcuxClEls_Cmac.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEls/src/mcuxClEls_Common.c", + + #"${ELS_PKC_CL_PATH}/src/comps/mcuxClEls/src/mcuxClEls_Crc.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEls/src/mcuxClEls_Ecc.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEls/src/mcuxClEls_Hash.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEls/src/mcuxClEls_Hmac.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEls/src/mcuxClEls_Kdf.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEls/src/mcuxClEls_KeyManagement.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClEls/src/mcuxClEls_Rng.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClHash/src/mcuxClHash_api_multipart_common.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClHash/src/mcuxClHash_api_multipart_compute.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClHash/src/mcuxClHash_api_oneshot_compute.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClHash/src/mcuxClHash_core_els_sha2.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClHash/src/mcuxClHash_internal_els_sha2.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClKey/src/mcuxClKey.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClKey/src/mcuxClKey_KeyTypes.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClKey/src/mcuxClKey_Protection.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMac/src/mcuxClMac.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMacModes/src/mcuxClMacModes.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMacModes/src/mcuxClMacModes_ELS_CBCMAC.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMacModes/src/mcuxClMacModes_ELS_CMAC.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMacModes/src/mcuxClMacModes_ELS_Functions.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMacModes/src/mcuxClMacModes_ELS_HMAC.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMacModes/src/mcuxClMacModes_Helper.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMacModes/src/mcuxClMacModes_Modes.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMath/src/mcuxClMath_ExactDivide.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMath/src/mcuxClMath_ExactDivideOdd.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMath/src/mcuxClMath_ExactDivideOdd_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMath/src/mcuxClMath_ModExp_SqrMultL2R.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMath/src/mcuxClMath_ModInv.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMath/src/mcuxClMath_ModInv_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMath/src/mcuxClMath_NDash.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMath/src/mcuxClMath_NDash_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMath/src/mcuxClMath_QDash.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMath/src/mcuxClMath_QDash_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMath/src/mcuxClMath_ReduceModEven.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMath/src/mcuxClMath_SecModExp.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMath/src/mcuxClMath_SecModExp_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMath/src/mcuxClMath_Utils.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMemory/src/mcuxClMemory.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClPadding/src/mcuxClPadding.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClPkc/src/mcuxClPkc_Calculate.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClPkc/src/mcuxClPkc_ImportExport.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClPkc/src/mcuxClPkc_Initialize.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClPkc/src/mcuxClPkc_UPTRT.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClPrng/src/mcuxClPrng_ELS.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRandom/src/mcuxClRandom_DRBG.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRandom/src/mcuxClRandom_PRNG.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRandomModes/src/mcuxClRandomModes_CtrDrbg.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRandomModes/src/mcuxClRandomModes_CtrDrbg_Els.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRandomModes/src/mcuxClRandomModes_CtrDrbg_PrDisabled.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRandomModes/src/mcuxClRandomModes_ElsMode.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRandomModes/src/mcuxClRandomModes_NormalMode.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRandomModes/src/mcuxClRandomModes_PatchMode.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRandomModes/src/mcuxClRandomModes_PrDisabled.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRandomModes/src/mcuxClRandomModes_TestMode.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_ComputeD.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_ComputeD_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_GenerateProbablePrime.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_KeyGeneration_Crt.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_KeyGeneration_Crt_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_KeyGeneration_Plain.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_Mgf1.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_MillerRabinTest.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_MillerRabinTest_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_ModInv.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_NoEncode.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_NoVerify.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_Pkcs1v15Encode_sign.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_Pkcs1v15Verify.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_PrivateCrt.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_PrivateCrt_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_PrivatePlain.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_PssEncode.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_PssVerify.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_Public.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_Public_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_RemoveBlinding.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_RemoveBlinding_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_Sign.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_TestPQDistance.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_TestPQDistance_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_TestPrimeCandidate.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_TestPrimeCandidate_FUP.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_Verify.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClRsa/src/mcuxClRsa_VerifyE.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClSession/src/mcuxClSession.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClTrng/src/mcuxClTrng_RNG4.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxCsslMemory/src/mcuxCsslMemory_Clear.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxCsslMemory/src/mcuxCsslMemory_Compare.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxCsslMemory/src/mcuxCsslMemory_Copy.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxCsslMemory/src/mcuxCsslMemory_Set.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxCsslParamIntegrity/src/mcuxCsslParamIntegrity.c", + "${ELS_PKC_CL_PATH}/src/platforms/redfinchSdk_sample/mcux_els.c", + "${ELS_PKC_CL_PATH}/src/platforms/redfinchSdk_sample/mcux_pkc.c", + ] + } + + if (chip_enable_ble) { + sources += [ + "${rt_sdk_root}/middleware/wireless/ethermind/bluetooth/export/extension/gatt_db_pl.c", + "${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux/bluetooth/controller/controller_rw610.c", + "${rt_sdk_root}/middleware/wireless/ethermind/port/pal/mcux/bluetooth/hci_platform.c", + ] + } + + if (chip_enable_wifi) { + sources += [ + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_11ax.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_11k.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_11v.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_action.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/mlan_mbo.c", + "${rt_sdk_root}/middleware/wifi_nxp/wifidriver/wifi-imu.c", + ] + } + + if (chip_enable_openthread) { + sources += [ + "${rt_sdk_root}/middleware/wireless/framework/platform/${rt_fwk_platform}/fwk_platform_hdlc.c", + "${rt_sdk_root}/middleware/wireless/framework/platform/${rt_fwk_platform}/fwk_platform_ot.c", + ] + if (!spinel_interface_rpmsg) { + sources += [ + "${rt_sdk_root}/middleware/wireless/ieee-802.15.4/ieee_802_15_4/phy/source/RW610N/RW610_RPMSG/ASP.c", + "${rt_sdk_root}/middleware/wireless/ieee-802.15.4/ieee_802_15_4/phy/source/RW610N/RW610_RPMSG/Phy.c", + ] + } + } + + if (!defined(public_configs)) { + public_configs = [] + } + + if (!defined(public_deps)) { + public_deps = [] + } + + if (!defined(deps)) { + deps = [] + } + + public_configs += [ ":${target_name}_config" ] + public_deps += [ nxp_sdk_target ] + + # The FactoryDataProvider/fwk_factory_data_provider.c component has a dependency to mbedtls + deps += [ "${nxp_sdk_build_root}/${nxp_sdk_name}/${rt_platform}:nxp_sdk_mbedtls_config" ] + + if (chip_enable_openthread) { + #Dep to ot header files required for mbedtls as mbedtls config file has a dependency to ot + deps += [ "${openthread_root}/src/core:libopenthread_core_headers" ] + } + } +} diff --git a/third_party/nxp/rt_sdk/sdk_hook/bt_pal/EM_platform.h b/third_party/nxp/rt_sdk/sdk_hook/bt_pal/EM_platform.h new file mode 100644 index 00000000000000..5d85b366aeb486 --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/bt_pal/EM_platform.h @@ -0,0 +1,22 @@ + +/** + * \file EM_platform.h + * + * + */ + +/* + * Copyright 2022 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _H_EM_PLATFORM_HOOK +#define _H_EM_PLATFORM_HOOK + +#include "mcux/EM_platform.h" +#undef EM_HAVE_STATIC_DECL + +#endif /* _H_EM_PLATFORM_HOOK */ diff --git a/third_party/nxp/rt_sdk/sdk_hook/littlefs_pl.c b/third_party/nxp/rt_sdk/sdk_hook/littlefs_pl.c new file mode 100644 index 00000000000000..b25469e343080a --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/littlefs_pl.c @@ -0,0 +1,16 @@ + +/* + * Copyright 2021 - 2022 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "littlefs_pl.h" +#include "lfs.h" +// #include "fwk_filesystem.h" + +/*lfs_t * lfs_pl_init(void) +{ + return (lfs_t*)FS_InitGetHandle(); +}*/ diff --git a/third_party/nxp/rt_sdk/sdk_hook/logging/log.h b/third_party/nxp/rt_sdk/sdk_hook/logging/log.h new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/third_party/nxp/rt_sdk/sdk_hook/mbedtls/ksdk_mbedtls_hook.c b/third_party/nxp/rt_sdk/sdk_hook/mbedtls/ksdk_mbedtls_hook.c new file mode 100644 index 00000000000000..b72121566bc312 --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/mbedtls/ksdk_mbedtls_hook.c @@ -0,0 +1,35 @@ +/* + * Copyright 2023 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "fsl_common.h" +#include "fsl_trng.h" + +#define TRGN_MAX_RETRY 10 + +int __wrap_mbedtls_hardware_poll(void * data, unsigned char * output, size_t len, size_t * olen) +{ + status_t result = kStatus_Fail; + int nbRetry = 0; + + do + { + result = TRNG_GetRandomData(TRNG, output, len); + if (result == kStatus_Success) + break; + nbRetry++; + } while (nbRetry < TRGN_MAX_RETRY); + + if (result == kStatus_Success) + { + *olen = len; + return 0; + } + else + { + return result; + } +} diff --git a/third_party/nxp/rt_sdk/sdk_hook/mbedtls/ksdk_mbedtls_software.c b/third_party/nxp/rt_sdk/sdk_hook/mbedtls/ksdk_mbedtls_software.c new file mode 100644 index 00000000000000..3749cf1872ddac --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/mbedtls/ksdk_mbedtls_software.c @@ -0,0 +1,203 @@ +/* + * Copyright 2022 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/platform.h" + +#if defined(MBEDTLS_THREADING_C) +/* Threading mutex implementations for mbedTLS. */ +#include "mbedtls/threading.h" +#include "threading_alt.h" +#endif + +#if !defined(MBEDTLS_MCUX_FREERTOS_THREADING_ALT) && defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_ALT) +extern void CRYPTO_ConfigureThreading(void); +#endif + +#include "fsl_adapter_rng.h" +#include "fsl_common.h" +#include "ksdk_mbedtls.h" + +/******************************************************************************/ +/*************************** FreeRTOS ********************************************/ +/******************************************************************************/ +#if defined(USE_RTOS) && defined(SDK_OS_FREE_RTOS) && defined(MBEDTLS_FREESCALE_FREERTOS_CALLOC_ALT) +#include "FreeRTOS.h" +#include "task.h" +#include + +/*---------HEAP_4 calloc --------------------------------------------------*/ +#if defined(configFRTOS_MEMORY_SCHEME) && (configFRTOS_MEMORY_SCHEME == 4) +void * pvPortCalloc(size_t num, size_t size) +{ + void * ptr; + + ptr = pvPortMalloc(num * size); + if (!ptr) + { + extern void vApplicationMallocFailedHook(void); + vApplicationMallocFailedHook(); + } + else + { + memset(ptr, 0, num * size); + } + return ptr; +} +#else // HEAP_3 +void * pvPortCalloc(size_t num, size_t size) +{ + void * pvReturn; + + vTaskSuspendAll(); + { + pvReturn = calloc(num, size); + traceMALLOC(pvReturn, size); + } + (void) xTaskResumeAll(); + +#if (configUSE_MALLOC_FAILED_HOOK == 1) + { + if (pvReturn == NULL) + { + extern void vApplicationMallocFailedHook(void); + vApplicationMallocFailedHook(); + } + } +#endif + + return pvReturn; +} +#endif // configFRTOS_MEMORY_SCHEME +#endif /* USE_RTOS && defined(SDK_OS_FREE_RTOS) && defined(MBEDTLS_FREESCALE_FREERTOS_CALLOC_ALT) */ + +/*-----------------------------------------------------------*/ +/*--------- mbedTLS threading functions for FreeRTOS --------*/ +/*--------------- See MBEDTLS_THREADING_ALT -----------------*/ +/*-----------------------------------------------------------*/ +#if defined(MBEDTLS_MCUX_FREERTOS_THREADING_ALT) +/* Threading mutex implementations for mbedTLS. */ +#include "mbedtls/threading.h" +#include "threading_alt.h" + +/** + * @brief Implementation of mbedtls_mutex_init for thread-safety. + * + */ +void mcux_mbedtls_mutex_init(mbedtls_threading_mutex_t * mutex) +{ + mutex->mutex = xSemaphoreCreateMutex(); + + if (mutex->mutex != NULL) + { + mutex->is_valid = 1; + } + else + { + mutex->is_valid = 0; + } +} + +/** + * @brief Implementation of mbedtls_mutex_free for thread-safety. + * + */ +void mcux_mbedtls_mutex_free(mbedtls_threading_mutex_t * mutex) +{ + if (mutex->is_valid == 1) + { + vSemaphoreDelete(mutex->mutex); + mutex->is_valid = 0; + } +} + +/** + * @brief Implementation of mbedtls_mutex_lock for thread-safety. + * + * @return 0 if successful, MBEDTLS_ERR_THREADING_MUTEX_ERROR if timeout, + * MBEDTLS_ERR_THREADING_BAD_INPUT_DATA if the mutex is not valid. + */ +int mcux_mbedtls_mutex_lock(mbedtls_threading_mutex_t * mutex) +{ + int ret = MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; + + if (mutex->is_valid == 1) + { + if (xSemaphoreTake(mutex->mutex, portMAX_DELAY)) + { + ret = 0; + } + else + { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } + } + + return ret; +} + +/** + * @brief Implementation of mbedtls_mutex_unlock for thread-safety. + * + * @return 0 if successful, MBEDTLS_ERR_THREADING_MUTEX_ERROR if timeout, + * MBEDTLS_ERR_THREADING_BAD_INPUT_DATA if the mutex is not valid. + */ +int mcux_mbedtls_mutex_unlock(mbedtls_threading_mutex_t * mutex) +{ + int ret = MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; + + if (mutex->is_valid == 1) + { + if (xSemaphoreGive(mutex->mutex)) + { + ret = 0; + } + else + { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } + } + + return ret; +} + +static void CRYPTO_ConfigureThreadingMcux(void) +{ + /* Configure mbedtls to use FreeRTOS mutexes. */ + mbedtls_threading_set_alt(mcux_mbedtls_mutex_init, mcux_mbedtls_mutex_free, mcux_mbedtls_mutex_lock, mcux_mbedtls_mutex_unlock); +} +#endif /* defined(MBEDTLS_MCUX_FREERTOS_THREADING_ALT) */ + +status_t CRYPTO_InitHardware(void) +{ +#if defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_ALT) + + CRYPTO_ConfigureThreadingMcux(); + +#endif /* (MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_ALT) */ + + return kStatus_HAL_RngSuccess; +} + +int mbedtls_hardware_poll(void * data, unsigned char * output, size_t len, size_t * olen) +{ + hal_rng_status_t status; + + status = HAL_RngGetData(output, len); + + if (status == kStatus_HAL_RngSuccess) + { + *olen = len; + return 0; + } + return kStatus_Fail; +} diff --git a/third_party/nxp/rt_sdk/sdk_hook/zephyr/bluetooth/addr.h b/third_party/nxp/rt_sdk/sdk_hook/zephyr/bluetooth/addr.h new file mode 100644 index 00000000000000..b3f0431f86291f --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/zephyr/bluetooth/addr.h @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if defined(__cplusplus) +extern "C" { +#endif /* _cplusplus */ + +#include + +#if defined(__cplusplus) +} +#endif diff --git a/third_party/nxp/rt_sdk/sdk_hook/zephyr/bluetooth/bluetooth.h b/third_party/nxp/rt_sdk/sdk_hook/zephyr/bluetooth/bluetooth.h new file mode 100644 index 00000000000000..7a0ab815021f74 --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/zephyr/bluetooth/bluetooth.h @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if defined(__cplusplus) +extern "C" { +#endif /* _cplusplus */ + +#include + +#if defined(__cplusplus) +} +#endif diff --git a/third_party/nxp/rt_sdk/sdk_hook/zephyr/bluetooth/conn.h b/third_party/nxp/rt_sdk/sdk_hook/zephyr/bluetooth/conn.h new file mode 100644 index 00000000000000..aca6ccd51d0650 --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/zephyr/bluetooth/conn.h @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if defined(__cplusplus) +extern "C" { +#endif /* _cplusplus */ + +#include + +#if defined(__cplusplus) +} +#endif diff --git a/third_party/nxp/rt_sdk/sdk_hook/zephyr/bluetooth/gatt.h b/third_party/nxp/rt_sdk/sdk_hook/zephyr/bluetooth/gatt.h new file mode 100644 index 00000000000000..d8d26a93040183 --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/zephyr/bluetooth/gatt.h @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if defined(__cplusplus) +extern "C" { +#endif /* _cplusplus */ + +#include + +#if defined(__cplusplus) +} +#endif diff --git a/third_party/nxp/rt_sdk/sdk_hook/zephyr/kernel.c b/third_party/nxp/rt_sdk/sdk_hook/zephyr/kernel.c new file mode 100644 index 00000000000000..4f94ffe7a7377e --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/zephyr/kernel.c @@ -0,0 +1,14 @@ +/* + * Copyright 2023 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "kernel.h" + +void k_usleep(useconds_t usec) +{ + usleep(usec); +} diff --git a/third_party/nxp/rt_sdk/sdk_hook/zephyr/kernel.h b/third_party/nxp/rt_sdk/sdk_hook/zephyr/kernel.h new file mode 100644 index 00000000000000..fc71ecbfcb1dbd --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/zephyr/kernel.h @@ -0,0 +1,19 @@ +/* + * Copyright 2023 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if defined(__cplusplus) +extern "C" { +#endif /* _cplusplus */ + +#include + +void k_usleep(useconds_t usec); + +#if defined(__cplusplus) +} +#endif diff --git a/third_party/nxp/rt_sdk/sdk_hook/zephyr/random/rand32.cpp b/third_party/nxp/rt_sdk/sdk_hook/zephyr/random/rand32.cpp new file mode 100644 index 00000000000000..a54301c01bedb1 --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/zephyr/random/rand32.cpp @@ -0,0 +1,23 @@ +/* + * Copyright 2022 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "rand32.h" +#include + +/** + * Fill the buffer given as an arg with random values + * Returns 0 if success, -1 otherwise + * + */ +int sys_csrand_get(void * dst, size_t len) +{ + CHIP_ERROR error; + error = chip::Crypto::DRBG_get_bytes(reinterpret_cast(dst), len); + + return ((error == CHIP_NO_ERROR) ? 0 : -1); +} diff --git a/third_party/nxp/rt_sdk/sdk_hook/zephyr/random/rand32.h b/third_party/nxp/rt_sdk/sdk_hook/zephyr/random/rand32.h new file mode 100644 index 00000000000000..ed953ef68010c0 --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/zephyr/random/rand32.h @@ -0,0 +1,29 @@ +/* + * Copyright 2022 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RAND32_H_ +#define RAND32_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** + * Fill the buffer given as an arg with random values + * Returns 0 if success, -1 otherwise + * + */ +int sys_csrand_get(void * dst, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* RAND32_H_ */ diff --git a/third_party/nxp/rt_sdk/sdk_hook/zephyr/sys/byteorder.h b/third_party/nxp/rt_sdk/sdk_hook/zephyr/sys/byteorder.h new file mode 100644 index 00000000000000..6dda868fddeb28 --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/zephyr/sys/byteorder.h @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if defined(__cplusplus) +extern "C" { +#endif /* _cplusplus */ + +#include + +#if defined(__cplusplus) +} +#endif diff --git a/third_party/nxp/rt_sdk/sdk_hook/zephyr/sys/slist.h b/third_party/nxp/rt_sdk/sdk_hook/zephyr/sys/slist.h new file mode 100644 index 00000000000000..3dee49cb0d86c7 --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/zephyr/sys/slist.h @@ -0,0 +1,16 @@ +/* + * Copyright 2023 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if defined(__cplusplus) +extern "C" { +#endif /* _cplusplus */ + +#include "sys/slist.h" + +#if defined(__cplusplus) +} +#endif diff --git a/third_party/nxp/rt_sdk/sdk_hook/zephyr/sys/util.h b/third_party/nxp/rt_sdk/sdk_hook/zephyr/sys/util.h new file mode 100644 index 00000000000000..66bd735853e765 --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/zephyr/sys/util.h @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if defined(__cplusplus) +extern "C" { +#endif /* _cplusplus */ + +#include + +#if defined(__cplusplus) +} +#endif diff --git a/third_party/nxp/rt_sdk/transceiver/app_transceiver_config.h b/third_party/nxp/rt_sdk/transceiver/app_transceiver_config.h new file mode 100644 index 00000000000000..2422b61dbf0b1c --- /dev/null +++ b/third_party/nxp/rt_sdk/transceiver/app_transceiver_config.h @@ -0,0 +1,37 @@ +/* + * Copyright 2020-2023 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define USB_HOST_CONFIG_EHCI 2 +#define CONTROLLER_ID kUSB_ControllerEhci0 + +#if defined(WIFI_IW416_BOARD_AW_AM457_USD) || defined(WIFI_IW416_BOARD_AW_AM510_USD) || \ + defined(WIFI_88W8987_BOARD_AW_CM358_USD) || defined(WIFI_IW61x_BOARD_RD_USD) || defined(WIFI_BOARD_RW610) || \ + defined(WIFI_88W8801_BOARD_MURATA_2DS_USD) +#define WIFI_TRANSCEIVER_SUPPORT 1 +#else +#define WIFI_TRANSCEIVER_SUPPORT 0 +#endif + +/* + * Check if the transceiver is supported. + * Applies only for Matter over Wi-fi or Matter over Thread + */ +#if (CHIP_DEVICE_CONFIG_ENABLE_WPA || CHIP_DEVICE_CONFIG_ENABLE_THREAD) +#if !WIFI_TRANSCEIVER_SUPPORT && !defined(K32W061_TRANSCEIVER) +#error The transceiver module is unsupported +#endif +#endif /* CHIP_DEVICE_CONFIG_ENABLE_WPA || CHIP_DEVICE_CONFIG_ENABLE_THREAD */ + +#if WIFI_TRANSCEIVER_SUPPORT +#define NOT_DEFINE_DEFAULT_WIFI_MODULE +/* app_config.h comes from: /components/wifi_bt_module/template/wifi_config.h */ +#include "app_config.h" +#endif /* WIFI_TRANSCEIVER_SUPPORT */ + +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include "edgefast_bluetooth_config.h" +#endif /* CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE */ diff --git a/third_party/openthread/ot-nxp b/third_party/openthread/ot-nxp index 72b9cbf7e9edb4..57422f917ad1ab 160000 --- a/third_party/openthread/ot-nxp +++ b/third_party/openthread/ot-nxp @@ -1 +1 @@ -Subproject commit 72b9cbf7e9edb4d687855be75474ee59628831a1 +Subproject commit 57422f917ad1abc65919435558cd836c8f7bada7 diff --git a/third_party/openthread/platforms/nxp/rt/rw61x/BUILD.gn b/third_party/openthread/platforms/nxp/rt/rw61x/BUILD.gn new file mode 100644 index 00000000000000..98cc50084dfd50 --- /dev/null +++ b/third_party/openthread/platforms/nxp/rt/rw61x/BUILD.gn @@ -0,0 +1,96 @@ +# Copyright (c) 2020-2022 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/chip.gni") +import("//build_overrides/mbedtls.gni") +import("//build_overrides/nxp_sdk.gni") +import("//build_overrides/openthread.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}/${nxp_sdk_name}.gni") +openthread_nxp_root = "${chip_root}/third_party/openthread/ot-nxp" + +config("openthread_rw61x_config") { + include_dirs = [ + "${openthread_nxp_root}/src/common", + "${openthread_nxp_root}/src/rw/rw612", + "${openthread_nxp_root}/third_party/mbedtls/configs", + "${openthread_root}/third_party/mbedtls", + "${openthread_root}/examples/platforms", + ] + if (spinel_interface_rpmsg) { + include_dirs += [ "${openthread_nxp_root}/src/common/spinel" ] + } +} + +#Config used by the openthread stack to get the path to OpenthreadConfig.h +source_set("openthread_core_config_rw61x") { + public_configs = [ ":openthread_rw61x_config" ] + public_deps = [ nxp_sdk_target ] +} + +source_set("libopenthread-rw61x") { + sources = [ + "${openthread_nxp_root}/src/common/alarm_freertos.c", + "${openthread_nxp_root}/src/common/logging.c", + "${openthread_nxp_root}/src/rw/rw612/platform/diag.c", + "${openthread_nxp_root}/src/rw/rw612/platform/entropy.c", + ] + + if (spinel_interface_rpmsg) { + sources += [ + "${openthread_nxp_root}/src/common/spinel/misc.c", + "${openthread_nxp_root}/src/common/spinel/radio.cpp", + "${openthread_nxp_root}/src/common/spinel/spinel_hdlc.cpp", + "${openthread_nxp_root}/src/common/spinel/system.c", + "${openthread_root}/src/lib/hdlc/hdlc.cpp", + ] + } else { + sources += [ + "${openthread_nxp_root}/src/rw/rw612/platform/misc.c", + "${openthread_nxp_root}/src/rw/rw612/platform/radio.c", + "${openthread_nxp_root}/src/rw/rw612/platform/system.c", + ] + } + + if (rt_nvm_component == "nvm_fwk") { + sources += [ "${openthread_nxp_root}/src/common/flash_nvm.c" ] + } else if (rt_nvm_component == "littlefs") { + sources += [ "${openthread_nxp_root}/src/common/flash_littlefs.c" ] + } else { + sources += [ "${openthread_nxp_root}/src/common/flash_ks.c" ] + } + + defines = [ + "OPENTHREAD_FTD", + "OT_PLAT_UART_INSTANCE=3", + ] + + public_configs = [ ":openthread_rw61x_config" ] + + deps = [ + "${nxp_sdk_build_root}:nxp_mbedtls", + "../../..:libopenthread-platform-utils", + nxp_sdk_target, + ] + + if (spinel_interface_rpmsg) { + defines += [ "OT_PLAT_SPINEL_OVER_HDLC" ] + deps += [ "${openthread_root}:libopenthread-spinel-rcp" ] + } +}