From d575057f2834d8d15607de3911bcb98a694ba5f8 Mon Sep 17 00:00:00 2001 From: Dina Benamar Date: Wed, 26 Jul 2023 18:00:32 +0200 Subject: [PATCH] [NXP] Adding Matter support for RW61x platform --- build_overrides/nxp_sdk.gni | 18 + .../nxp/common/main/AppAssert.cpp | 33 + .../common/main/AppFactoryDataDefaultImpl.cpp | 76 + .../nxp/common/main/AppMatterButtonEmpty.cpp | 26 + .../nxp/common/main/AppMatterCli.cpp | 138 + .../nxp/common/main/AppTask.cpp | 481 + .../nxp/common/main/CHIPDeviceManager.cpp | 63 + .../nxp/common/main/DeviceCallbacks.cpp | 175 + .../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 | 66 + .../common/main/include/CHIPDeviceManager.h | 124 + .../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 | 192 + .../all-clusters-app/nxp/rt/rw61x/README.md | 200 + .../nxp/rt/rw61x/README_OTA_Requestor.md | 170 + .../nxp/rt/rw61x/README_Openthread.md | 85 + .../nxp/rt/rw61x/README_Wifi.md | 37 + .../all-clusters-app/nxp/rt/rw61x/args.gni | 19 + .../nxp/rt/rw61x/build_overrides | 1 + .../rw61x/include/config/CHIPProjectConfig.h | 213 + .../nxp/rt/rw61x/third_party/connectedhomeip | 1 + examples/build_overrides/nxp_sdk.gni | 18 + .../nxp/common/OTARequestorInitiator.cpp | 71 + .../nxp/common/OTARequestorInitiator.h | 51 + .../platform/nxp/common/app/support/BUILD.gn | 51 + .../nxp/common/app/support/Memconfig.cpp | 210 + examples/platform/nxp/rt/rw61x/BUILD.gn | 21 + .../nxp/rt/rw61x/app/ldscripts/RW610_flash.ld | 584 + .../project_include/freeRTOS/FreeRTOSConfig.h | 182 + .../openthread/OpenThreadConfig.h | 84 + examples/platform/nxp/rt/rw61x/board/board.c | 392 + examples/platform/nxp/rt/rw61x/board/board.h | 171 + .../nxp/rt/rw61x/board/clock_config.c | 253 + .../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 | 53 + .../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 | 36 + .../nxp/zap/thermostat_matter_thread.matter | 2122 ++ .../nxp/zap/thermostat_matter_thread.zap | 16489 ++++++++++++++++ .../nxp/zap/thermostat_matter_wifi.matter | 1978 ++ .../nxp/zap/thermostat_matter_wifi.zap | 16489 ++++++++++++++++ src/crypto/tests/BUILD.gn | 2 +- src/lib/shell/BUILD.gn | 5 + src/lib/shell/streamer_nxp.cpp | 249 + src/lwip/BUILD.gn | 7 + src/platform/BUILD.gn | 12 + src/platform/device.gni | 13 +- src/platform/nxp/BUILD.gn | 23 + .../CHIPDeviceNXPPlatformDefaultConfig.h | 109 + .../nxp/common/CHIPDevicePlatformEvent.h | 125 + .../nxp/common/ConfigurationManagerImpl.cpp | 316 + .../nxp/common/ConfigurationManagerImpl.h | 92 + .../nxp/common/ConnectivityManagerImpl.cpp | 508 + .../nxp/common/ConnectivityManagerImpl.h | 189 + .../nxp/common/DiagnosticDataProviderImpl.cpp | 333 + .../nxp/common/DiagnosticDataProviderImpl.h | 91 + .../nxp/common/InetNXPPlatformDefaultConfig.h | 31 + .../nxp/common/KeyValueStoreManagerImpl.cpp | 98 + .../nxp/common/KeyValueStoreManagerImpl.h | 82 + src/platform/nxp/common/Logging.cpp | 97 + src/platform/nxp/common/NXPConfig.cpp | 610 + src/platform/nxp/common/NXPConfig.h | 202 + .../nxp/common/NetworkCommissioningDriver.h | 113 + .../common/NetworkCommissioningWiFiDriver.cpp | 445 + .../common/NetworkProvisioningServerImpl.cpp | 41 + .../common/NetworkProvisioningServerImpl.h | 80 + .../nxp/common/OTAImageProcessorImpl.cpp | 358 + .../nxp/common/OTAImageProcessorImpl.h | 85 + src/platform/nxp/common/PlatformManagerImpl.h | 108 + .../nxp/common/SoftwareUpdateManagerImpl.cpp | 46 + .../nxp/common/SoftwareUpdateManagerImpl.h | 89 + .../common/SystemNXPPlatformDefaultConfig.h | 88 + .../nxp/common/ThreadStackManagerImpl.cpp | 124 + .../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 | 120 + .../FactoryDataProviderFwkImpl.cpp | 134 + .../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 | 39 + .../nxp/rt/rw61x/CHIPDevicePlatformConfig.h | 46 + .../nxp/rt/rw61x/CHIPPlatformConfig.h | 55 + .../nxp/rt/rw61x/InetPlatformConfig.h | 41 + .../nxp/rt/rw61x/PlatformManagerImpl.cpp | 347 + .../nxp/rt/rw61x/SystemPlatformConfig.h | 42 + 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 | 229 + .../nxp/rt_sdk/lwip/common/lwipopts_common.h | 619 + .../nxp/rt_sdk/lwip/common/lwippools.h | 30 + third_party/nxp/rt_sdk/lwip/lwip.gni | 256 + .../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 | 33 + 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 | 685 + .../nxp/rt_sdk/sdk_hook/bt_pal/EM_platform.h | 23 + 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 | 206 + .../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 | 17 + .../nxp/rt_sdk/sdk_hook/zephyr/sys/util.h | 17 + .../transceiver/app_transceiver_config.h | 37 + .../platforms/nxp/rt/rw61x/BUILD.gn | 96 + 141 files changed, 52700 insertions(+), 2 deletions(-) create mode 100644 build_overrides/nxp_sdk.gni 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/README_OTA_Requestor.md create mode 100644 examples/all-clusters-app/nxp/rt/rw61x/README_Openthread.md create mode 100644 examples/all-clusters-app/nxp/rt/rw61x/README_Wifi.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/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/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..534f0572ab3742 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/AppAssert.cpp @@ -0,0 +1,33 @@ +/* + * + * 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); +} \ No newline at end of file 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..eecbdb82219f78 --- /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; +} \ No newline at end of file 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..eea994594969af --- /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; +} \ No newline at end of file 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..cb818e5c377d6e --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/AppMatterCli.cpp @@ -0,0 +1,138 @@ +/* + * + * 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 +#include +#include "AppTask.h" +#include + +#ifdef ENABLE_CHIP_SHELL +#include +#include +#include "task.h" + +#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..bd0554e5244e34 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/AppTask.cpp @@ -0,0 +1,481 @@ +/* + * + * 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/support/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 "AppMatterCli.h" +#include "AppMatterButton.h" +#include "AppFactoryData.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..c7d8023fe810c2 --- /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..65aaa120546a08 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/DeviceCallbacks.cpp @@ -0,0 +1,175 @@ +/* + * + * 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 \ No newline at end of file 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..3bf0ae7cca28b6 --- /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_ */ \ No newline at end of file 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..b326101ac2a252 --- /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_ */ \ No newline at end of file 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..163534f6920886 --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/include/AppTask.h @@ -0,0 +1,66 @@ +/* + * + * 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..a9de545ef7981d --- /dev/null +++ b/examples/all-clusters-app/nxp/common/main/include/CHIPDeviceManager.h @@ -0,0 +1,124 @@ +/* + * + * 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..1c995a1db5349b --- /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 +#include +#include +#include "FreeRTOS.h" + +#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..400f68580a4f58 --- /dev/null +++ b/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn @@ -0,0 +1,192 @@ +# 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/static-supported-modes-manager.cpp", + "${chip_root}/examples/${app_common_folder}/src/smco-stub.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..3f5a53bc6c2f19 --- /dev/null +++ b/examples/all-clusters-app/nxp/rt/rw61x/README.md @@ -0,0 +1,200 @@ +# 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](#intro) +- [Building](#building) +- [Flashing and debugging](#flashdebug) +- [Testing the example](#testing-the-example) +- [Matter Shell](#matter-shell) + +
+ + + +## 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. For that follow instructions from [README_Wifi.md][README_Wifi.md]. +- Matter over Openthread. For that follow instructions from [README_Openthread.md][README_Openthread.md]. + +[README_Wifi.md]: README_Wifi.md +[README_Openthread.md]: README_Openthread.md + +The example targets the +[`NXP RD-RW610-BGA`] and the [`NXP RD-RW612-BGA`] +boards, with the following configurations : +- RW610 : Matter over Wi-Fi. +- RW612 : Matter over Wi-Fi and Matter over Thread. + + + + +## 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 for Project CHIP](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. (Note : SDK 2.13.1 version is with access control.) + + ![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.) + + Please refer to Matter release notes for getting the latest released SDK. + +- 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/ +``` + +Optional GN options that can be added when building an application: + +- To enable the [matter CLI](README.md#matter-shell), 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](../../../../platform/nxp/doc/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](../../../../platform/nxp/doc/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 + +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 + +### 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](../../../../../examples/chip-tool) application as it is described [here](../../../../../examples/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](../../../../../examples/chip-tool/README.md) application as it is described [here](../../../../../examples/chip-tool/README.md#using-the-client-to-send-matter-commands). \ No newline at end of file diff --git a/examples/all-clusters-app/nxp/rt/rw61x/README_OTA_Requestor.md b/examples/all-clusters-app/nxp/rt/rw61x/README_OTA_Requestor.md new file mode 100644 index 00000000000000..809f89eabec945 --- /dev/null +++ b/examples/all-clusters-app/nxp/rt/rw61x/README_OTA_Requestor.md @@ -0,0 +1,170 @@ +# OTA requestor feature + +## 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 using the RW61x All-Clusters application. + +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 all-clusters 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 all-clusters 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 all-clusters 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](../../../../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](../../../../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 application can be generated using the instructions from the [README.md 'Building section'][readme_building_section] section. The application is automatically linked to be executed from the primary image partition, taking into consideration the offset imposed by mcuboot. + +[readme_building_section]: README.md#building + +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 All-clusters 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. \ No newline at end of file diff --git a/examples/all-clusters-app/nxp/rt/rw61x/README_Openthread.md b/examples/all-clusters-app/nxp/rt/rw61x/README_Openthread.md new file mode 100644 index 00000000000000..5d54e69214e9c3 --- /dev/null +++ b/examples/all-clusters-app/nxp/rt/rw61x/README_Openthread.md @@ -0,0 +1,85 @@ +# Matter over Thread on RW612 + +## Hardware requirements + +- `RD-RW612-BGA` board +- BLE/15.4 antenna + + + +## Building + +### Pre-build instructions +First instructions from [README.md 'Building section'][readme_building_section] should be followed. + +[readme_building_section]: README.md#building + +### Build instructions + +- 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 +``` + +The resulting output file can be found in out/debug/chip-rw61x-all-cluster-example. + +## Flash Binaries +### Flashing and debugging RW612 + +To know how to flash and debug follow instructions from [README.md 'Flashing and debugging'][readme_flash_debug_section]. + +[readme_flash_debug_section]:README.md#flashing-and-debugging + +## Raspberrypi Border Router setup + +Instructions to start an openthread border router should be followed. In this section a mechanism to start the BR, without accessing the web interface, is described. + +Start the docker BR image: + +``` +sudo docker run -it --rm --network host --privileged -v /dev/ttyACM0:/dev/radio connectedhomeip/otbr:sve2 --radio-url spinel+hdlc+uart:///dev/radio -B eth0 +``` + +Get the docker ID of the BR image: +``` +sudo docker container ls +``` + +Create a thread network on the border router ( should be replaced by the previously gotten BR docker ID): + +``` +sudo docker exec -it sh -c "sudo ot-ctl dataset init new"; sudo docker exec -it sh -c "sudo ot-ctl dataset channel 17"; sudo docker exec -it sh -c "sudo ot-ctl dataset panid 0x1222"; sudo docker exec -it sh -c "sudo ot-ctl dataset extpanid 1111111122222222"; sudo docker exec -it sh -c "sudo ot-ctl dataset networkkey 00112233445566778899aabbccddeeaa"; sudo docker exec -it sh -c "sudo ot-ctl dataset commit active"; sudo docker exec -it sh -c "sudo ot-ctl ifconfig up"; sudo docker exec -it sh -c "sudo ot-ctl thread start"; sudo docker exec -it sh -c "sudo ot-ctl prefix add fd11:22::/64 pasor"; sudo docker exec -it sh -c "sudo ot-ctl netdata register" +``` + +Get the dataset active of the thread network created : +``` +sudo docker exec -it sh -c "sudo ot-ctl dataset active -x" +``` + + +## Testing the all cluster app example (with BLE commissioning support) - default configuration + +The pairing "ble-thread" feature must be used and instructions from [README.md 'Testing the example'][readme_test_example_section] should be followed. + +[readme_test_example_section]:README.md#testing-the-example + +## Testing the all cluster app example (without BLE commissioning support) - only for testing purpose + +For such test, having the Matter CLI is mandatory, instructions from [README.md 'Testing the all-clusters application with Matter CLI enabled'][readme_test_with_matter_cli_section] should be followed. + +[readme_test_with_matter_cli_section]:README.md#testing-the-all-clusters-application-with-matter-cli-enabled + +Then using the Matter CLI below commands to join an existing thread network should be entered, `networkkey` and `panid` should be changed depending on thread network configurations: + +``` +otcli networkkey 00112233445566778899aabbccddeeff +otcli panid 0x1234 +otcli channel 17 +otcli commit active +otcli ifconfig up +otcli thread start +``` + +Note: The pairing "onnetwork" feature should be used as the pairing/commissioning method. diff --git a/examples/all-clusters-app/nxp/rt/rw61x/README_Wifi.md b/examples/all-clusters-app/nxp/rt/rw61x/README_Wifi.md new file mode 100644 index 00000000000000..a4f8680917ce26 --- /dev/null +++ b/examples/all-clusters-app/nxp/rt/rw61x/README_Wifi.md @@ -0,0 +1,37 @@ +# Matter over Wi-Fi on RW61x + +## Hardware requirements + +- `RW612` or `RW610` board +- Wi-Fi antenna (to plug in Ant1) + BLE antenna (to plug in Ant2) + + + +## Building + +First instructions from [README.md 'Building section'][readme_building_section] should be followed. + +[readme_building_section]: README.md#building + +- 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 +``` + +The resulting output file can be found in out/debug/chip-rw61x-all-cluster-example. + + + +## Flashing and debugging + +To know how to flash and debug follow instructions from [README.md 'Flashing and debugging'][readme_flash_debug_section]. + +[readme_flash_debug_section]:README.md#flashing-and-debugging + +## Testing the example + +Follow instructions from [README.md 'Testing the example'][readme_test_example_section]. + +[readme_test_example_section]:README.md#testing-the-example 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..4da03b5741f096 --- /dev/null +++ b/examples/all-clusters-app/nxp/rt/rw61x/include/config/CHIPProjectConfig.h @@ -0,0 +1,213 @@ +/* + * 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..116f7a5169753f --- /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 */ +} \ No newline at end of file diff --git a/examples/platform/nxp/common/OTARequestorInitiator.h b/examples/platform/nxp/common/OTARequestorInitiator.h new file mode 100644 index 00000000000000..660a221b668287 --- /dev/null +++ b/examples/platform/nxp/common/OTARequestorInitiator.h @@ -0,0 +1,51 @@ +/* + * + * 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 "platform/nxp/common/OTAImageProcessorImpl.h" +#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" + +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..1347ec443f3d87 --- /dev/null +++ b/examples/platform/nxp/common/app/support/BUILD.gn @@ -0,0 +1,51 @@ +# 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..a9b2ee586d0c7a --- /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 "task.h" +#include +#include +#include +#include "fsl_debug_console.h" + +#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..2e946a385aecc5 --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/BUILD.gn @@ -0,0 +1,21 @@ +# 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..6f52050cd819d9 --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/app/project_include/freeRTOS/FreeRTOSConfig.h @@ -0,0 +1,182 @@ +/* + * 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..b99a5e2c060569 --- /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..1fa42f0f910854 --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/board/board.c @@ -0,0 +1,392 @@ +/* + * 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..95708574742c19 --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/board/board.h @@ -0,0 +1,171 @@ +/* + * 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..ca23a5c589a71f --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/board/clock_config.c @@ -0,0 +1,253 @@ +/* + * 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; +} \ No newline at end of file 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..8e91bff0edd3d3 --- /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..602b5b50718033 --- /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..9865454df07e50 --- /dev/null +++ b/examples/platform/nxp/rt/rw61x/board/pin_mux.h @@ -0,0 +1,53 @@ +/* + * 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 zD=E!S)D6iQ{fFS91^6^nwO0>vbtZG4-=g9oNfO@8lU}DA{Oz8Pq8NavZXbnui271R zP;Ja;(6tqQwEd<6ytTDcPATDx5_;f4&Hbms{B5PP%2M$kuLk{dnD62B#-~v8#1&MP zna+Gf(4T;+LP3m()EIM47N3Df$n60;Tf+44%DCl=}b>$b@Tk74zCZ?hV)@VMiCuNw`*p7f9Au{@3et9a=4!i&? zra(vKX4MVjHZd{D^y>na3$jq|JVF3@15Mua7NTk-D#N(!_7rry09LDZ^Q!<@C>^vGoTJ{uvO>8voC^{<{&aEb-u-G0 zGOx55RjXIh_dZ{VcJbYqPSaM=)K0s4oS5yuYE)p)za=Cf^E<@L^YQ`-%vc{18^C*_ zb2~9{N%ZL$8 zd;{p8>>!%7P*$ebq(#ZCNopMPyxR1XSGN(W{P9H$Xp)Sa9mrdz9`29PzUn2G(AWb! z(lnq!<>nsEhw-9JI8{p)I+|^$4e?FF)GIrgs5-vK>c4Ye799#4bs;`k`zw{L> z=(&x>Lt1$y8uhQ^xHREC$qClgW)-;)7?%w`x`VXRSiQYjxPsgOX;-e`M2lyaQ_?4c zW{|21wiDA{XjE5MEnL=D9MH5B2h3K`zL#d_;)(@?k|IMfJgqRa8q`C3!;ZX@l}4*@ zTK>xw%*Zygq$7Td^~FKDa;MU|EdWZbe(gzopzSF3JXOq)dz3QAA31-6HpocM4(t9@ z$P<&|EER@?k;u$|4TWTZheUK@2E8`;pj@dY2g#~f)uI*bCwNb7*x>F|I4WJ-t6s8mni*yQn^3PT_xbi;0nWvtSwNdEZ3{qM-pxfTN#tt>u% zy*B)7PJwbVc8IEuw)g{+3T>9PlJ?gED4*%>rAB2a&)D}u2ME^M_VPa)G=J?3oC zBA+2B_b7^%Ev9K>USmive}9jE(g*~SXe4a2)Vo}g9ypiM5fikvHgoSGK}$>icO->q zz=_Mo;c5m53Ke>vInR8P-nviGlD=klj};Jal)A7s2pGs{cMkCBSNQeZtP~vOX>zg& zK`89n+7pLVGWt7B`uCjgG30x97RK2PRJ94^^(SVIC)T{lRAEM{11@PP+0ahLhsZrp zbQz0Iwaqc_^gYgk`nwgfDwdpN-P$P25hWxKndu}EAdwlJcl z2|Fx7Wm}i3NBL7h9Pf1zTm;xoP9D-TNG!|sxzpF{3|ENhd-T=%J{S~Q{Q33mxEA){ z%`B*AQLR3^zDMa3C)bJM;^J*Y#Ga`85zF~{k~F|qhBd~@Oc_F*uAmS|q)st+kSj29FC%d-@EsM$>G_t+6&)UO> z_9ga%i00GBV8H|XKM1=&HLJjuMi@6;W_|5Tzcu!;YO!@r_ci_H$5&>Y=r~znC1T&( zvh@L=A!Qew8@N#h_wE^xFqhZU)lIv8n~;~&McWWwj0#(SapRQ}6cp@Usu|UbNznHa z$xFrg5pPV%r=1>xaQbZid~D?4SjUv&&X+iX@Yj^1Nh(biC;Ct`$H(tA6>(fN; zFN2MH9J}Y>Q}vI-2sH)K;j9*!k}t&l+2c zb&qNYOw@}tZhD>`#DQ@7ZImgobfRJ)wbJV8?GDNwJySWh-t4Im?p&6__5f-giba!E z`)w+Hf)|nv$7^pO4guda1%A9F?rzhasX<-3V!f(I=b>qUUbR{`rw&U~*BY$WH*8Ho zb3*b&5(m=HQs0CVdNm0fiyF*O^6IXZVV(^}xkXaZMLiXks?SAWc6C%eu6L24p5LJI zkqqq1qEr`x^)wfdCFc`O*g8Ehg`fMep$9r8TAWMn^C6e|iST&_T4R_H;Pj4Wo z0&W%0h{eqQ@AX9MCO`^!eX=icdEDP^Zwh#8yD2kgk6imuF2Pkd0R+1I1ku2C{scYm zb4O6f99ZcDl5p?nX=S*raf0T1k>jyquk~H`Bgq>J0brE{baM;gl?avm@Ram z#?q3CZ(_?WTq?^FiWflaVv=M*_1ZFaIfhkFJEmS=YG{osZg~n;g*e8pGc&*~qt-@k z(3pRg?dmvWwD(!v$y479!A{0C!u5?g7G84!)~!0M;)w^PXy+M5%1 z5V(A8yu3KIJK8o}jEvX^nT4l+)XNw287L+N4iO!-aw*Es`+A5S;0a^Fo&Bb5)5Ov* zaoNbb1keBgOvHk+CNEC!`$&!d(=J96V??ni`WzJUx7i zgHba#=xSd;D?wz)Xe}qT%Aol^!GDpVbY~j6gdM>+@tn`SZKugxV6+AG<(?+$b=PS(H^u=K%l1 z#;>7U2JEJu{Chg9c=!84B5BGu)CGXNB5Bm)lzqRMTFWoeW$3x^8w>X=drGial}?pA zVNYb_rvVEL1S`37=TREmgACk)0dZlls}8#o!$k&;v9}wOgn*m%Io{2cC&*LgKSxok z2jO2?>+0~h(W;0nUQj+r#Y^S5l)A>w=kj;~2e zj__@fbfn+Sm-)N|F7>TM6CiEWqK|7q0}cn=EbtF97~hkmKH~5{+s5b9IZ@Ddm>-b( z>`?uy8ky$~u0Dxf0WG}%!DC5UMWLg$S{$(Ih@mswhtRP;PcIfVW49SMgp&sa)c9vS!%^9$lzdf-z}_V+%m^ z54}x_>~TmCou^-x?dpN+gLC?`+1*kZ7r75j!RNk_cHk~N8FGSbrM{)7O0X0z)@?iR zci9NHBgB%Luobg%W#t()&GNJcJ8j{f^{0&aG<~0y0{<%4f7>3k!?;_?fz68Y!vpPS zuUB)c8}wW&B@G6o@f&rYHU3uOo$0K?mNFq(#=;2MYy`R74m(@=EPqkxG}aIP9&E>C z8Am_avFDJ{N>qev0|~d%mT#a`05Kgvb|mP4@moR3A6y(Q@LL?!kS+dx$rbCqKdf#H zYXx1mHD6ViAR_a|_q$*J z6WkCZ_%BC?gMqfLvJO;c6s^sSWRzKPTa%#6_ZLa3sfe(!`f$jlsT%~f!Ew-+$JCNpU>t^}cZPvVhvrYEGaiPFCV(hAywf2d6V=u% zV{f=%gie_V-D--|gx%)kJVz@Ms>p3<(CT!4dbdQt=p!`n+900_n}mcu_H<{sC|LGk zpQ)KZjWegEhWk~w+FWrGtsXolNbeqUtoMtpzL>ipKw04F48SUxy3}@Wp`Y$~Z98eU zcr{%gDYE+W6Wr@Yml>za8ddnXzG5S@2vCRgB@Lp_i!yNl>jzzk|2I_e zO&=&$-4E8^PdB+2&7tG5hTbCs?(T>R6b2QQJbuRI$9MPDSBQ5$#&`%k1pq&V@6wz2 z$xwXf@BppyxGthVcaV?Xm3#KgBL$cqj#rDyR9atDlgY@S$Ug^)6LsrymU9iSLXpzr zj9_R9Ak<%pCpjXos*#l-Q^JB}o{3Qbf${)U>yr=?K$|U}6>#J-k3{-yNFt9;*2+}* z2CB^Z3oXog3(U>_t_BbZoGFcsVuG>P=tZo^hO0VR;gcY*_sl`sN5y4d@-EH2Hy>>L zX|!h-frNHrn5Y{6POdr7;Pti0t}Nvp*#G`T{Q5zZGo0yY^5Y9e8el?FkdnMfY2XPI zI4^p`yN_YM&IIr(&r>H$aX;tJF#tjPfV3<;VVWFW$@Q+Er;>`>9aXB3v z|D*iz{2hJjy}1BLv+t$2DDjxjPY=~C!0oQk(Fr2SBnlR8b0AQaPUES%kc^dVodWe3 z#|{R%>w6+8JV%3PV+J%a;IrD0q#)++6%fK5jBXst4Tb4z(f+w;Z^3Gb;svdL7ayxM zta(+YH;)C|Bi>Lqv2whE_q^*teK=YL`g~iSLduZaOBgyHUzksI2*%GyR0iaZ+ii0N zkp3tn1GZ6FkG)>uU8HeTK|jiO&J#*AH2UQ+qbE62I`gxr+weL9rb@%je_h7^s~qF%PpWVpe#8U0^$y1uBb^?vF-+4x-Sa?`Mdg>Mf2%#V zQ7?G-&*$WMn|?=c*<$joU-SEtub8be#a`ug?&b>K7*AS)F{uwTetsA=`p6cS6~#`< z;vnp=oiDk5egaSTKWbtBRJm5^kbd*UD_i}SI1D^sBRMtQUmdPA|3+%5r^55^8XkLb z|1=cLQ)o-RvSGusWrDe-U`F_L4lB{gnaijYp-dE1s1b;I0#@U9^#jl#Hz0dhpK%%u z%S%AhXzJ$%X--|82H_q63?w8I=7aRsGdy2Dqj9OmHYY{lfHbpo*GCFJiuVko4DaiH za#B6b{OCd?_u>%@bO2=xz#r{D9^wu-P9=LBT! zYbBR%g-&0Bthe?1p_peCCV(9z06;UA=})(l`9$3FUXH1#t9FB_N;&zz))f{}%j2LE z%J{Ao2$)yW>F%2%U>?$6Z^CyqBLwhKyZ09uaU9%pTF>{8Fm6DJZh+Z5qLr7s(8AZ; zLkLi+vx(3DmidI+1o;htJt7B-zbu3TM0RhNd75gXR<~+y0Gp!d`Cjd^VH~6qT(O35xz?#|I~7wc`aafN5Upp{r(iM9BqU61@WCr)Nih3xuv_zwDCF z^=M7|(o4qqEDihD&6+PIm&q6pXWZbJ6yKR zJ$>gmxDi%kSJCiQEAU;Uq&tZ=P+2oO;sO8qHGLKumcN3C2%xd5`ThncEkr;FnW|X} zkk_7Ph_X}xZ}C9`k1pk%>9$Yv(pC{bAeIOAGW!^X@(ZhpS`J&ot>z{rC8b-g?t3cB z3_HCJW8h&csMLO-?XpCk!5OWq_X!jgDqdMaSqcylA?wNfUBn;Vjy#q9O*b*n8_e6y z%QjGA-#n>oZ2jKyx4}h(2Q4^d5{f-9?-yn4(dN?!{49zXN-SwgEH-eq0y0U~yN2ha zbof^f0^lb72@ZzyuT8dNLI}FfiT71-guC&oe>_^U(N{j!{{bkVm$I;;+ttw444om5Q`X-#_ZU0qXLa44Q2#%;`= z^kH!Rqv&5o5ft0|73itZOaRz4^yC}RyqJM zv>W+NtNIDyxvz7$=8LQ|D34W_=mBl}M-TUJfM&ZUt$C;qk+$(N}wU{Hq%0 z^B3X*+``&k)9ZsQY~o30+&2u z=Mn!HIES3~k|dXek=!AyqL3o@@iEB5mD22Zc`dJOO87;I9NcamZRk+43q)Fr@$U@j-HKxy-JDmKw^mM$MMX5!iX(fy z4?KELKdGL#>^jHg#8+lD?e6)~8gg1oiB3u3^gQ|f z9>6_cbYgwJyDTCi;?-P2pfT_GIvvPbf-EOYQDV1b0trHrqUiy(SOvA;nfO~EK-yWg zAV2>d2zYiJb`1O~7`Rq3pk^eO6F>S!Z;!Gl+wl)>^4cZiNN=-74q zeCs>g3=lgIb|1@IuvIfB|?YXV^t{-FT8{#<4dPlBQ7Dn{)p5K+C_=!h=>W&7cdd`gJPiG+@0f* z@$kk;bnER3TRdI^t`8?@Q-s$r4;)cgw~m`lMk#(QQ72dt1yG&ySi1b?V-}+XjIW97@p# zpZgg~pzM@3#_=e4LLo|mfl9K7+w6#1HAF(eK0^MVd$h0}a5jZm%wH2^b{(UtpLHr3gqzi-?7zj;vP1e|!w|da&dCn7gq&2gel`)x{!8Tw&@nGo+R;t0GEiWMjFfm>^_2us5$tK}pfOtb4k4eQH-c148o z0AEdiEkD8_pJcWDJ7yZA>;!D8VK^D^r{A$NH*A3tJfZ1+tt_dIL6|@n@mB4~7$9dn zV3~} zgp5~mQ;xTZnfSr)cPHU@mG7a7>8!87gnlMKjqw{)?QcW5LD~K~_&XrGo`dDTJy;yr zC#VO4-noFUM6xY-x$U)>>t`s%(@JUbazxDxFhE#pppUKx#OF(SUloe{f5r2_bFPW$ z#Y5Qj=txr5f}M^kVbD`w3#_yIcUp(~gA0sOPR7WeLqjLMFV9i&{(7g4WKyMV8g#pM zaQK(3MVYR{L1+}a`7Im1n0Zg;;~!0tQ8Z90bm!%sqy^lsX~5h;>ibR|Kvw(XWrHKw z5C1};OR>Xq-sQUUK7D>+V##2k3BWcy@E(tI{hT>u!gZEvolCkv1#@(W_G~5w)X!mK zT(#4{*X*gHqGGt!%X@9rAIslrU`E9Q-eNb1os+4<&=cG6e#kO4GcW06p4=8Zxj zuWp>oa_Lv(x>k`VHRpkTG~r_#$`_vpFB^)r0!s?&Int`dO649?X|uNc?jJ1QdI7e~ z=BNcy)@sNg$v-;6qfl;6VjU$61e;vZ&#|4{L3g_(kA~uBOIr=*HN;GX;Al>CwbrzI zpT8J=8!yrMRvLfh*T0=7JK}j55@<_BTq``PbDr(W-N@MD*`k9{DdD~_n zT~4^k!@D_46r~Te2ahn6#s~(jzMA}^#ZhVjr?w(&ikHqE2 zo{Ge{&Uxe2M2K6xH`3KooVuY<>o%`m+#!|fH{Qo_-CG}H3o;);o>VKS^izUXPVP=} z__xxyPt9EMoBC-9O=hKEMU82xH&v9KRj0LIa=Zw?t+?T*9!aSU{UVuj?1jJ{?(1sd zelKjM{QS5}cWp|giOSFOc zd(F+aTgj%}D3DpSuA=@gz9DAM#%OB++<2ZWsJvx z>juPsNgKD6civvHe5D8dRT@v<4!=JDlRG;ewBi2_3M=~gtwO;FL0fgZ7@iEYfg<8@ zAjbx}o;4tMTgZZeNQMZm5sU^S0J~}HBdZva{t_dwwoX+%=Kg2`zo8UcUWSgZ!04P0 z)h@nY-la`QNPL{nVNOmnx790liDrLLh@2M)|N14Tx5h3{z{y4FahIb7VMXVNxbzb@ zlKVt*-JzVDGr*$}6QgrgLm0jLpfCR5ovfU{p)p+*$#xQ|o6I&P2C{3&?2X0ttz6;Mb zpYIcYi)2Uf0CIwf`ZvePq)&d6_ZzMNI}jKMhsOo}aB27jZHV$v&I;r*WGv^+t%-Pj z-`ro*2K;u^LuPx^W#;2NegbNt4#>eRa5=;;Vp<3!$tAOQ(ur;Fq+=z={!5ja^~?z6 z)j|C|NHjyv{1k675g5SOQT8aIyGyQc2$BV!W5p`AHvh${MTKdBjz74Qj<^5A|A%^e zE~?ar$}<}{6=agcHMLA?SmsbS*63JY!dqI+W}0nrn5D9%`pM>nM~MSt+QQJH=oD|FjUbKw_RkZ<{6IrI%Tfns5)Hx@AtmyaT=XYlb;xen+}Uj$ zi@L#Cf_1BXS;O<$OGH+|)DaB!%sUGb#qDqe0K)cUSu!|IUH= z>blp~|4(FTp=)3lcwwEEc(9SH(Jq9Y0ZF?5@3% z<8S5S?*7HcbGRs)*SjH%_n1}fxQ|aoZybCJ?N%phMD|juNTuxp;IeVn#D{bNUxSM7k-oNaiRfNeQ{>qf zg_PohfAeRKgx`npyxe&EN*neP|H#N zt@Su^wPm9!Z)HZYbZ%8pM0<>#X>|BW!rJ0pMxN5>?B$ekpMud^${{&o<7fM_RvlhT zX%?Zi0TvVZ&uD+99mn+@^K67W6FfzL#WmY&E{p7Z>gTuVJ0CSdAM~Yi#G;0Td|4kW zZ1k(W-M5{P+4ht9t(>Z=+Vg^*Rp^S#h%xnAJ^-P!Veen(_Syn0?jk^O+pqk65N zmuMu0yGvRuN@#f3WYksVK*V$RBI`B<^yE;v`{(z1&ThTYxBV}XY)eDk8yOif)-s_c z?E?tABOQO0)n1yEEesa$K&6=+_91S**iwDTj)%nv+FB&zx_aQIVPUTW#;ku=Z9=J z=r;{cSjw2L7~r^DW$D82$|@|KtoRn^{Lpn@HP*t|B|sczWQ|%@@NXHg0rqSxhu} z7wI&lqF&(GM7&Lq^oyQpsLE*gS^cjXVn+pl92ky48T+VDa}ic!4G%-8^2tv16!n%S z3|io@iQCGJo(zAH)2$va`vYL7O$M0bMG_h3D&HRLmS!-46s9Bo0gx_FR*yRC%sfH; z<^F@%Y<745a&onB)a`uk-jjm_|vhui!XYi%y^8pR}m%XBQjrVYN(o5zanB^81YIyBdp;tO= z2w9v3;nC?V!DiSmcdTKP@gI=8N3|@Krw&b|)SHYWKj|?tXXQ=&cW1vl9qBl(6nZpp zIejUiYUWg3u2|ltH3=)CHSQJ{tCZ~w;_pl~IEUQ&9(XO~_4!>smRdC{stiMYPzB~$ zH9?HCZ7rC@47O=7Vl1+s#%>KhH<)-lC<->CeEmAZH1jv>NJW-dpj^IOg9t!jk}mAr z-0y$r;d+lu)<2W{ZnC?3@YSXNQJKF%4<#~+;lA26qF*0mkdi^3E4wDm5eWE8hIx!e zO#@6RBM|iJq|l!2Md!z8*MFH;T&x0y86KYoA3&#j0NUKByZ4XmxmcD>kECoA4(&@< zbTsgso9`5mu=IUxV>oBQ(vWzX+wE!=-%W~Tg!`(^xTCU2d`>BXH&udb&wLfq=jiFJzN zG*xOiM4Gp4&IIN3E(}UZotHeE!ca4^;6KaG}IlalsFL(USkhK}G!0)|Bl{x5<+vr-68 z!UOA#0d-UB3Fga-1J;7FF#3ip%%4UY_^oEZ8}L9FO8$zmiB5TQG&=<=jBi#d3t@zO zr%4HY-ZLt3*VPNT>is)~RJGr76q}}((M*ug)^GWG~kC|wf(+C^-?V|Bp%}xQ`MoNrih{VQah&32;$Mk58TGU@)n_<8LiR+U3fnL;V z>csK&#EAyly8kqqKR{+>3p9YpwT*YVquR$>@-7%y>hQaGk@#Wk8g5)yTqUemw4kephmR+>Cw> z^rg?aoWk!DYJ0U_+={KC#h$1X$(XnDlEG?N2k4#uZZ!U$(HOt+vu>R+5x4l0AESqEz zNV;4Wg^YF|&`bca9>_y^S{KO=3YSax1mE-19RRND|%yf zWrqsTsiiR`y$N<>i48+=FSiZGM)sfA4}Hv7|23w-bABOca~{dsA5U&0x7RyC+=a)Z zp&ysx9b*P|*+(>c7aJp@q_)3<`hTu=lHp*FT4+fuEsp9n&Q1CCe{$|3T5&XKYrT~5 z5<4yFVy|~vI`OulpS2(Hxm4yEnh6GfNv`sd)>g+%`B<+9;1SUJ;a)$$ZBOp;m=HHOimK0$3}Z&}76Tkp zbuc+A+`NoN+hnHwQ(H7v8oO66ut8RUm)NnGE zxQ`(8PKaLpLfz*cewLq5!$So>pJ{nFuRnQ{%KbqRAP()rJK%SjP9$dWd9ZO?4o9{U zD#ssj>`kvpx%R5oh|l*sYarO>w+q|EBjWDoR1{v5@Z2{jsCQurr0+dKH}tx^lqpSP zxX~WPuy=Zyp|sGXjGH83Q(eRGSNZklOn_2=Dsj$qZbU|G`vwobyvM_nd)h3Ygapw? zN<9WVFZ_ODmt=xe?VE@L-Ce7fl<1%N$cSa*6IkQE&CTP8%x7YD1P)*JHsrNdWprE< z3+p%a(Sa=>;)aDWezKY~HR?mE51eBVDqJ)j_G939Eb)^~QT&YsTW37{Pmx5pCd;(F zl6t%s_Yp^&i3iUp`mEe~N&(Ia;OaW?+#nJ|chi&cH5u2QYFX5=YRIDE)-|Ja==1AF zwXHIkw*r!8fQb=CP15+RoWYU$J>i5n_JFM|%vDOKj4Ulu<1UiTg(K+zwOMstE{tV- z>k9KOxabNSvn#DsY(AMaw4@L5!9|Q*9$&`cAD(H!&sr`^RxU5kT=UK3?BOPMMx8$d z&LXTUosM62ZjXNYRvGcwdKY%Q+H}8UQCFneuKaGi&2F2Uqg7MX0jzD=>V7npV0q8+ zf_IE1+vTdiqr3z9)lO9`A{+>1yS4f$BcfcC9o{kb7jUyZnJVro1?Il>z*3J~X)N!R zM!j7wYGT@jn`JHFbN@0z^o(9Uyb^TV*Do1ZS{CF*ct1pV~pe`fP!*$3@Q2e8+#}3_mrb&UIrKo#>pE> zx+Q{LhGQQ(1Ed`d=P|X-cpX9GsLk&vK6j#v5q>}fXbmg5oWv%xfGLttN-n*IyI+Wm zh&rxg?dtBe6Z5-%5CKp^$xZn!mo)*DPZXoS`TR5$<7dOBG6d_#!-+Q@R>!Q0rDSMj zU?}Rxt{f7OY2cPPUcCHW@38n-M0pz0P36x}Gx9#TIW3Stlp4eXNid-}9=>uG@550?U*gBougdsSo_;WEuzp7&>&@ z97cJRB_5A`gd&9^Gr9YjR~`KdKKkDgMcs!7?oP$=Vfzx@)h6yHpZ#=qH;PMkhhyoE zJwD@z=(;_8?nm;tvD5Pb1O=4A@oD2VR#{6p~ zdmnFvLZ&Q!ea|HRYg>jH8><$!b7P{nO!K2>{(P}6_BGg07IIHMiXfPO`z{KEkBTv%>`xpwe~#B!deKnPQdKO1DKYQwZ`R3x z2#-~7S-yF)qih(;dmM{m*KRhSTB{1{q}Esg4;4UsKSr6n<1Rt&uh4culo4wpz-+x|$k^NdDNye}msBz+r1zce7!Q2cT@6Ux67cneD-Exa5gx_?$O& zT1sWRXixpD3{oDrAE-)&tl-t_pmN!ay9kg^E8R)uKB|_;B;BK%hT{AMA zT$@!PIVW%r1xslv@5zwR2h%SP66bh$ghDzfUGyXaj@GOCi;r0$q?-VFe!Q1)Sv-F2 za900fH$mXdtmF)iHDa5NgPr}Q@$$_N4x5vjk&F_X6F`hWp*+91^VUFEXDxn!Ie>|7 zR&~ML`D9tdjSi?Ru5zBdB7@kD5j?;ZUPouMjvtT++CGJuMy=$=K3D1NdFk!u7oAkr zk8vv=L93asTYsb8AX=Ma962_HDLcnmpZiGnW^K{2SFF+^Duv z3lTJuxlowPG>lSdHe|5IQhhPPDBgehsY*rXzRQ|%fK`eU>;Eid)3Cu&6pDWBTI-04 zwl{P+3GwlwV+IcZ)>lI#e_gjT9vu^>BggQRJqqoUMwe3%m_dV@{JASCB~RhvjmmbQ zcorDwvf#wqB=i}~xqRTJvY2t-`S~z9F6QP!tPuiCX}CqmbRFmGa28%5!r&Z*(B;=Im)K60y07QH zQIlvVRKcRyBm`zi0&uXBBY^Kpu+mT811`PM1*?gKe?IX)w^ZmJkzZYFG%3S5&-okB z(VjaG-vcW8zAKo`>Lnid!$3np8|d}a1C6eGMuQTUXM1%<2w+fj_`x3rCXJ+ZP->ro zB*DY&<}Oi`#{+NWUgDPDH;CHfM}K_LpV8`fV5k+0IXEf0XQ)4q9m9433>ZiNgWNf7 zF)DOXElllauxlwN^>Db_7*vwilz32@G>}}%2esaR!8d&<{cZ;29KD5ZCM+lb>cHSQ z)|PwmgqQ(J?U#PCM3PHP4XSRy2#~Ck{CN5PF@vJfTdQP4)MA3I)8O#5cXAInql+v) z+-x)$Ujl>4kNtwe*iqJ7iZbk5c;lG;#2v;K92M9?LSRM6hCz=|ROs$gEImHdVL_kss;3I28FLlNV3K&wEb)|2FFw8Xm}re}?yuc-19&#h`fNV;C^}k5mq=p1e3>%-w4*Lqty6+I?70byyit55+(H+R|Jv<@LZT zdz}jbk5>>Zt$0UTVYk?wcqA3TEc3trqq74TnGbU$MfX=n9p07le!5+?*r&&fSXi(I zwqFI3bOLY$a=-Q8U7UaVAg6Mnv5)0qzT0Vd4J-(bHClv=s3j5dL^!G;h}EO_EK_QOdcBg(;Kdfs2Myj+Uqu5g5!Hljfy?9q&3-? z6LqzN73lZJ`yndNUp2K@+wG4>?E;0=Qt#a?yqi}iF7*ttJMSzE-(MNL9XD$1qI`On zHcD4*QI8MSwoXr#o0G@Sy3yQ{ramF6KgF(oqwJ}oYPKkmXv^VG0Zs3m=egN^58Zh> zV{y%K59;UVRqKD!f6AWbKXcGj4UedokkU(6vsNI^T5B*fuh1!OVFk_OZ-(EKe_8r7Ch?WQf1M??%t1 z4VRA_UP~19=m;hmY;t$5Un~7I6#EM}#T%Z&{7jo zWn;O;0^8i(Kb@ElqWcg_17N4^oTMBNfUD>=u7*iOdHry($x3UOM9JIu2`RE<>tWAv z*}8AMTA8N(+^(xniFglAYkK3*E#5+2N4iWOBj-C~jS_kBM zid~u+|A(@#j;gxb)~36WZUjY;k`$z*8>EB{NNqwk(%lV`1}%sPNC{G#?ozr_Noi^6 z@LL<+^WJmLckdbZ{_Pk7zqQs}b3OA38qy>|E!g#Get&bC|FL0v;$9z~H5p1!X9X?H zj+d95)k8;~u8$rF*u)?1zj@z~GyGzGNPgSzC)Cqn@+?^dX4Zp9lmL;uNoQwXAXr6n zu>*{qJ7g)5`q{oX<#a z!zFzJDa(Pe8T3t3(p~QQ-Js`u`!v+lZ-sv!PCP5T0LlO*HMLk^DbZIF?DFWZf`fZ( zsBKKrL{GPgowdGqh(C~Mf=L&I3rBy2yqOQkelr{AzHcxUny8ljroWY8=)ZH9Rymo| z>drpe*Eu~4r=Id!loO?=pJM5i)E=_2Rz{E&nmR<=G3xzbt)ci>(xTBzM6%xpGq{@4 zCtXy6B`Jf2@Q={VlqjNN?iBT1M;OHS-u>r#hIjz34Ad$}uM5kX_elwC4o3IU{Cw$- zwJFwJ@Dj{NXc(0zUcBk_k7#az_8-OUGwgJB+5yjxT?`;+3XsHVvGT}legmESV#+Ic z2V8EWQ{b`(rX`P~@ewLblr#h#5ZIoW!2r{qIbFo{H4rE)>;DyD%|w?r?;CeGpR`N& zo}%yr_kp_+pkGCN4kqBnfhprM0^ynDu726^>*;ZZ#wI4XiM58~A%0!yRAt%18r0Lv zFrOrT`z-6*(h3-#6~NTZzYZ-pmk*f1UOn65+>`A%+~iZ(uGY7(d+v z&AFdMj!HT=9&7D+j~VOzltnF~YuSZD7wf-&o7w>pMd>X!hIX^l^)wm_cOAHkS7ymO z;b-|WNj>ycM{Ap|?1JB#ni>>0HeZ@=fDc3TP$lg%q>7#RV{x$>@F&R;w+Eixot-QN z*FGaUs|XMs24pB(QJkOD-|GsRHus>rT^sw?UK{&+pq9{-s}1iVZXrTH>_1N0Z}i5K zIPCE}v2RaG`CrVCO!?LtyPj0KD-@W+Gw}w`LzqOXeBIh!%zwW#kUAG_v)?V{9aj8; z+923efhc&_^Ylu&`?gFHDy3kkFrZ3|fAd#;PW{-WwqAt9&MLNz*%qj! z=N{k1I_kTR3z%vg^_Kx_*%M5+K8yNDk7D1X{j68ZtfPhz>jH)lB3JqUOer%bh0KBi zND1IhM#1iHZ|;s+Wv2+<0cFsBu2BeRI~uaC;|g?ELA^f?!;m37a_~d`3g|ka| z?pqYnt%Hzr5!V-dUFARcqzwPIQtJlv#lq{=wrUKC?_#7C!9*By$?Py(_0-R-ilQ)k_r zQ6a-OP50}GkI_y1K~he}0ne6X^5p*f#BBN8j6}H|w<^2Vd7SB!+|M9a1r(`a$H;$f zC=in*S~KMZ?e`4a%gO+qbZ9NQTQK>$mxp;&2oZ{t2D^k7D>=UKylOB~6rGzageYtdS`~`c= z2*L;gswr#v9gKguN#1h2tpcN}fy?FCmiF9g;IVycQ+UHNaxu*MjogM+ctd7DFw-pX zPipvSX%tDmykkA%7&VbV8?J>><1dtCA%{)89CXpi|ZK0U3-PseQq-Xp8x$>jSUIGwO z>5Fq_IV;*(%5P|2@gIP>S)`CxCu83xUs~Atd{YX2m>mRQ*f1Gs-43q>N$ci##$J?= zg~uXv(%Fo1(Z~A>ds$X0!;Ip%W|fRDV$`G`QC9F3Sm911si#alUi`$b2a_WD-ue<_ zIUTjM$HGkQb84+f_u$=|g0Vt+)8~TL$}os-3EuhNBWm%{fL+>-8R)`P+q{G(?be#> z7p8~v$P|&HjtC*O0C5n{;Y59mLNst|!MF?lG1-^0s z+apBCLqb=yl9<=m7X8B z>PqU)EK(96S@~Z(on}1$9v!Jmvaiyq>x#9rD9wJqx$xi`I)7lkcEtXYpMtMxMcWRXIfD zlGVm55MgIy+=JiV+Sv`l72n+X268VyiFhNWtKr!zbeX)n1^LxHKHhlL`ZMWDpZe%B zU(tH%*wL^xg#57x3WB2s=QbO(Qz#{QKqNzsf)+x7*V1yU+hEdRD^r@N`MyLlD;7Q9 z+HTwJ+iP1SabN6!0`2au?vM?ouFJx{K;-}ty~??)rz#(1%&ZB6WpI8L?^~>`_9LDc zezT8jJ`uN8c*mN};yX(S2uD$w4u<2tyigce9ogk;JB9 zWb}C&7+ndS0%&EF`wHX}B?2{B!Lwx$bf#}xGoJh5Lrdz5V6!N?$?53{W6Hm=rCSCH z@^}Bcrr$bo@^#TX=o;UDrE~wj(De)}E1U+Y-LqLE5a2q0<+Yi-)Q4om7fPT=2F_{fdkYmJF@5$GE3-HS9N%-y5|$j)yN z21_>pdaZALeLCk6AEDE2zr^%Jr&;#$l4 z_Y<;@9Fm2@wOddPy5XPY1LEZ?m{KOHc;8x9^Ps8*2Cy1n0Fe#vOBGPAb>HFYX;{K! zy2s6}jvpGtlV!I{Rmuv|l1kc%Jr0|DtUwIct4*n2cxafRSg7D0z5_Cvba}am+HbW; zGi@MH7j*tH=wH7XfJpv&Eq$M6Br5sbkjgvtVnq7pRp@Y20&laLDc@>A4?+sEc`Q@9 zjCtC|aFw}OKJPqQc88M_9#Xlr6eppZ!9tBiwd)WlgdG%-3a2Cp73uCt>&%j7k*WuY zqHQ_zp+N(h8!f-#QUla9{}oZxK`#2GvNDe7wef%ZVeXMaV(CRKD{%oPvUWdNTSw=f zdKAd&Lo6NfQpc@_NZqNMC5>m#hmWLMr^D1F(8#fvzjj&S@wKk<%%=yH5h?OqbQP%& zTm(thYi^XP+D9=NP&$P?eUSVCov+1&?R5q_g$Aq?74kQn@c%t&Uy+n{=zvt}uo(b+ z@pP8oR?^23AQI$HHXv`a?X3W9@Etn_G`qH51yj2bX6%g?5I6+l-^#~yQD3pl^4Im{ zW14u7*Siy0P-Z*?#%uf2wj~{tPyX`{9fFl!C(kkJduXuWIGqDAZWo>naxpZx;x`X- z0F$&SvXg3QPHCwo0%{YWa~bRhfl$Nmym*{RHl|9=!{3LQ%2B?MDP`sTPv5tX1oE2L z07>L*_i3b%?*X{Gv>he^A|}UWJ8f$q4da~=1aWVy(V2ErQ&amZY4+W~+$gJF()f-u(5Can5KHJJ+7xmNLh@fK1-eOelD2wjt?uxKUltDN! z0#xgeY5_hea)_uS5>5hIVIuRWlz_n(9vh5nTZk}GOSIurE?||AOaBExEn{l!&s$16 zVX_g#fCSI`E1vi@71(RDGuO}vUHHvwOThqUW5d(H`-l_fnZ5Lvu9T>L$J74$EV$6# zoQ01+5E&6Fd*R=SvTn=;5kN|P)%9@}A-H)}54`|58|?o=+FW;3QiU==6r59osE@f6RjWumV3CH z?gNpN?zs#eHNV0vn5v}>m)|%%3gyVN>KrClxTGl}=3FCNvv;z^f|0J0d501an#l^x zf9|0GORe;Or7jC!@AbdjeAWY8o9{ZbsuaQVUco8^Q})> zF3RmT#<|;1fFV){HtA@zeX<<^-$DZj6@7kGm6}QoMVu&f`0)` zhgMLIv5-`k%W$^hcs*l_ovCFFNH{biU=aU>IO7`22}wy^Z+(G8TBimu!`id`PnVO1 z!9h>1n4UJM{EV0f^nE!7_e0)N=E3pK95*5>k#FZiKfr}qavw>Gei=ZRDt!kA^Uv=* zib%*s05fje-)#`UOl!1naylU&xvq{*2MiN|%G~6XfBsgWQ~0y#YP0Dlcs=Nt9fPvU z1p>!E15bPTG8>NTphugXe|ehRf}~DfRB=5i^MB=X>61=-pF_86MZ&vr$0AetNs3wXBmhF?5k?=YXGn2 zg5cPGjz^&y^1y-4UfLiIkPY1IrBx8=l?ly3&M*5Vic82ibQR_reW4qp`P~F`E)n#1 z)!xMeMfkV=eqCeJ>N^fwt#=a4qG~?ViMr*%5px#ooG&d6;kM*kqszc)5)pH~LEq81 z=7Qu%Hc@FTA5Pc$70i0>Awv0>(YNEk@atS~rpjKg9Mg*gKQpmdi)_O9K-*k0Y@(MPMbKOo)i~bw*#=!c2pl?b3 zmi~l}@nRT8Akga9B5HDRvgelujP~iu39}DD5i~s(6j>so2S6WUc$TN}$Bxbgi;D=u zZRbUSXo8ut0|eovI5S=ATKFELboFDL`2K|Bj^xiYkpD-*;VObA@isIsYh;id>y<&h zBH9hy^S#Ueq>bU?kZm#S$mOBOZl(Z3E9JKIFWmN9TDy28<12Y)J-{_KfhW|P-uMn^ z1Pc6(SUBisC?9!zx!6x?szCU0@^hhliHgTdBfc%iR!Vq&+%LMrw$KGMvK0%Sn7mkm z9)9M3T*aqRTG6}_VENd;oG>uNoVw7buwkS7WL@+y&yp^+)HB#{kHEA+USFs5;-?j= z#rm|}@ChNYaCPrgqvqAp4;n`Z7+QT40Xf6Hk@+)d+~0E*0+KB1i#P_2tKqPyeAos;<`bgL5b**#!7a9sb60nL;9_9TFQq` z*&9V0uD>WmD0A`sjD(H@E9hI!XTgE-km=%4@!&6Y9bAw##X%rS^R-vIZG>ZRM!7W? zJp5MQ{0XMt3tnNFSjgB}48uwH^|QKDk10Z)xTKcu5Q3OZ5-#z}-&&i4v_!J7mcb;6 z%XRfDuL3YWQ51egspN9H4|RQ(x~LTo$O@oy)@E)8F@6aSX^6{TNm*G(eEZy@-JJ9h z?m|Pb)zit!H8WB)J7pH6I;?MOajTRWRwq{hUqXCG&2YDGzr*#AWkw`lb}K&zBPTyP zYh~sZM8u&Y>pve21hr<|cU+PBdDS^1d5=2KDAW~}<&2>EF1Md5vDO+MRaeSCOR2GY zb8$YCmfg7BSrQJyh70)2Yfmv-O5RD8cHD6>u}1Qf?OJ66`R?q=f@@!s)8zt^Tr0E) zhp|8Y&7{l>0$STzh4eegbP?4Zb)p~oLSXhZ?-vRn zsfA_Y0q3F`Gu&9z49>PN{PGpl@5kRFx{y$?elZ%DzaP@wN}=eugIB?sf%J=+#k`4! zzb|?jb+>3_mC%fFI=4iK=70FG;S><@4Ho>IC||!K2~OMCTRn>j55a@lm`lhop@=N) z=d^?jJIz4P@K{aR9d~;bI=y1UNYQ94DZV`tI$Alj3C|IN%-gS{CxZwwY=YI;f+SLH z(uC}Fxpz;=@w<(8SqEWiuKM~Z8+d6mZZ-!s&a2v@z0Yg{ z$srotfV`R0LEi9>ZwtYV1CBs2M|&inP9FM$S_Ri$a*w>`G~_MmaQcZXn{X!oU2;ir zG_mivUdgnNlz)pwn>0$bAkn>mp$?#?hn-`c=Y-3qfZ;LL8jchxofn_cPF!qL7DxxM zj-~@^P85ahnr0WA8GK0?6*X!IjMM3@fzcDB=oIPL_rW4>z+~V-sBh>Aeqfu=cI|XX zAiRS#z$nDx@}iALaK!TH*Hq&qP$NoNv;p54zFnjTTSMe&Ph&S9`-dauVEHWn4z4;y zaE5C6`qjVX)@05he zqK!CSInpId^DUZ^q7DL0weDaca@*sDP1#S<5g|!08`S|S7OW9cW|?}VAsJ1= zM+c1l7}4faQ0&u8G777aTieO;jHGJG>-ZIDgkBg%f6fJ4@KKnCzeY5V;*qDNc}oy_ z_sDHyS~?0E)hw&mQSs3`SUz${&=HIYirA(Uj6ig$DBchpPs@1A3f5O9>Yx$Ke*MoQ z4TQA%|CgN3vcTu{%v|6^c|>ODA{HQ11wZ|aio5%SmA2`1D|r)Jn=@LvgxD;7ljY)s zVY`6jrHHYNas=lZniNtXPsmm>BSR}rZkDY0bT|RK_>!K3^Gvaw-1$6yh4oNYHL}w^ zcm+eyvF~IR>rJLn7?_`Uk&|*W67zldG8Bz6Nq+&48|2AQm}{7+}8Koh!hV zs7VpV8+eT0Zr2bCXCe6o-V^cKB!A;>g+UY?7aLI&cU>g+Hg$KQeDv4aQ_IFH?qP>t z%Aq6%#r_0scPgw0nc9^F7Wp&z!YH2iG6p>p2!@~K(9wy$vvN`6eG~Gq2-ytXZ%9V0 zn!rURIgtoL&TU+@56h(c(gKK4Qr6tYXQd@XQN4C`a4I?iEIuN@UCI=n86DUY5wsMs z@x1sKNtT$F=z!gtRM5jTpO5gO`T<*T1P&K*T4d|wEuh{Cq>oJn9q4^}& zHtq<0X_AX~uM1KONd{Z>_>kH!ALEqnjXDpD!y!+3^>^4&~qfyHAvh9B zu1&C8+9@?2WYn!0a70U$x^j72G$^s!r$2U9_7yJ@HV*V6)evFvzBW{nz$6vbK`D2AF!-790 z6{Ffo%`9OfIF1VJHxIB_L1M@*N-(!$H5cZ=E^7=0^UvE4no`1_i44AKDbY9??o#H? zb?l(1zX~06z5l4OV#u?VqWU2@-TcJ8`rVof=C|9`v?JPq&!ik*>@m2ui6U_)CbJJ) z+P7VUr~iuSEn;(OmNrz74rhRO+upWaZ!`)Ms+0wj}=vbAsiG)y$r11jerDlC2W!0)$l0QM}S&E!9+DdX-VB$)9EN}NM0e$pk?ST zEdMpwA#MRiwAX8^SjC$0FX!KyuT<7Qaxt{4HyBrp7f9MX zUFqFah5gOqgbtM8?8<*EAt_{+gWmF_`E9fa9sM05iQOJk4OolE^NZKX*7ZK4`t*W! z)7itkR#Te@m>HU$v?`-EU3^fZn?Nq*+EpfPXMHPw zc{ag}q)vFT80N(r%g_}4*{E*(;j=%BXvanuS(fJ=-@-O|UGo{v5$jO!?BlL7XQ#Wl zM`*?+GPk<$C&AulM~qJvgqM$qfY)Uo_VCc|o+dY0j=7+dcZ0!ER z9#lKXqdCI@GD9(=_2uO+2R}#`kQR54yEGeF1u0l6siK{Sd__spi(ocj8Jh25cu|fB z+;~yuz#7hR-}2315GoA#bf;6CqsE6bx?<^8gVC;l8pHM^WiG1s+qOoj9Nk2k<;w*w zus*vLfjz=U6kUX~JcuzYr_^qvJ@>Jo%x)%+U69r1&$NnS>pon=pSP}uv=xGXp(VLy zxZ-WfsOj!L+asUiQa?+^<%|P|zaLNKzdSUOrv$QHB21nl>{G0-aU@Xnew|0~Yv1@YgP-RVc+mR}dC7pv3Mot+AxCHX|0}GsAhDv(2=LFiAUq zLxuvZWiQCrA&e$^Jr`(wZLq;iVaE<^oRIif>9^u0l%}o~HIomVS5%gnf=mK;>80*I zWP{%#Cl|p+WuyY;M@akgpG{{lLeQK$iSf~>(d0%2EoFS;*C<$lrRX+5Ewqh!cZ*sa z=z32~fR_VF=3&= za%~Oc@@+5SmlI}D^mh`A0IT&MEBWuJogf7SDJ(McO^iw9jk%`bg6C_tWR9>ZNf|7) z_bC7g*k}haq^2AZ94Na~(w6gLLHW0dM`UKC6ao}X)ILTm$mJ0Rx>f>1S4kfVtOu4v zCKQdQD>MQu-x4u=cMN@)AHgjA-qcEWf%N{exrm@6aGudmN-*57}3MrbcSMM%Vw(z%k z_5JeHU|rlI-R0cuvtbceSt3*RZO{-S(8p^;_uGGsD}fkB1NOi5C7aS7o()lMm+-od zxXCvE&;KU~t2U6q$<`|IQ^j0AD=T~e+5UA{_DFo&vJ}0gi1;TZqcwjnvi!xnlBO#I z`~#fnyIBp9ocj9u*j8K2DXM_1T6OakLRi#qiq4I|4&;_5Ub4z|f6P&|et5rWZ7&rz z%P&UXwI zVm|`TFe*lS5oL6}(G>UNsLp^zxTluaTXW>rV%EvfbdLGqt2{steFg#;84hpE zE%9H_Kivr&!*%ZV33|_-?R?_aFOxyoaE+PD$XkHf-PPzEh^7`oXn zrH;1V76$ni8`dACYk|G#TrqI#_4^C1E(-Exknl6y-`^iCdQODSlhB}FQYe-?FX8kv zg0Q~q%NBq#+q2VLXCfv7t0Flkt;+rSKx(adH*@kS0!L&eF;(*CBTVk%e&w)P_QS+i z)a_S%qwl#A@YNdQ9dqqya~1VCnt!@8OXqC|JVG^NW$SIR-6Go)WwzpQ`rE+BWz6-k zomBnWKj!t`-$xR`V)?(Df9*geL`5O41aP~V+;L$4nj<2DfJ_5phfIBdMB{D1hn{&p zzrE1RKs8no!!Mp!r>o0=P2b%q3!@VAssKjBVg=?wcBV7HLdiaQe!&dzVtCHU+8HAh zKmvx6_H_rb^n_dS=3z$X#y$T%jcz+m;_9g<|76%yOBCt^cCl|d`IvFJ^QxNbAK62b z2zPZ*=snVX-+X%SXF$$nn78fkGJJShgk9Kk=X)(|!m`|Ug3DC}IIB~?p%2@1n|DOh z9P?2N**?R)R~Ds0&CWoK&e^YITuiFbJvG%bHZBH+KW1NjNrEa z!igm)MTm@b*8n6-4Q&F8*zF51x_JuY(a?e7!`Huo`AGPWnHFzkdNsu8cJ?k2y(@KC z2mF7+S=M*fvs)c zMoTHLU7N!Xf_8GOLJy1(kqE=uqzPN|`pBoTRh~g)DXIu6fIZjcb72XL}DCk5;}B%aOD-ZUX~S6V~6 z096=vr=_Gk_Fn;3f1kJZnl4wYL0-TgC|614|5i10-2U#Nvsrg4f-uzhNn6|d%}N9( z8%3CMZ{mEVIM4&Jx~#d562qM9ts?JzH~Rsto5rw_oS8pG*3_OsoFF2|E>$be5%K^E z=o!c-%mcUD>k=!Bm`hnF-Av#Nyyo*%WQ4T-<;M8eTZAs~U%-pDC{6}oh&J3IE;0T- zQ9%ABbgvs|8pOB(&sJ&trK-~w19L*mDs+9rQ2$Ncajw^5!>^KOO~wtA=Fv?@YE##P z;U#7`<2DN1c4cYeCs0c+vaG3vMImCiT96un|1bC0f9-?nJAJ}5yVI?n;Z`_TZMk2* zXc#eg{lGwp+vs-(fBPQ^Z+m)rozkv#(WVruajQgs%axje=<-J&jdzx33(I!c6p%C} zZ^^Vo;ig3dtS#_mEfcKlX`U4}q4zu${Q$)hgy* z$5JT6+eQ8qNKS#PfQ1U{3FhxMZv1ZY*BaGf7D=2@Optx6(9^?K;}oIa001U6m++Ix1Zd)^{C-4?7aJ8OGKucGJ+;To8?>Hss;ncHeZ%=nPWyaU z{Mc^*K35(v_o$P-)#?%MP%V18n78hwnoCt?=APfoF^Pp>c6D}VDppsj)862ZpL{gsg6KS_rDqFY z&^V=+(cnp{M?7b><*(qW8keM7eV7bBnHELc!%Intdf(-uY|WyAx5eVg;Oo_P)%0C& zIjiX}F5Bh=wBXuZ4ZBx~X6f&HPR;Mr*!NIyTbn{>lFC9sOa6c;n_w;c8Fl3oxCe(u z_R&1`Ya@6sl}qs3l^7kiA(FFS;i?r#w^j~k)V0qHDy%=We+4f4pA*`^++PUyc>pYZA*J3u(j4%gcQ~`4Lb*)6y#I7*|El z98=ZRO%%c8lv5qtM_nacc%Hk={KA}0udCDu(~_jE@ys(OY|~L?3dNzgTF~d%0It1k zJnsRYds1=GHm8_$K!}5JIA$|nyLU|SzOc}i1iVN{?9uX3&lZw81zvHoF=lF@Xdo#n zDrzRsLYQ(MWFj3;S-sb<(jj-T^;k) zRK9w{il6oLWD-NKtuvj@=7R|hs%#7wwZjS%xN6Qk-g`G$&Gc3wv3DkqQyBUD4#=lg zp^9xf0Pf|QT9MLEjzGjUP?C@mmz3>EseU6rNL3vy!#ySWS(p-ro$E4g&Yxn_K~hy3 zTevh?yaZHiNDUWGgh&>h~?`r#7{ni(p+eOm;((9}0 z;2SS5{09v6*%rUom!Yf1@#?U4W;f3WyR`7kS;~pJ72R_RobzpmKRveC9RIvwN869v zR}ZW#{q%uU(&N0cS%9SuhRk<%IfOmaxJMw<1weozzck7s5+h>r`%j64)u7b|>#uEt zk89LJtgatFA=-pD<$+kJ4Ba=AiG)WSC6Ni6QH${oBN9?}2T172Vi%^AIRGfnhTQ{; zz$v@091xxWR*XJKy+>&Qo9VPJUU#JVnlR;e(ylfbhP7QVvUq7RxF75Yr_0dG(7Re| zq@J(Y8BdkLrXC3NqsK1 zeIGP!)dk-_HVKS>7>?8B@cQkCq!=Kaj4xAyN`!4qm6fDA6?9pOzf`@pC3&nY4g%g@ z1}ENM6MfOin;#8pv3f^Stm7W%v@RFoZE9?;1C2Tsul-J1vDRYcJlN{dETDnVEP*2K z1HY!)yaouCq{PK=buQ}9EM?#>@)f&$42=aDBa`pAE#fMo5Yl8lxQMdp%5h5z-tJWw zN=|3Z6byVtienTevdhYrLGV{{`VbhE1&12;&-{$FKp!X?1aB>@=>$qR@uUpI@Q zbL57H;_bRYL3RFkU_SMhb1gO4E+r*}_&j+{*f`SsiT)Hy=3&Qv9iI~+1Qqe zlJ0bdZD2rnyZFb>B#1Tp%m^8Te&c}D9}g{OSTjBakxV(3ngNt;C&F+Kfl%8_AQ`Ei z_uW2)UDK3U{@zsPaF0^Opl+AjwZOr6gV{pOYP}*GLMEJyf+F1Ncj-a` zCzAR5(Lz1-^uk0=A`ZLhidT`OciCT|VFwLRGEUUHHJO{o&+C3R$lq*vVCfX(@{$!I zS>zoAeP`w71}CAQ9LNE^09h@|7=LjfxQG^mj%!xSuL)+aAKesXxz=ywSU6uXD~JN$ zI)IrH-<630Gy+Ry>Sf{`FIqBujOdQvo$*}Or-8+Mlx*ZPj1Rwj&yvL*qwauiSnYU4 z;QT6t;s!9bcyO-ihT66Ws*J&m>*h+CtOlt++0DS8{{f=(?%ou>bPL=FH}%0~Y@?)I zF@fi!3c#9u)VHI?VT6ZnuQj)mZZ-8FuY{KBfKk#SbC+(wH6@ z1t>VKkw-ThGrpVjragGe$@0Mg{F$#ZWpQPqzWU|QTz%V5yM>b$HIidhg;0fFW z&e5Cc3cOt+4y_-C1*Y;!C)D_XCUO{%k0M<4aPchd`X%KQpnL!6|NogGTwqY~HY(A` z$+lbaTkpx!ABB*a->;_h*PWK)`5)@|u+$S;W(R2l(V3zLon>=t(Njta?DBy1!%R>n z3OXWdxUh0^a>frs3{~p~8s^Gl^jCHtc~Ais#uODz`<+5~)kjgzOFpgoEE;0o^s+_ax-LtnRp;Ld?hWmA(?ce)t-qbDtIukE=Q zDj4==0+9qGLQ@p#aaPZB+qmk*4`z58BF^}EuDFlj$Z;9)+QxCrN|(M547cwhOq6TY zPq-X@fQ*qO0o!ry2vH!fuI#I$pU?0GZ07~&!L-21EHCP9OI+A=MSjKeF(qI5^D4gt|iBeWEeXS)pi^ub#)?z>|bT|s8#z0L+QVio1s$D7%TZ?vN*wI3-d zDUF_iY>s>s&u{{|(Y-+^R@dOUR~>Q9FVvI+#3;tOby7`O5T`=8IJVq%Q`Zwj29G|x zO@PzDp<9Gyf47ow$9d-%_VGb*_d^4h6iFqs^C<4dJa!M@Z66QfZge!IaEmlQ%E@LE ze{Q{nKk?f!76BTA73cvIhvgajCY=PMiwq&yBoXn%qa*;GbpsXMZ3Nc!PTW_dUYuGg z&Z_fAwd2R%TQhnFRWIlqA05>1x}*8)?Yhg`Pe{g_%mDu1XqnpF`DFmuSF-Jqt^`Ap zk0PKK=`HSoQm2l7C-jUCmi_Ojh@05U&>v@k8M)FE$rtw16^cfLXu|#8p!FNSWIr%^ zj>yceWa!ubWWVU8Ce<%Ce!Q|j;~q(hKQTurL*VBQfy-Q_@4n##Yb(y>_r?Tdd9l;c zngi>0;=QcPEr*AHGUrdzg&nib`bFHgRlw6Mzw%$#wx{HQ{UH8_I;Q75-{rQ>3I=TX z?kN9oL(S3F{pKnp@o{`idHr^u=ur}UsfUA$+6Dh{&SUN+PNrGGk3oS#uJN~@{sAys ze(Q&ArwY)Y=mX_w!C>Y*A@*>l6l&#rHQbdXmYG-tHg)uq4gWzdGMdztv@@Z*|eZ}>+Y zx81sq1ENh%uOgf`3_7X|e1{93&4QP`sg6vzj7&`T58Wu(y&v@;RlKU5;#{==mc&;)YvJs?1s5yAtD@k+ zPRx5)q^rbbY*hU>74GrVns@#>0g^f3jvv*%X|{sPLRoGh8fxX0ys#$*$pzI;mf@+c zYX`mjHHL1u%H3=tI*b!P9%++*e#))qM=FJygb2OnY-8@SYk`<+%P^{Zxj0#h>j4B+dEH zSe;o9x<+R9>Jcp!JAr}N+TpB+hoz(6itA=E70{?IxDNHpE_o67Nq)^r3*Q!5K`&=q z+`+D;Tz5@K;1nh|z^tk09X!`ru0tad5Wcg`Z6GZvo<`Dr_>SFq8*WE^Q@ElT`hY=?}!q^+_7`zd;Th z@?#0Zbtu&uvVZhbdX`cyE`4=j81~li{tn59mPs`0 zR}X-V$Jkx^&+@+^GoV=x=ODXx?_NPb$uS2=7S80fTNntRPIT%}t0kmN>#P3JNZ!V*5 zJU?mUK@^;sy_v_Mgaf#K$9dMphBXf!->KD(xX62cCanH$2XMJRCK6NFEF8xbqs*Rg zp^4Eay5^|ONw^3_yWu0C8~d)+_x|+8;l)(K?&WEjYI9MiK6M$v40#r}#joh6;i%E} zrtrMNBADaDM2vHt!#XqsPxOo?FNrCk*Va+&Q|4-HwQ=uG-*VLs$zAH=CWfzwz|0o+ zoCB6L#AXfz1!f89HTs0f6_?ASCM*2vcM_e^Qde~Nm&d)h;E9nf_%E%2A~!^CG-0?k z)YOmj;r$+Wim$CXwif;ijy2k6<-L&COidSep7<J*0col7vT{tEBPF5DP&bkMHtXmx!6?&JgH!Fo(Xdd66u~4q? zy#TKlJ4@4Bl3z0I#V}^u1$QKyv)vYaw=Xm7v@K!g%$YsWvBBeLPs8WP47@+=hwM>j zx#nO$))}54Gl|X*g0|a@U@gCp;$f=XSu)i}(ngDK+n6J}S?NRNC}C z{y||Z2c6cnsq{q*V)BXZjz2tk1?ZE-*vE5lI!3Vrdrc@bN<6XfOWuZieoo>;a_r7| z-kikEhv;I*Pv>YN4rknBmclo80E$*0A?f4ts-sK~bm;1tafMy5q18BY?Ufz8>+0PQ zmk|2j?(Ba9)9P(L@I;oX&3dlV=>&{zYNkAfE+C{loW{Rt#QB%xq-cWGH>y4A);@=f zW`n7@x$Et+z(i4D`x(I}qSt_$TTyo`zIMef&FBw&_BV3;LD?mBXd5q_M7Y?q;`2Sk z4Qq#!wO2eW-+{ZE!!by||F;O_k;0Sg&`sG;viEyFX`rWx>O7>q2zV;ZI$7c!y)75g z6zN50uw&{&$VcBi$7A}EoG76VZ0dcDeWIvzStu{?urY0PnnGxMuU)KcQ53JA5&kcWWiOvYXs!NDA3+p*56vX3&CuleaF!7_&66s>r%ORwyQ~ zeV%W2&4^u96#v>%Ytn;7cJ0DxCjSxA~Mc7xgEJXk`v|FTCj`nu$S zjST1ywf*)WodIPhzha`S$Omp=Q1yNN8ZjwEogkKh5kyX=frVm}W$c zNv+P1=6CSoW0yM!>qtyay<4mU#@OM}OOWSp*pP@FC)X9qr`Cw2eWYIy9oJ)ENxY4fyA?{K)7 zHrr#DJ24Rqe-SvuEH%(YQ+(#GD9J(Oa@^K<(w7!2;a!56AQD|3!W+f&CfS%FrhryG zn93qP%unrd@q;ot`;N6DksXfFOoMC`DP7kxZB}5Sck&rk)+wON>%AtQi17~J6RbC~ zVsxvF@0??C(Q3bxU8eQF?V3a5F+kYW+C0ZKa#wG;Zgf$eFyuv0Q&csVSO*-O*N5P| zruEp*v8wSK`b*@(kcH{D3H{Ox;Al1P&#KR;TK9h2)1Ai6a!;Qw*oXI=VxkA1ZSXt% zuoeg%7#kCaBzn9U`WL)$rwly>Q3o2<^Qk#P|oA-g)a%QE&+xIIH zCdl#z)cUf{IE>sJ8EW7sq+{P{ct$^AX((ORlStK2k~I8oVL6L+^)OF{l(RA&a2fOV zps*PQCx9G)GIwEAr86o(6dNaYl>B@w6o-D%%<$Fs@82D0`RsRt9AkQa*Q2R2aNcKB z)cnvjKQ^04={FI~#WSfFS4k4HAxzJ{98c`^3%ALGh$$jmi4EiI_Y0wc4qSusbz!bm zB3y0bp^h)0p;fY;rxfOHDi&p%k=)LbMP2-`_|p5Q-IkeX6Tk!6s6wV@2My5oQOu!z z8DgTjnNF8nn(&rm%NY!w7ZjaehI_bHe^L)DdpneC5#e7f$^*DJ|%&4cPe!vSWzQ9^6id7{52hKi-`Cl$YkyisE1iN+5yu6E+GAjvYcjsf6Q{R33 zw)c{Zqjkpadg@{#*CZigI#VTx@@*f;2ny$DYMC>qPJ_^KiyRgA!LA`)n7Xsq1%MCj zjP>-r>j0iT)te989s`qV($kX5Y$Z$yvP{X#M8zUgc@yz+_~P_HX92@LM>9pJ4&M`s zi_t1m_!{xJ!=b>DMi`%U4LTwwAhF>o*n`yQ_61-5fo68pi(^Gh7<;Q4y`SoxT&`zy z&9kRq0w?Z+NAovC z)I>fYh(RonQ%iBd3Ey%Ti0pE%ogN*xRqNatW|=B^4+a`8{{(MNU&EU|n=b_O-hLc= z`Ot&b0(sFym$-pIk}dgh>s!uAhM7S+d3(%S?hRn~phH{HE6MPjFIExS36ruV$>jSj z?t2ze(zRUw&fXcjAc|GE7e9FUC~`JW%B#A!=*KK=KDC^=@0!5iY9ie3rO!?cpZP zztD&nfVCEGm*Ye3_JeNniA&fq_t(a?AdBrnE4P+pk<#s?O~=7$%+Kb4qLEn}_Q5q; zh!X+&{I{4|rvM!z#RHT{OLEE3Ine|T3v~9)+2T6}@U=Y^m8l?oq%WL&e0*jMps;c{ zsuT>zU}e_fcM1)Sc-Ow8*uDAjCG6+Vr-HT>u75HT8g8y_`_~I1drJQpA z2eU9+Q9#Lp(lAayC7RClrohh+T7G)WG4A*UPcbn){c}53E#wfGL_D6j`#*kY1bA6d z5OC70-HK1m?~rlkxjvjTT&Ty*YRNOmk?Y&RA7e?2xArp7l!>vo&Dk^%vEV#_Em zsi`Xm*I|6?EYhAbc2S|u{hbhW@!4r)o_}2gS_xxUs@kTxHIuBUN3+9Q((y399n|o< z(>DO}V|MkMO{W2m4`~I5QYMI;lZcb~Jms^7#k(*lmQHU;DwdK^4xeA zm_ZayalC3`mPi+{O?259{YEW>rFS5Tn7OguV8Cn;g~tovSTKJRbJVW1zDL1X_jCMh z;OmsV(ptSL`1^&<+H@}B^z-Yk+m2ZCLw^8bZp@mI ziv{f9or6|dh`E?SD$Z7vkhJM{z?Cl=`f53og78Zj#S6EjjgRnb z0Ui=#bEFq>tJ&GvG7tFppa`AsiIl^sTGl0beG?5pv+(~F&H6tel}rp|z{K8F7TJVn z1MtW5UQ*y(SfYYGzIPFW z$r;TPgu14k|L3f^R}#=uXCr87)UNL^*?VVS(&Bsof-fzy76LkvJRF8$VW7d6seihf z_32X+5Y3KNtijjU9l5Hjyr_JD)Sg|n;g{2#!Wh8A{RRXZOESUQI?p#FcL1(|KY* zIn}Rr_(1*B52*VdSoTutEC960Ql?he-UqX~m=nU>#NmT!JY`l_f{u>9u(cxATr>Y} z@0WSJZ!~HZU~e6MmwLWn|2CE;CbR31%X?3maBWUrgAKAs@yN>K2sTrI17L#?ZI*vM z7u`6p;1^gw@HK-M1fNgn`5LG3>Tkel*mBC0itA3PDvOPk7;I)sn=0s<*qQNf?K43% z@}+W~DWl(NWMt9sjJ^Xw2pK!j$r6B!LK7HyWwCT2;KMx-WA`z;9SqBLSV`>TZbqz# z&y(%CIbH_xj}tK1%{)Y7AAeM9gJd3YaRZCHbiQE;AXX(|2Q^!ROq33D9Wf8WW~o<{ zffAQ30XhIaxQHq0$+{q*D_ZRVjnvOH`$o+K>2h10`%{ZxH4krk^UM2a#BqKJ*4o+i zPZ$lLG$$P`dwZfCf)_9P?1*TE??N`it-C@fVPK1A>fSe=^;p7Bz%aO+gxjW^0ndm+ zk6PDQY`;Hw8fgRhSM-Br%OAq&U&bd3PLXUidR29aSbe=e>?K zfHDdguG^WFE%#?I14G`3$otQ3GjP5u1?##Y#$Nk6hPCD`#^1GYNR3yW4B&MnF- z5&pUkyYvyaqpbsIysu``mXX(esMR2X65XJu?5I?YDT!9#q{ZgXXP%_y`03*#%yo(5E@%XO7*gCetT;YBCL+Ya2YaEON8X9Vbm-W15x!>+T3d07I#= z%H-^M3OtLdkCKvF$Sj`n+Zs4WZLr{9v^ zzM%_E!Zbd5w*^ZbCUdnU`HQ5rjDU4Fq3bEn#}ZMFR@qBhdX~h2BPAa{`R{#{SA1#Q za9cwS;ZLpm(*>9Y){N@xjhFL0f(Z+KdWb(ngMDzPyisC}J@JH=znLn}@+leMU zGcj#&<7ys0X`xh9ucrKKqxFBOrt%hsDYjNlFOf23PFpPXvnxfGc<=*F?LzMBD2cqw zB>8q?lh1ISMOsyzdzXTdTbbY|3p2^T9ov72M-TXg0Oh$osug`XJaa%EnElLMq|!j= zvQ%hJN`1*q`CT1*zP+aC6K5#I_Sx`IU2G|a0eqGnTDj*D!5%2sk8 z1EbISXq1QTdz$xn;~z(*X-8Ad}*LYdFB7K^Or!ysGJ{xq|f5 z?+I+C_$WEMf_QXBcd^+O;Olv1oyJ%}F>&^!B}`)I#Pm z;tYcxLfoeD4@mDPSrh=B;&zfkOcdv`GUmlfZsZ!Kg_th;2sx48@v1S(Sa(S zIX0s#a2hMM@LQa|tB3SfpyesF@tm*vG|Pp*m+!$T4W<>B$;>uVez79pE)3~+(gTjk ztF&iz?Rv<1mMP>W*Q94~zvQq0!*R>(x44KcXHFxVjCmsrWzqP8rs?h^I6oF52A5>i zq4LpbS*!zQ%9GzW=bOQIl2l$^#Os_G&;{@Z;ePS|r{EfQ1+lBzR9`RoaZxtaK>?E{ zC1-PUb9e67LW|!c-V%(nnW4bllEI~|>Okr!eVohk0Jia{EHPH}R)c601~7V3@Y?pr z(_6SKByu0e!U(PN-WO49xbZhG%38bbq3aT4&(@t2&Z=Us^ASxM0qtDk_8)ongl|bA za#2-uZ~d-Dq=Q0Dz!_76Zt>Z&Jk?TNh(2E9N_cT25G=-&eHXTg#RYAz1ddeU^+E8j z9gGI=n|sX}p>I#FEq(8az2S{l&H)TDFQ+_*_xKSma(j%ict$(Z-{MsCEMx9TaMV(O zUGq3_ERLW;eDDy0k5dpIGy4<~y?zIyz8lSq?hY=ueML4C`mpr61P5>%5k&v{pi@SO zz)L0R;_1_sI5*X0DM+Z>Ef_>l!ShA}rW1DaW35W{rsKq z)kmpqhV4wv#Stuuv}!xcm|PK8K$9Vi=o~JL#7Q02+|;JlL>@C!w`mu~5V4F$+;3;} zb!YF~p}hU!SvGC$<+mcFrBRD=!?<>SF9Lh6bp>?qhr&c8VHYiGOLJO+p1Qu-r1PHgJG0fFtXA5 z#K(s@()mxF#?`Mr1SW?Ye_Sy|Rs)sQH~NtaxEGjqA2H|dhAQF|V|QIXLLN`xs-o3; z9*?X_vAykKB#cD|-`a3=o;EidXn#O;@J3}d=GMxS2F~{?dEDzCo(F2Vo=q0Kc7|Q7 z6hHr2V;810?S^;V#*+4Zbx)Ov+1~}9_phJW;Ls#k%VO`=fqiIr!?96HHdG>;kmtsN zWM7TWjB*jp_^`kTFi5%knvSlR&DPpMBMwSa2`TszvFWaM&pqd4pyfB#@zDW!61^Bo zT{3o_v52mh(|HIOPe)&y3!gE7QJy6)3BAV-T*T%Xlsp3c?BItzZ%_;Q%dz_kDy%7< zeOMw;Ef!<7M`1tsg$;T=xjN0*q^`~a`ocAiG56Ribgk^Xxz%R~#nrZJR@F+!**5bX@ zRGJe9F7%&&e&G~LO{<8QqY5(l8l7|xI?ooenn!Gv^dncV@m$2uELnyVWG3cE5G|PJ zIyW@1X8J(?fH0r&B*O?;V7Gcbv}qH&Is{dFy*&ux8=Us7xTDp$&U>R`@@*X*&n|$T zgYUr{QS-#8GjDUjwqFN=x>?K}_;a_UM|)WoLkJgMA6N9st|B;>z6R7AqoA_(D7a2E zDojEH@~oUmTRZ{|`9E51TB0SeL0{?w(uIbT;LqXC2x7eq7<^8LTgjez=U@k9>G9+#-lBe!XcH@9VY(>1K1xwFRj&Cg9;)1X6?Ug*mc;VE9I|3q z^jHGS#x|^7XWnpFyd~IO&kwUe2kaUiX{pMY&P&k058L1_F(RIkI~yswkdI`Lr7={aQ>g`pWr}*644UiTbh;_V?WPOP|Y1Fk6+_KjBa$q zhG8BL29{%-wT-3e3#dJXmwZI|??z&*g~907lPr41&i1vlWlB?BSpo~T(Ua0ul`nWW z2LXSjJ~v13M`ppvD9Dq&J$ipAU8aOoK9M!9r2I;{W{K`!`6oeA_nE`Y(=?kn8|+R@ zR8cN20ndr8M`%b_b69ahKg?Z82({kPdVmoQ;ghJaP&Mn4W0u4VboYZ|KT)9_@h{?k z>+rdsE9z`S!9+(wkz-*(o*9~H_dsyPjBf^OG!*ZMdPoDZXr%C4Cj?`-wZv~E!pB<4 zr|gwAFOkSUnv_noOfSMfoBYeI`=18G2T$M%%EYgu$zu5uVDxkzrmx=SHke9*9z-*! zVfr@q*G68A&T?crbkv4Tv%-1Z(HCN?ony*fpTMgsd$pD2v+Mg{0_oeZFQ4ctr*1J< zbIl%6er8}d5X6$(=0%$61_7lFj7$a(-~P;b0#k$Kj}X^i%~fKHDLxjWPfn+egI%=Y zQBqrwLTHM+~a6668Xq&73-J_B!xtF zAy%~?2dJ@3341$y zsK8(&Ki#miB#XTBz1IdFJP$`a$GBOOngC1Dh@)I4^L7`s28n6i?2EliSsDun+k zh1T>7aHQc&IGw}?>5O=fI7tEZlFdyAF0D~9A}j~s0?E5)v-wZ=aJ;&x8hnFyu)#uX zvk<$ms@O?70K~g{=ZaD+l!CA6I+!O<)12ep%Upo`ksT6EWQ*qoen@;P^hZRgA|8&TfiEl ze`qK!iWV)+c6-zj{|Ng?ReNuU zL228Jw52a}qyx z7L5BJ5ZPUGDyn6wQ5?>xoOX==y^j8)1dKH{UjP36_)?`pwGgi!l9u^t9*^e;;@@JfLJTYl_T=n#-PzL> zi7OYxXxDPW2whB`a_`xwUoz3ve->4mnZOaE-+w6mRP{zhdW8GLr*Dx zrSVCd*9M3Uo6t36`NzS_CwFq zytt7e%*AwRc2C-4cL9A^K(7h7XpTYhK*g^J(Htxnd0c9 zEDPq58^kr7NQar*q;zs-o#8|^ociMYfjQ~8lr{Hq$HmCLc;s3#$WXf9c1#;?>CjCo;1lD#hPBZ`k3fLOGCwc zdv(xM=`Vp_cPeh@t=l3$_=pc>-h_@<3K#B_dI2b3AV^q8Z6$K2clrU14p^A4>fN7= zm{y5_l`583*2?U4QGW#rPsC9eFj3gV^RN{thVm-`=PSVrM^8>DjLvgm_fYin5&#fC z1whVH3y`O~)f2}^%YSNrI(*4!HsHs>EgD*p=fD0!dt-otC2yM^*mczY^`0qfHyLAHGCotbrjz zfitZEP5viab=O&P$J>B`^FeeI7-jxtuI^Q>)4UNFti>Epd*O!kQj7IxVr#Dv5Oq@^ z^@W7w!y6Fab7SWO;oL&=1a=t!z?-%kHMe$B;M25dL5okI2Ao*DtzJ$pcPa?|WF3n> z>f%w*6oP&*H;(!VIY0`OKL5L{|GzM)-qlmbcV@a3^@vHH3(NWTR0V>T5 zd1ENzQQ@M&B!fz#lgk7aCT3=4-g3GRbQ(J5mH@)3yzX6kwaJSu=9=zThlE5UCCc&y zW)#+05(}y*I_aA)_xCjC^pMlrAp<^7?0;*9duNMaLcoTE`Soa!sVatuApDuzg<6i5&-g+G%PatI%d^2I1qE%E=)0Ay5zGSB^=AC^l_H z;)_#~;tp#l+@O<_L$uAjDqu2r{>iia_UQx5gRq)d@_46icZ$f>4=MBlR3i*- ztB#doHEgfuRoiy^Hhg_Xz)(Lp|JuljUf=a2Oqc&27!I{7OjJ@#f=PjY^zos#a*d5dHzpM}%-U9dh@L86DeF=pmOX{5G1cylq9H>lmsCC`dp^pK zUdUWIqAh^iAfe4C$^uD-mB@E|@>o)QCNxzF+%~5!>5q4ev448SSx{~HH|L_qK;XV& z4rHM|ko~8)(SOUM=wLHakS=DWr^Bv#Mc2^mbhy=R$-63vKdrwcXZ-H!%aKGmxioez z+JPoa+tFr5MNFC-Eo4KJV|5Fg8`xulz#zIS46z1yHbL+~+`NVG8>6(lZI`sJ^6Q*H z&M#o!x5oRnhmGr$wqIK2u(tr-dtubm%--`f;HoL)F%fmq}ISdx2}t-E-tE za@lGa??O*@0Y_ao%J0oi(NUI3Jnh!crECt9Ge2U6yE)XOYb7g@3*@N2&AB=Oo*zwz zSnLt0@<_ipn7Cvm%Lsvqm{wJM+aWOclh*Ma^uw|^zdaMOQ1xc+8yUHa9#a|QiZ`W2 zgPSTwWyH%dQsa0joZ|M?zx4tN)8L#N*X=%a3bv&(rLHs)TYefBt8Uw^H|9ArT!p_& zycbA)rPa+C1|LXTF$5EMGNc|B^CWL{HsYamIzH^NF*IY(=iifC_E}ucoc{K{TBVK& z?5RHtpi~xG%Xqj~8+ktqTi1BdgO0YH7je3+Pzx4P*uNIiYFv{MLG{b6_jLRAj(W6_ zOBGj<8MyT?RcUX1RIB~!2X@T~BrvynI03N8r{lZ8)_;{%fKG>Y>W$?) zDzqo4W#9Y>%KeiHsrVu!l)pDX2m@nbO+#5h_sYU{z7I06skDQStR(A8U4i&mup|F` zRA@g;)KDS~bK&N)!5B{r|C)s+;}R3QIk;EESP`x*4oxs<*ZF<33YN>P2EcCiVa}h# zy9^Utk$8`n z?tv4bYeM%X8gCbL=u}A5iEo9~m9JtnC|C`EiKQv)3clVCUoMIkyul>;k{*JEy|~=$ z8VI>TycZ4DP-)_sPwO5`@c0Yp>~$i>fHYp8Mcd$cE{rkK+=U}B0@IG4o3B#w-6Nf$ zQudyeM-ygI^PCyPgH?+MA=pZ`ZK1WGN%7e`&@Qh?2khE<9}Oz9(R(kA@!CA1E#AtowvbVgv}M@B z*?jbY28<9Xzl@f-ELgvopjCmYE13M_YjiV4k|31$gL$!q&Jb`Vs zdoVg0%vgcox)M4YycB-g87$-B7%1Hf#i$;aUqP@f@A@eeF$|O>E=y4BBA1RnS4?A_ zu7-jYsd!Wo6WE&!y9Wi=zm1pN;^ZQyyfpjW*b%fWr3)N^d)h&HR{Y@Sf|IiM!tN2a zYh_PMtmm*o{Mxl3cd^dJQiJzWOQgAC81>Yw*G8WhM*6ULUCBCoE zIi71d62I4yb4jqiv}5bU6g5NuV{x9zEpMwtPs;u;9JBJ7>r`u6{vukZN23FEX20t@osm$fMn~H zCauvSstPSZC$jhnFim43U(iUC`WYCI4qzg}8bP$SZy#2*n{C)C#`h>_8-@Soq7y6GqTMWaZyi2R6)SAhd(;dfe*;&#CA z<5!Q^mTE0H({YIl3OAcRDy{>hNoTsRi@)__pj}1TT z>iMT)J_@+wzYtV4gXWbBllvH$AL_@`2cy2R6D8?u=*0;N!elD0pkF78D< zy*0Xl9g6k-vVGMpFgYm(01p(^S`XTf{ z$!njHbmYGXRMn)d_3rRY+voo0ly7CJL+Ms5y@;xZMYSVm%G-astGN!P++X+itw1oL zjF=K{uzRWAw&UxN#G(P}X+LBU`>)PP9i%RGA|EK9UT=thsI|LuK9dRfdnW4(zXB~b zRsE;YiyFRx!6#2&XsbJYx@9Np8&S(rciSl5kbO;?_06`Dx-jJY{YNPy#MbWP7dtzb zDYlvP6rQ=5c#XHot+x}~^qd&7xJ_QXOx05PG8sTvIt0D8et%xumA|I1psN_o$IVx< zZ2RE&%ksMxQN&R9m+{(wpfAZknjEBpel{~)mWHhgl|4-}_0=G~>{tn~{W*tB=eVaT za`r0FPyYWSg(!FTCaQkSQ>8#R+(4 zszJioMOvE0`jyBO=4sEE$r~^M$_{ZLROe4>RK#_RbhcG2M zJTj(|?G#4@pf5oKu1jAptX!R1)0sb#WB{%%VK5(~0jwH&49?Aakzyd(cXUoB~4iT+?;(=em>$u$GcV%c-@|529VR7fpf2_*867D zDC~Wf26YqayH{c#_K0k!U?w&u+WhbVzYKHlje7-cC|g}sWWE2|T{MfD1+e=G1C2CA zA0%;q(}OPll^!HN^R;}C(OqfXDT;xl?p9Ol#{O*VyW4g1@>f#y+~$WyN<0p4|4`qL zKP%cg)|;#ap*H0npf9}O;l&W<1if@(x~MopYVMMdB8c&^5C!?+nHDFjyL*7%QZ%j@ zF=CuR1SI)vAcQeVyQ>coMWTX0%=VL{WY8d8WGZ2zGMEi|3v2z{y7nF1Row_H0C?Om zzE!GhkGENlO6=-6`8Wr{B$Z=j?GD}M*li~U`EOx1`>R76-$C5jFtY6ku=jo3TTJhtT%``TJwctiI?0{x zh8gt$4AHCSSG^)p^~OPZ+X5xA4yA)$fp4~}SZxi}&jC`De_c-?fYkreK2}4Xgua9r zHOFyI8>+9e902o(3dcJUw?yKjV;nMoLSDv~k%X7afrS~y&${ZXo(BfTb2i8BtHm&g zkS&bnzaf=HHBzuThYm@46UXjDBOJSYlhV&ui6-Cz629LKJU^FAjd_+AB)wTi<8a%q z$k+t#VOX*ng(^7Y)8GcKE%et8NFAHa(T-dhChZNm9ML6;*iX+zkcDGHUa`t4V6DS4 z-}<%J%UV9EK|u*Osx2A4esS{fq?=GtXXbXsPIL9qF=QKCqlmkd?VaBl7!37O)${)} zRR1mR=*O4w7THLIcNp+VkllO=e=%OP{XAf$eb1cBgg@n$T+ypR!yNXYKz^m`{4j&} zH8i8_ypbgIRFvdhNpK7r%qS`l?wPj%r3&Sq1=yA;-3{ewS$B}3p`lUzPw*;iUbg}u z4IFhkM%o`67C?b-f(M4|yp%l&xt`b{pmF1OL9oNvS)>q#2Qjv|nDi@+>Dd|gn(EH< zbu{E_PSRq?FX6la9NWGE1Fy?L03F( zdISe+Qs&YW8W)tqOWw9Ek^Ak7*#>as=BZbxb$daDOy4$JkoBotY><6a_R+#!O0m4q zb}8HY2pfWLC{m^T&9>t^Bb;BE4C5!+w|{45*xDoy<2T_vAx;=58qcv>NFw>ZBJpII zw-;bu_zbgC9JPp#-=)%;db4w|v>RYvK7EE}QvoC?HiKR3?~r;zgA-etUk9uzlC<+@ zy~s15fo~YMz)fo%u7CmR1IYa;&>?;zbeUV$#@br7i~SAp&O_F%8Pydg_%p%C9*DpY z_?}J^dw%pabDQ6sHw(y;628bouDV=S&C&16I-}`>vupO`oQci_> z>A!B%;%vq&HXGXYrgQx;?1xmB(;gixy2UPDgmEP;D6g;%M6#co?CqGmL{GVz2lS4C z&QhrVnwUqz8HAakNGkd3#sHPm-HGt;HJzuvpbyXJ8$*pe2Z`$Pk*7UK+vDhS zbIreVVZS~8P?S-kHa>Y(iwHaVc4iJkN@rFT=r;={a)w7`^V87WRwsiaUb8G?JE!hl z`=sRn9(~Tni+T2x*5n<74BkyKso1tpLT7@(rX=gZvWl>ZbJ}=?-`71TG=|p~$BlR` zV>8U8*YF*rs`NCOvQ7Z<;WKD1Mo%YP6nT1S~{GEokBcO#MUiA zUj+1A!TJ%5`nEBl`CJZfM5PGpy~?wbCtcmY#mt4hRaWfc{LUCByLH9zMZrS0<=k<5 zv^m!3hEi{p-sBjZ>||pxn_l~F*PC|Hj{Wex7&go*rY)xC3Z~}c=g$bUwcIN@Y9e6Q z>S-xnj1>oZHkc+}2AxbVCem2Hur|(hr|33`#QI~#u#@Q2%SO34XT$azEYI$@n+9wh zYb`lnlWp=W$=D8DJ~)QuAgfd$Cepg1(Gl9j53j6|Mo~P|RJ=+hrp<#0VW|O-&a_HSv>u` zx*Cbf9glhZG7gycAEBmsdTdi7uGhnStYtpSl|((;(-K@SAC@S19>(&jkG$>SeyBdZ zZQdB@x_Jn&sQ@+q1x~U=CHgQ_83>$#zGI87d~7;`k`hKQM5F%N1{c9SM zNQGF#^S_bXc;2P<6VT3+)8}_JZGrlPf}jQg4bhLz zf_L!GI6bEFzg$|h`DQ|Y_Nza9m&8?;BN`tQa#agB@tN9E;R~oQ3Q|JywzUdUhqZ6$ z4ycDB$C#$Gc%B~ryKp?2{ow$pAN8Fv*wmjjkY|-*(e4Y;z6s~~PwwC1K$!{>hlZc- zJ~`Dgh`x}&QnII1kGF-(umqj%MSU?Y07)-l1v$4`(Xly9qq?pQ)z8=BV;mIFG*e%! zL38hClw_hpqT;HwdG9|}h9%-N)t3ZD7)HnmNN#*8OB15VnrSQmTQKMszL>OFl87xK zSFpI*z@UX>y6SnOMPs(v=b`u2cG0L}U@8S4*0G5p$zn|_h|1NZnnXz&L^_1*0tXAd zj-XyaL$+?$KYlQ5hDx^^~MDB z(bs%+i|mFkU1xRa)^For7C;{&xJ_(L*2&gL=ZuFvXWnw;?Hl|Nml&qZ%$8PN1l8I99UliQ zZhACu`4M>>c2`gaMmd6HfUB-xB#}{OZUjM(G$99qO`H2hdahCGeVJ5DY`i{@N8xOw zYycpU73g4*k9Ygxlj|_AhV3Kd1=5 zqj3L~#`mYmU^z2hrstf|=Kp+iNRG{(d^1g-bG)c`e@Ej*boqy0EjGpFj>rIwq5F(} z?_#`eT%yVWia_}vgk9qCA1UqkWl$L+i&Q8)JO9nMjzmstK4+H z^Gm7KxL!A378Qhn8D=H-32P>l9x3>K3WPd2k!HRR2h&$l;E7k}o4oFZ;?~##2!h5| z6KKtVhPbo0@3)O4c=`l-OpR5~F5^zyB`h&6D1%gi*7zM(*z%@GPoE(ZL7CyTfF`k8 z7o%KYv+wG;f$i`+Ru%#ZY|aDst6+121lc!MQQJgNlJYY3g4td1%vW`pjMvmy11>^v z&>%0TwlhzU=U{dz;R_TMe%4j5n+rj|0vbT{POteq7Y=3>W=45exkzREIMz=|PKJ@o zmRJkR0FhbQH!3EBbjYKAQJs422k=d(I&gxWQ2q38;1=k%co4vi*zN?%nk?kwcH*Lk zP57SdTit)|^vN83JN!B((Ju%d1D)Uj;_ z@Ao&p0}-ZlzvGM#40l!!(-k;(z4VCCkYm-9l&D{Oo5<@6+?;4#nLDcM``28Sf;Sfv z+OB-raP9CZ( zW;N2>?Bybhp99#p1~B&75~z9A&Wo}$Ku3TyKtgtza%m?%?j5rrV#xnAN~6nYs@=SUH8)bwe8+=$>tT_gSl@L^0~Py zkGF5Sw;mrksZj9R@F$0dxKzDyQYgZpDTgFZ`aIqPVDv}*~R=Z~(68_(B*1f<|g0$dW<+_D3{%|xBK++rejS}s=dEo4HenvXG(H+*_wQ~Ut0zte$!!4U2>UvJ!%ZrB*PCQH* zM0>jIu+VJSEtI2%kfA*lxLFHfCU&}v;n2=AHW{{72pTanH$Zf-4!=U~G&5QD1uXY4) z6Vf_hM?E@T5Y@RN-%XLjP6UlFIi$y87ZcNKc_PjmS#oOO1Hk2_1r7&s~N5b-F)N#t~jOz3Lk<-&l_O8E@eRXKQ?z#Ckm$Gd>%0A5BZ_ znNEi|uc7xqT&)M!L^51Yiq*~I+!TQfEM8W*zwAZyE>!=nEqtY7ckUuqHtoK|MqJn$ z(FoUaE=|0tv*v&%P}4p%DBFLcTd7Z zr$?;1#FuLM^GVKc#Zht6)5T8u&ILPYiYw(?T%Q@P7kSf9SWZ}?iNjIq~Z zmwP+c3Sx`t#t`=f9y_@PqZ-@ku<(7+8`uU!TC`HPjB`&HhG z(83hT_%_2QJ!>zvA0CI)jYr`(2!T+}Zs2_&A(nl0s8lMa-+a+@4@9K`g-{p-DIgnE zK2i)Q;<8GSB!n;2DrL{#R`HxtuxKXouKx_(LZ-5qMh8#cgV+rZD2rFHmzS8H;ElGa z89%*p>MkQNt=8M&Oy`C@BGi){B52s)W~D4$wOs#Eq)+|Mpz7O|tmdP4I7cLF1#R|S zDn|8A?#%l=z?Gn=zWlfC03=B;?$p;mhUFr_9ppHw0HhD@!u&GxJnf8xvfJ zwa2Uqk)%87v}$s)O3KKfr(7id9O;#d&~><_ATq_yT=)VZ0(6YOJPhB@Uy*u&X*^fE ztC6saQP{imYtEi;l$Zz@`xvt1#zO`rJvR*^Y8@<)pk%(p!D8fd{~BH!WKo-FFq5IK znb4}0{E=<;ETfXJC(AVj&NeCaY4+4ICRL8^E$%>649t&E-9`Vpt`13BfE9^Wh0} z0BcWQon{aRxr5V2N;4)>zGu}%JZnmopoRwEbMO?{!v)8dvEaIFm)MV7`017=VheDi z16v*5m(M9<8+qo@5CqnYEjI*D+DitJkT}kf4NBJAj5Sh1O!#QdDJNy|X6Us5$A+Ti zjqS(M{MmlBQA%FIHBB^7!;k7uv-J0gCyI9FHa**&1Ga{BZui1^WmnMyxpv>QnWzI{ z9{lyzf?iq>?s139A4M66yjXG+;Gs8oRK+^lh=bC++iU_NA*=uYP=x3*fe&9y`9=!l)qE5jp{?!Gx4KYhhf6i$@m7W&jIvb_Y(_{PK^( zYvNYKC7a(9%VW;7A}u2y-cY4`w+g!Ow%eR8jE-ZqU5oX}M>P;oA(-4#-pUU{rt%No z{J99WVYyin#RW-D)!1D?^)T_;B~f7UscTrimc95!;dIHF2uD!X4}kPg62T8A+AzUx z6Mm89ukv(aUo~#-o5wJo?{X=ZU&sCmk};%$2_g027%5ma=Ih=1LO4+Fq{i!hqmeEL zo2l>NM$tmH{TK!tk)VnY4@b$3Wdl0CafIQ)*FlkylIwYnjPkft^AFifDQIb)fvvJM zME+J)h@fJ#!JJs4ykrn?GZPd)d@keT=Isa4n%|U+Y_A0$2p!hUoOSXd!auV*#jDux#6SRCi_(Qt{$bRB2c~u1MMA@KKaYkoxTz3&Yhq*Ka zmIOUgieAhzITT5it}fcHIj&o_0ioWBWhogyW>&m^%#I2Z$Y+_e*>4hK79-xQ*RP&+ zdL6=;Db+5X3Ne6bOX47g(3fb}V~%8>2uZkyBC@+Bhz_U%935XU=6?-1|$ zSuAQhi&(lFtd&!C`Y#Rgi~`o3;DH?7;7Tu2eolaeL_M;v0j^6o8k>J*d$v6i>D6g1 z$|1qvy+<^*%MgVcbl%%zO9R>U7nafV0xstv$wheO~HOqa$&8t_z!2pZR>9m`z!}&H{PY) zdH5e~<=-P5{!hK*X&$WbXlVO}>8Qs5k`;P~qW;5Q`+q4ZApP;bV6K0UR*;`blDYpw zPmyO}cyq|@%W{OE0kZr2fa>62C8oGc4{9z&sKYrM2Y+~}P#8jqgG+J6``&~xGpQQI+GY#&CV_ch1}VJ zp+M98{(wV)*}#Vu;|8|~3LB*J+(p{q9O5u5gv|MW>C%VooAbU`d8==I@$&=lRnITw z{|#}j6h{tDM8ezoUj|BCkRkuOCZ-92>;3h=q0fzs4pu^lj3IqwO$uhqbbnH~?j=xuhW}qt&=dR!e$(d5IsRXxWsaA^#(`GR4LYF$ zz`v2);&)_pwD&eOI@4Rk%vp77Xt0I8wIbIA1Re-XeZO#VA)3(|Zb>b6&$FZgct}zm z_rT9U;r7mG@@r~u^NN_W&oE-4CWTPT!RoqV8S%d!5p_3hCOx=OzsdlAgP2vWrM3Ud z?THG@?1!@VsMAY2`5*Zf=WhH_pn>s*!axAO8 zP4xlSW-4+=T*N^{WGVv!J@8(@V~ciZK3lj zTr^X9=MtCjkfV4gi+1l}HIQNKvw-e10PrfjIe|ayl#ReS{V5<%%a}jMTNCp6`Z>y@ z-pk<8LwkUM!TJ(UC#2~1@F8#4830=+k9O}NfX8e59f08pKyLJ22xJOzZv7&5u&3f5 zb}n*@T+4lh&alZYeO&=i^$-g>GR>sbhT`COVQ02$rHQb=SnJtm@U2oIj)^;%WkO>Q zp6$K2`jNtWsZFP!V+m z23&Xv=rbk#`e0b*=gOw-Bp??Jl-_yK8H$@y47eO+*Qt1fN|qEz01NybC_g!XNAWg| zbZyUfa8~{xWgAJ(%C9Z67yiS4`=eCSX9vTaD{{~Ih@jW_)brNfFA!Ge0#mfa9j4iU z)jom>PnyigZysQ*0n?idvdcq_X8_9K1XrEo%RT=7J?HXrU3pp+c_11xYXF^&?;IZe zs2()AE7}2GjJFV9+?LYu((VutrK53M971gogubcp#}2j1Hyf@UXO24QvC0V^muuza+Yy?Ld z(CSrXminw&`Khq@cXMii6p&oYc$&Bo`e$)mxtk%e9yvNsAx7s^;2AKn_J;mxkyBI1 zZJzSajn8s!p*M;So~$yTXwL1Gcb;(GQN|^7HW_k1laKfpaOFE_d|H9$ejM-t^nAuL zF3Kw9<_d?#(qTcf0Ip}*j(z>UmQ(&1pT`TIoJH5!mR*a@Akof3&cE_rTWb;=fC`8% zki8~XCgsU4;aev40GiRoOPACDE596~#99LQ_{KiyXL^a#v6(0t$u1 z5yTCtzh5EH$a=>#p>v)14$a-+O`RIDfb0zJv;ikG4SJOqMBqk0>d&V^uk<@}*e(fs zy?xMNHNAsE%BL^E#TGth+O+{?^}4$)=pMchRwbZnRuMzx4^WQFN08HB1cjU>s%BV+ z-GO&dzp%?hc*p z(dSxefu&22Da zh&`K@X@HA=Sz-D|_uEB+ENml>^BcPz+||*dT29kK3c_X%2W~HS8mfB}Ja8H4ZYP zv@bRcxlKv;j0O1jcCUTf2{Y~S$U|_-7OW6%(-#t?-T|pVX=aJZBjXv=Nq~0yN|O|j z%Nn)E+P$2L%R7!G*JbVIK-{EibmdZT8WzK=SRvflyUjRH_^s*3cnw9Z8!T4Wl7U4k{f8|qW?PJ%+Y-}ejwkxNRS%p)<1}(zFGv*@y#t` zo|<&*(1fX=jvnzpSYM6|ajarS`R4LI_mT^C@+grXNf%OrbMiN?v{NzhHrWZZ1Q$p`E7Dv|YzZHY93vv^yCmTTJqA3-j4x23wqTt|*g3j}nYL5R zLFNn@VgKgu zDqObUZ1_nL3$I$aTaCPvSjVUHnUBN!CAfsfP5oEK+>gju2%zVbaUd1`wC(5ND`ERd zzBjS@6zezF;_yes$Xv&m@du>0Acr0c$_%cK%Dh0y5`#mCiF=45fDHMI_;crKc zI%5G90i*X6beuj2|8&ZYATiSOMq!a8#T+LRMG=>xXzx<Po4>`1@j`;2touX1y*VBRln2M>#Qje<1FdajjjkT!n~T4iqxRzFcq%faZM zYUj164UXnEZ65EQ>yPM+Fy{Szc!s8(F&e2|-{+19QNA*y9e3Sqc$x^{doT7FbZpAn zij#L#`yDw=d|;{2-0h)teoRSQlbcHwx(7&}!Kd=X)VdeldrGWghSi^x0xaerJ-q;r zC}5agx~Ypjw+xr$v04udk7e9r({}N<-0u7Q#y~+6Gd3s~3%e&Pq_*RkXR}q0aC@M) zNP^RC2HjkBx9SHoR5NuF0?^slA=mHYy`Nuc#keU_g$S+`7D%u()_syvj9|!Vab-6? z*gpW>S>;W}xPF!q@-|8DZ)}P#*#@e2ugRe4u)AX=f`0mY$nCb7zCc7SIX|MO&GjQ& zwwPq+v&eOjIYHKA1d;Ey-K4G&@ImFK5EPc*q+V(qeWNCTk`}zrZ`7REO<1YsT=VHH zoA=?V?a{(YQ^%Wv?t7x6L*qz+N}AvM*uUDTpud7?-Ij~<0KcAOoGfE1k>FMVwYp&O@ijU;WBIM`_}5-SkUH41Q`|ck?RE1t>CU8! zM1LqPkS}6X#KNvI=cZFv5xLf-!muhGJZUgZoAkD6NOKhRrQVcH#KDz~jt$PPf9s3H z`>^{R(`xm2U2mr^Np1tJpJN%bw!i)CZA0D)(Kf3xZsC=S5fc23hxcP?qA1*7g~~^? z2gi=>xiHmczWvUA&G_nP{)_P$EbShjPMgs}eFBx#Ux2i=tzu%gfEA|+=nNbp8 zfZp@zWdIq8u4^tFxK(^(ibIu{F1h;#m@*kNGpJpifTB{r4d* z<6p26F?OTi99to)m@7sH(|q34p@W8Aw8C7(3&m^}61Xui-ePryx=YO~xa;3AM#bI{ z8+}RqY%zBF$_hORH+$_6qXz2V57rJ=oF-1=E0>c?Z?J=(@rtQ?4DFr9^=*~Ll$Z*{ zlPieR@R*8NJKh*7Dx81s3IC!&^LUFWJXe4gr}vX(T$#2V&nQK;Cg6rTm*uCzpg^+| zVS4rt;8D{>^#qT|{W6w4*%ZmR=I5CXT$G|%v7{EE8MoBG3jL^6%OZy zcYJs9Vk4?k`MvT;BCF~8EiXUIi^Vf6Ks4r(yg)P@6Q=chUi$yId-G^0`~QEuO%z2N zN%mwN3MFLAl87SvSQ29$lq?}+$r9O(sBEFKW@7A=WEr|MLFkEtm2vx(5%SZang8 z&~j!xa}?{u(3(tUckx(HbKcWS7^8lsqN{5UqHw8>WUg;Q>3rqlZuk{zRDm{U>1 z4h3v>lyp&>9i7>tc0J0s&5b@`gHb=Dzp=I@VvA1R5RzKIEt`%jPRy-7A4UPb%u6&n zCO9@2iHW`b;o9QVdr1T(qS;%M*x-j}sK09QF!Od$cdBBO`u;5OaQ?GPJLu4{Q8d~= zp`Gkq{S8e~sHLyl1Xb-8Sg#`BhDk&~v(s_UU!}vpoFp_9zw!Y%q27!tyKxkVB%G76W2uT30 ziq2=*nxAiVyo8!j@}|!2!>3q~Kqq!7CO+bmg}unlhHV>CT$9mElkMJ(IsIHbJj*d? zLTTs#Kk%H2f4-8ZE~T-C!rjSmHCect%)T}VcuF7Ha(rt`%PaCDBxzl<^~||5dv`|- zU);D<-^1FTVls>@{4o6O_H94mt`ngmZEeY~f%s$)(4d7nm}Kb8{0<1{(2+SSNm{us zGt>48Lw{m@q@Fu{5hokF8zUYy<>1UFAs%kqH~22P7Cn&{t+L}9cyn*SjS&@{BYZ@` z>qA2$`y$XcG~z-HS+i=gqHrc!wTo?MvzE8LZumBfCP(SrvhBDsc4o+?!~1C3J+`aR zOBDn?opsueA5R`Na*-fQPmPhV8^c)`1Uk5=6KQj<=Kl6=|6K@N*8!nd;4_YFtK=k9ZQDin-hl`y!@V|d; zo`sjio^Aoh9w}Xq$TP;*uN4d13>b-}E=m0}qDQ|g`$vUjdlK+2ZOY|GhHPtqFCqrBJ0g-)B^@xZ?x zKeMfSOKfrp%?Nz}93M=fa)`KppI6AN;hEW6xZC6z=_bSJf~8%l)(aDzUqR>`nFu49 zvHk|v*hp;P6-SO_EUWgupO~b*;D99;r#+owPzx{SteRJ`NI^b>&itg<9BJ4yU6W@& z;~ShL|tW|^@i4;>J0AzfK1_GM5wF9IzX9Nmzoe6*V5CuB^(8D~$#2u_v zphgq_i>k!>c25_ z_uHCFNdfw!hTm2Cq|W{s-|53(4B2?{Fh1i15nx3ocu-B&_oDOe4^ zIe+vrENdTNF5~BPdwzO$p(4Y^te55d{gW!uUrP-FXEWtK6{7SA_dXKf0c3163J{ug zgW9gtyknZzh8uRD7;F9irhJO6c&OdQ%z^Kij% zYK&n71SX(LPumYEB6(@-gVF@)J1jG@e*RQ6b}V}NRvb`I66#sXd_KaCjyrbaQIa|9 z5|U|XSmvtKfbGW1Pk`ltwI3`Ehb|E^iF#Sv0?h`P^3HRIn%DbVwxuchyNM~UroHKy zZcQD?IQ6ikpIMcdLVDr#!6D6EP;+d%@%UPJw1E=14S zXlURGi!>n-`}wQV5M#k>$1pg`UMvi&|6d|Ea$;XZdJ3RMz{`sQs-AC+^-IZv%%7S(*PbI_FJQO&{OI{;Osg-= z;Hwuh6-3-!>*qt#{n-=_r4!WAL~@Fq6uwMluII{*zG*M+=}A-U&;B|+Ds@Zed^*31q@9wyW95N+M=y+dLs*jH+CE4s!WWzV!f z?J9e{^q>x zX@U*!P_iSXDe3+B&Wag0!*&Zfw zv!knur{cNMv&B&%&KZtjDAzt@yckToCypKQZCAA~u;E_rnUek1KWeIJJfZc z^oeY@YG@Ave`wANk=G3e%cZ1kY_&k%7PPZqyVXnY zv=p;(sKYWI+gFQ~zJ9UELXU9yvTzPWlR@kz3vgfako`6J zIEI+E%R1}YEfvX|%Wt$lxL3q2-`0bgz^rLaxRgm~8*6;bE^8r8efLa$D9#o_UpK@i z__ig8Io=Vrbtzd|u}F~oa4OciwK7ZfYVZZg*t8)%d{(J z`TZm6cCk%A-#zMnr*chWlC9i=@s{N9Yqsm9L=8Idjn9*;VcrY{v-yOgh5hr6iXBYL{|`D4AV`Ro$Sn4_0NYVZzI z3trigH0sM=>^&`R^)45m^H?*!P0Rm~xK{A>qc;xa8m2!P40YC!-bRs*;N}XGW2wUC zH;OFkTqJl-w(Q+6^a!d()8K<|8^#rU)joxXv&p{xG6OGK!!_^L%NLfl0bMyp0tkcQ z#4ET@l{{OygB02|*P~Hs&4pz);wPlDX{mBbm#l6u^iR)^3>f7bzLYNclKiMG3+#yn z%2w=8xi_b)pgH7b=N)4+UR@!3?sJ(hrbNtf2QeHBnD?Js=?;^(*j0myK^?4e@;@!LLT1^LrgEd_`;Lztgsm>(n9+8Pk@?GuQMF;zHt(FnAge%g z%(0kYQuNHVgZhKX7OKv%yECsJG(~Ola`5_o@4-@TT=k(TB1C(f?hzgDk4H7_ax;wU zYf(6qZ^3avay2TLnPmI@hBBRi`jmbS@*WHI?awtPh{KU~=yul!p-$ub^db~oZAn>bpQsnX9-aT%F%^1~28+h2*tfUSnr(r4(IUfeyjzPUo3f5cd3V$D_V#>xNtGrTA8#M>ioYVh0*FL{T-`5e25??guA)qUDgz$b#_vnSP}bi7!KdM0?>A)QZ+&n4$IWWX62^J|^}?V^`f+hT zIUFiWZw|Le?5gWu*@~Zk;bD1#&A|0EDc&KjPzl`3%!=Qc^(^Qan>m1Y*VgS+VX$o- zgL~;$-8kYMtf$=@`UBU(W4$bjK8ME~7#R`bSiM?|9mv;3eI&(>j3~X3E`B>tj?|{@ zS!iuwifI}%2tJ4ZKK+W+8a)Uj1a!2~(p(0o#i6E1B1Y2RhtMWwYjH*%hG&FGQo~S*7(S(dit3B{&n11X9hdHOqWD1xor2(cXDB2lpJpu$iFp4}M5plV1QqtVNgPFuNITq;lL zOWFCbM2GD&@r77l&dg;FBb8|wn5fN-EW%JaPK z2Vb59-vxd+0oKdAH-^O^440p8&YA-~KheVp7Rn*@@ujE7$`4WO&(m+|3v8q#^=DCB z8E&{8ag2ta&Kgj}HeZ%@vqxWjdGgkcfJqfuBJIs`(%SMc zl6I1?JUhY;dd_q=kO6tDOr6a?4UUOd4|)9Y`p)e59dvY{%NYx^txGQ1=f!+sEwO5+ zFY&_X`jWkys}|CX>v6D%)XGvz9D%-n)L-bwuu37ncqkocR6iffjf2l$@8{1>Ci{Xz zaW+ONei+%?5kck+IA)%cs2ZXC8MZ{3NNcKbFovXlgKh^G7 z*476SZos=-$7%xKcf|M+>7JX{cNsO{7L7bvgFbnpl4!+^!#tYTEIXiZEbJv(gHa z7eWL;*|~*9*E@jr)^VLPg@a@PzD3l65rhoHGl zTZgX9vjtF>HOf(k1wD;rHDkFpd$JbS&~QE)@d*4e2^6=1@Fk*S#4;kfNa3WdjsOr% z!oL<3;oZ7ap@Vc`H{)rRvmOmG-X>?EUw;jh%25fbw19ym3^j~gvY&6T6!o0Q)Ia5^ z%5Qior_f>Q%)y@HJD%=rj-*!&&#iK*)+pE|U}e7TH>m2;)9e1w?& zSG68RgEM4SwR7N!IiYIjmx(1hAm=tHv1)Mn=)UwJ@`rzVNP@K@+$90 z%*zu-7&xW?Vf}c!`81HRg@(DDzoqMM8L8mwR{9p0$}}(Ynh{x!LFfh@wRrmo{oPH~ zo-S*PpF0{9EOz;rlmVed>FpQEJlFtG1-)#Z%RK}8Jy*w!h6OwqgSKq(`?18%!=SR_ zg&j@n{h_@EgiQf3yS%Qxe9ITc``xI(Vrn0%Ym3A&dI;@kUZwDfUvy-zyli<;ScOPS zm1g$W3H$RRf8by?=fgBxpLBA-SZvqYc(m=b-4R?rCyT|^lWco)-g@N7d{f?t2?tiA z89a{lq2F?u_^;&`LJ$&0$UYZ|!ZJHZszicMqtzx)wXSVGfEq zWtOhIqZmV6+>dns{;Sj(Oo>nMcaEn}+)A-%9o;=LfAIqSLSqRgmLxMK*`ib7;nUli z7`{X@)ivHs=9`D#QZ4?GQ|F_$NEGVjy`?(N*0GkF%%1b!E2<%Mha(kGdZ6V|t#U=a ziazjcH~xlt(37|GPx(qZ&j;SINvOvQt**i!?5JNeuvB*~YNxL%NZse_&U^NDu1yZr z&-?$M4T&YK`Zy`_8%i(wzk9(!04`*AEQwHyj03UX#wSysBlNl)!pLx*=q2A?b9#~^-lHg46 zn0JBVQA@<)O-l-vdAw_JZ2~{bOuE>^!gNU3I!SN%-tuLM#*cEktQ17hRALmz<{34_ znszbsKfZ7vBTsC=xk4D*uf8aKpJ-^_9<8FI=cK;LbQh#@1(TnzMq4p<LUYQn>LbLx@8ALD!Y}JNIY-^ zmvD<&Yb89_P~Yd` zgfCToIIp{T%ayGM<{$g7#fK1cC0D+iaM00u6ezy-`flOsHueNhcKbjrql4#5Npj-O zQ@q+)JB`?P3Zo{^hwCOZhP<7e43*-487e!XGU23B7&N&%Bln_lgfC&Ok+MgS2no;ke`54qN3eAjk)+OTW|&# zG^s%IbYGhgyoymWdlDM;vjbH!y!j ztrrT!x$SwUUb=j7v|h_Tt2su`O?@1<51M<@7`roJ~!L4^P^uLcPQFg3r4=h7R&6TVulA>zmW`|Ns7D2IeOCZA09~aCB9=WSHB`pNhAN| zpsU1MlS)P@b}==xG;~I@&n^3bHp!$r^kLD$j38WeI$SC9Eo=)Z zdl5arf7w`(A16VBLlJ7ED5~RK)-0OeDrixVSgny|cu2&S&$-Vr1`%xD2?`>vJ&PgY zUiy$Du5(dOie?(cHQzz1wvMh@$%!)r7NP3-ij`r3ojuMM`{Xj@m`^=3(o8;nvZlXm zx!qg}+A(x{vH{ifXgHP8W%|USc~{M_4j5u-By?q?>B1Ywn?B1$qu!@#8(!+WzO?(s znYuW@yyUR{r=<_+Wd}2fWP2a3JaKxiVG^bFV(955%>u6Led&3cqo=PK=u~@HtX`?! zTxg!q@IZ6^zIe*uM~{0wj$&s+qnz`no!IXSP@fS zZbRoOs38;u_lDv*q)2<_NJ%D-hhMZ@x>H1SlDj(JDj?{F9j^Ysd#^xe+WdkxiH@oJ z>6+AOlk}yEFORQBlr8Ik{3p5|mp9Uxr+>=r^5SGArkf5wc{Mz<`=)fO$arLQx+8J7 zZl0hvEnkz?Acvdgu#wdn!jsOUF&CoMGS>!5?4$GxZ|E8mPQJ9ao!7G#%N}2O6E_Mqi#?l)1z7>=K(U?WU_BEuPH+4jqYci+uvCUlvd#}$9wuJklBV$9Y2*K@eJ$o`Jr`xH*L7`U21~-&KUeKC7trC zEmcH6W=TTY$1TNEK)sFGdFK7hagNK4(FXo8Ha(r_w!qhosqC-xMI-lB>od1_KMrOw zz-{bXz?3r$vEoX-{qzp6xziI}f61ovkwi?vvy|ZEOJv|?CW~pgGiN_6vPbx8Y>9Dx zui*H?we|DiQ*=Rg!$WZqwy#}Ao(4Piy@A%HMhs%XC5w=d18n7<%=SC=*kBHHm>73M zgEn0%VhNeUky+=uAqf5#b9Xso8 z`|0rmu`6bGPGspk!SP)>N=&t*Q(6n=#*hRq65+gf?KKW%-eiQE&?x`dr zy6t}O1X6^ynD*i8>u?fM!4U~f%*Wm`C*Ks!!HQ?g7o2?g8HM(k^keeveQj44oq)gD zy|#)@zaJr~)y%KFvDW}x_qWbp_?>p$UrRLqcMk85m{O7CvJ)t}-4|{esa8no@;81z zvl==q^qF7zT-|}Winl z0jJ7NgpCT9fgys|O8e&%)}7!xLYGX|cL&(!2l{|P!`%(W2o2V)crw9F((2M$y6aTz(lbIt){vtXx$CNd<{Im+i`~`x8(rPNhk<5Hhs)vecBaGBS^UQgcT}qc9z`E} zJ)Owf^yE7Yw{zZDV%6)wk7Nf1&&0ofK(Ou6Ge#qlOdl@q(ii!2p3~eN?uwH>XZBYc zymaU)IAOK-`sintt|79TYKc4>p&d)&FWcMt=^r9^lIfBDYV2Zxge|U%&Pk1Qmf`uZ z&eQ>y1x+`)L7hZ0Vp0KT-Rq|bbxAGz>PZ6Vd6+|^FZwjYH8Z^Kznv)2*B8g5fCRPB;>5YvbKCCZc6%b@}GK@yY%uUU}YEmvx=h zT5C4Tl<=vo>yMBuQ>yL=Dc*)0y7~Ijq=Hk%X+He29$Sav@MP-4^F4MkfGB1t0hZ60 zq}-Ay<71^ypz-WKB%!BLhwafqzsT!&Gikwo`!;805ARm9uiji|Hn$KS!twXq(Loi0 ze%CO`x9IAk_TrT3QvnmhJBPmyM9Z4glTi-Ux4bIpASo3_W!1c8du^`76Sfwr+nMKm z^(ql7>PV0iq`S#yU0}k zGAE=bz>7J%`syOWv6e0fJBC;?9(v!YNw{2rc(CN#(t|hWP2jvvgM>q`VypceHxHi% z%BDG*Jj)t;&1&C3!+mp`vP-&fSm3%6heeK}v4JApTL1w&`dQf{x_iK!*ls66Bsa>8 zbT-cpZ@JVqboB#9RHM3OP~Bzhwp-?M&6#{Gy{O@;=aD1mS$mlemUVCQj9NP19q_t34OH_WM)@D4{epcs!wC@jyXV7Y^5H6SQzeKpa_!#f-26uGRSZ5}YkoI9q zG0Vt=Vh?RO{aR+*g2(PwOyK(I7U|3WTfkz__6Sp`xe=qnjw}F?73@K@MFgQqdYYxe zVTrk!2oB{Gh_JUBHE%F&FLQI|Fak%sl)z3tq@xX>8rhQ6FAjlQuDo8ZSX+4&kq%^#;kKw3 zQ^}!^Vzh5cy)Lfc6&;YT$32+LZd6uxkP$55e9iW=6hip?zd4f!9@W!t!IR02DL8;w z4QaUeVntnNpNyuZJobRbFu{hQWDl|q`nIzTsu4<8uyihqqRqO7u7vB~XC{dl7S(R^ zo;4Yr@*7U~FxBQgcpDN6pONru`kuAyFSZhgfc>m_An%UM*uB7k%v~ndGF!a~$v@C_ z==A1}F`r4s+|Wpu&D#XU8hj7UUgT_?GMb1EttOO-DZ)80(p>3*%uTe|$$wP~x9C^b zzWCYtEp_KRd=4#T|~x*7RintR~b8EKI7V5?)V5hKse{*`!=>rl&b!-ug3PC$rBVF zmhek_5y9f`h?-&Us-e$&Kn^I+aUojYH~)gfyneO}{RNrpJ-D_e^92a9*86d>Cuar- zve$=j$tLp!3UburxJ*W;({#7zN2~1!B>QVS3bt_MDO6GZYA0}^k*3(AA5fp+@7Ucv zdd43J_0+F+4uZ!)#|d6?X0MCtQj;V%s^);APk0UTPR;~u=^WQ(mR)oBq-e**a?T<6UZBbUH(y-bT(j^e9iL6ORK-^k;7+5gRy^ z<0wYNHyjpqS@IpCWs3gvNLz928gJ_Gy#w}Zvub0KGSD8q5rMivxwWO$c5p{**_!u* z)01lqS1xaS6z6Z@+cNV%YwGUAq|fr?U4?=53w1m~gSsm&f!Z~3=m^7eb&Olfam#zH z+B>HU>Q#K&QpTb>@K3q=itU6A-RCr2fR9)i+YA0VoPc%&F?4&I<=kNK0qXdVkL>W4 zdiBug=%*J6_~;`2-+;s;7A;#^*ziW91W)|R(c6`u1|2Nll~*_@WpSbVJ(g`Op#gMz zF3x4O&Kk{4VC135Le zLzV}4$z~mtaLwxl-Ksr+;k8hBBZ2k6M=d@Fk8qgKV;hMW2SFE(8-4J{XOIPE$Ge}s z)PEAjB%cD_iHP1Cf#Wql#RB^fv8bQ@(jwcKAO)P2xzUcu<0jR$P=rQVyd;5l6|!j& zr62=LxAaCX6|kuNWf^SlB=t$4uR!OW#yUZBn7Bi;@u{~p+Wg#iLp?+yYj`x=b{8KquLezwX9_x z*3?#NvZe6J)v-PN0D2&)%6;O?^~XuNc~$41^bz`x-&_kjN}V_*=Yh6`B-keSz2kFUlws)sIid zK3E!Te$bBoF+VFChou)ZRU`wLmG9v5Vc7N}FhpG4^e}N4f(Ig_qV|tDzxU3-BBE7& zKt)=iE^3Y&*t&BQY0zkeGT$BK=Slg)o4aPfKDu5-r0)pn)4&SDViRdmN*TN_O@R`e zbg+WlJs33SQhA>izEzMGNb7F8c^XXKX{%CeH6#j@CY7uBPTo`gI`@{}R+5%INf(wD zCYkl{HS$RoL$%>n=i@y|lcchh7}B&6!gm$CQbnP8!+zHnk9lU&N6#qFg~_#t`|0TX zJJ*+EUIwI-6zl)EjLAh^=MwuPj2L_zGa`lgHMSRqAl0wE} zB}$PNFPsPoF@suU^d@M>_vQBY*3d#?@&1st`GN}Wmx8vvr#fy^jSQYTxPK9J$~#^M zGs2yi%!%K!z<>2O`B)-rYy&BE2-%h635(3dW7qHQ6V8P6oz;_9RYZEPZpBa{OQCEQ zHSEqOHyS|*U8lcU3`AGlR7aF7J*+f#Ua!`}P?{Y$L)JklSZuL%=nOv5`|f7@66Z;# zsCFTK?Z1G8RPpe#kOAJpbVFo^BgR0KYEYu{_6l)#XW{m7Q=sfx8O5|3TkoEBO4 zdSY=W?Y-i63|E=gD&S2<8k9KQ?p*Pp%EP|g^s)lZaTdz*8xJB#MB4j(@zshlR=v1f zQ{@Cn_x8m{-%KgLPZ(@Xc>|A;4Fdj(A`X3Wmwon-)ASB^zW$&FN8;S>A9rW-Z+G{b zy)8DGOd8=JbSbH+g+q}$YM!Sct-K9#icNP4DnV>16>anY*z73*FsM=R2-bS7y3n{N z)RP;Jh&vk(d;lFx6f8f6&{N;biViD!WZeKEW$k#8_hO{sij|mjhOpgB2Mg&eWM+Vw z?njUV%f_^?oC-861jq;So*_|_K1h9!_Y4b*j!tc@T=3e`i3~|yB=o$wbNaIQg*>sB zjw6Nq*Q!IAb0(~XzoGMB;YT(YKU0d|U)ygiE01Ij3NwYrLQtf7*Ct7;6|MQ!UCru4$62&4E_NB{obOie&Reab@E(|lB&42|Z;>ee&y$B(dYD{> z!kZ(Wn8bD6eP4ER1qZ}|r&UxQ<`n$bjxkXcKbPOS+zkq!_2DN7#fLh>p9@H#N6HTC zbdIOCl3>OW?KzjT77cC*nci4LY^*ZI zKzqKMj5V`VcXCrjI)3ZlR)ei1c>RiVb8%5*aZ8;Hd5lhYFH~)USc7r-p&z8f zuldvC{h3I!9V#kl0KZ>3)=yC^<2c%WF3ab#G?@XBRv(?0EeQt$&1hG&2pc0poo#(F z2cA`UOL*6VF=oJGJ4G7(qTtJqO=D@f%&5mOa?3HPp*6F?`Z5z&h9~;~-jZ{SRkT~Tnb4pc*iw8J4&I}u zh@J&kk;2MNMbYQP4NWPxRBbggtaP@5Y4eDT$~(y9^h|@$p1vEKwyUirkY+s72N=&} zTA#fd=yP2VJ^5BTgAx5>KUMVm%Vr9#+@RQ&j_uv{KvwCvE8ld}=MDju0P*5v=_o{N zk$(@``UdSIv2RRRE{ADV$ve|uB4`}7sofDn>Bam8z}H!J;#ru-4`ofq=bma65C{gW97;TAL#U z>RI1JOZHt1g*6`d4_0-wzCm;X^-%6SO|wV4@gdfw|gmX(xx zCkeFOtzdjR_wxrfSL_h@GFr9qs~BKO{ry+P01wpb$A{JRKi($Szv?I}qd)!S6|$RM z1pZTTfJE@_kKDKptKom#``KUh$MQe>OS%jA)ZxM{mUB*CD-JJL3tnxMF)v=w(5uFi zG^3y1%4!&fOa3G^aiQ53tsgex`Gn4@#!Ipm-9DST_~k&WYp;@}sM+lYQts`=7ifU$ z7jLRe>gF77iRHv}zMDxh+Ww>H-YVOCjD4(>=TZ_D^B;9Fi{2q;SG_~MClpVbrPj|U zo3tKF&DlR>7kz*G<8xiy8JJ6I#g0aF4Z#!OrXCJ%5wCA!&-FN}ig{i=qki;oOssWN zMuFhZLWs(CGlnxN=^}1aLn}?MZ23X{zu(EOvzLZcDEqkb*zH??>4mQo|Wr%%qLSS_V5Gi+$!zVxoCdReu!j`-{o6kQF@ z&m7+Q+Y_vlxTcYB!A*xM8S0Gkiin-cE!Hj|jIcj{-a1^(YH6ST9eRLaDCd5c$HKO~ zI!=@QjJY<0Re`O!CN(?p@{lCKhL&E+zMkIAyK(9Z5a$w?nChbaO;6}?mb?DN#d=azexWeMx`P^+>)U2Qn~t1$ti zaz1df4TpRijWC3E2124RSW$Fif z;#yfoc+)_nYljms$`%{~o80y##tm?x3aa#<^pyYA0Ri;T-*1v2&{$;P<|E04k+!pl z+Ndkp0=C&tHU)i0A#bwNRt~yI>8}y+$m*+t@2YL_$Wg$C){ozN$$y>S5GYbKJv%DC zk7m0`Zttm6Duf40F~!dF(OYYRq8*C<1E>#&MmS<8L@hBJhV0Rfb1x-AIM89NbcF7!rb?@TT6T ze6^xyuY;T954)}0Rl8RC(f;YId2GQES&v1Pl<)P|bo2O>apo9p#hNHo?Ki}e2^^MV zKpOMJ5i(xsKSHf!3a$I~fUH(B1OKpa+x}9~bnMFpg&&wkAoX9q)qud~hpkIE@TrT^ z4eCzxgJW&SF_hBI%(c<$^fn%Jn9QiH9O8nMXE$JoNy#nVlcoFIuP>~{&ieP><98Q2!x=Yb7rFs03dxG-xK)t zlQx*%e@{LB{}b5yXSc%fe-_Zb{F}!k_uu8gR}UfvWDpDki_7|h`TiRg_qVBMdTJX) zo~1ABa5@e`mVCs>d*o-Ty8n;MRe`(KuNM&hKQl>$MKy08xl#ds&1ySvWR$duhKBKA zAX#7PGGn@)kEN{)T!pj^IPocXvi&6a!b|@zca0D3;g%;XTaP3k2!f>=ku{GrC;142 z@(pUIBQ+t6ltdgPX~9tdg0_e_o;L`cn^wT^Fe@4f;etr>@DH#2m4VW~-bBnaEQ{N? z(-hj@@Unl<>c6A-Xd{1V6JpL?<+`tyHqS$b_n>K9tu&mw`DFcf?;_$LXTcD0&mj1K zlV2^eTEp%JA~b~jsUcPyAS5Vw1o)?jYueu|*Z@t)bsZd@TcV8J(XwT3Vpck>#_r+TF73Ytp`+j6&Z)|9Yx^G)t z_cxo^-*$Wdl=GyaNEwSb*smizkguq_D=I_peiY`$TQITK;uCu$TkTH^Zl?D0TVRD)Ib@JcID*E3t=dW53zpiz+=`{7VTH(y3iF{*B69{Q@_U3Khy{k zPM`!}+Ybj1_IhU^FX3#q4uN)c;%x1~;|i2=JBzo=^s-!XheW91r;p?BgrNX%3JOD6 zu!2ScSs)|6|K+RyQ+0=SJzBes6%9DdQ=Ca14#2!Q7ofZY$OjqWk+8=|reR-7jw{Ih z=~|^pj*yI_eo!&0b*25u{!hVK(0yY=gaB47J>ZVWz39a+clXc>c@U+x7YJCI2uBdZy@6 z8q|wFE|*ZuY!+HtZQ0RNF7yA)=JCJS2mh;H$e;JtaOphZiP=2iLhCSWgHrTY`I;1C zB_rp9Msmz zKv7CX#3nN{wjx5sqc~(%J@+7AFB6Yk`@J<%#2J!KiyBVG#Pr4qUKA9P)LIzrJn3%g zq*dH|>WGT!0p{EZQirxt-J?)R9;7;iHBIxat(imZ_b_^`7_6}f8!}VFs$gIHwVe%{ zmbYD09pVq8eWYC{XSC?FRJ4nx7(U*7An{8c^2Py*Ru!2nK>5B>IT0J38r znfhzH>7O(+G!@BXjiE!Kq0MIMfEX@-i>rK<7uM^1tgvMSC`h!t8m@x*BjDv* RW;-$yf_Gi03C`Y5Igqr1L5=16+lx@PA^oDe#+1OtzP_xVTT!~Y>9x)9)ZYE zy&En7o==ZIZ&HAth6MGp306Sph%z)9hQP)WV%DBO##eeOlBk&p1PSEiC!($ITxdhX}>VSd%e@VHX(r+77;|YX9S>l zWeDzpDqtXoj-FjFgGH!)j0FubgUNzOvHQ_iShvj8QKQ@Y+U17h>t`E8?P>~3^N)%# z|1T}dBV|~6HEktII={vIp=W#p1}u~@+2O0VYlhWFngs36`K?UfSDcFeh_}$i@ioeg5-h+7y!{Obp+h9E}e;@)i=(rs&zjm$aUuy?(gybdr46u5ezO_8dar9*(^DW4LS)Vi{eEu!L{%)KG*itJWwFD3{uQs@ z3!$dd?7$8V&@rE`We??2^KSBh)qD^HLmYsxYxad6o4a1&vC4CP_56?bTJmeeBkz^I zEGMS*!H3~wj?Z&X-pVN>N>5&N*zqMejQHINhG2@?8{wPT*%kbPgS+Sde40M$v?{BZ zM-{5%7(jd3%;66uKd=M;)$jkGTG#)q!v9|^(ugee|KedqZn{hCAx76Mi;0igC$&-3Tc ze~5Miemn2|H#RzZmSqU*{bq30=!W&Xihy|4zzN~U6&26_nr$FOQvD>pYgle#i{)|G z)NwAJiwmC!PFsm<29MV&Rxac#-A;bgt^TP_#urkaz}_4iN`E zW+X~wDDA#2{*PPWKiL=LQ<7lOL!ncEDqz31;*#$HN4(Y~S@Q0p>*ml23-w%)g$Qak zXfY$fKnU*&>1XoDo`Bk#1yQHje`#ioZbU565t6wMp%jX6LF3A8NRuXWU^7xhQk*;d z>-oWI#c^FjmK$|mQ(yGC>>IIJ7qd8h{*v1qnEelV!p3Zwc!IPtV|Xh96TOJNyE2Ax z#^E0ckYC>v#yW6w=I&DO;|t8NMQIuY=@;*jfOSOBvNeSQk;87eCx->J5FHVUIhPbCRX$< zZZv|uf?H|`823=!0N>H+p~wsATE_{KU^P^m|FQKorTtW;3-@Ucjd|?A(QbyW`p!9P zMbxH&;rOrJn1Qdy=NLbh5LUOJpPl?ra<_&=nxCkWy2CR-BCYHj7+5%7A-*tm->pLI zV@GU@44M4?Xn98S2RVjkua%tIImpGsk}R0qSh$I2a0^~wi!rr01>Wyj&W>eO7T+UB zj)ZNa`0{;m?sN0wtZWUA$0l1xCc0cs$G7%578kb}U>>?Ih&~>AdBLf^qwgfKqU_lo zOX&)t|Mu~yB8H%c1^&l;Q5JV7(6_j{BBqRq;%`z2rdkaP=G4Sw19?H~mrC76_WF(O zhGFB2qSJlUY{Q>Ji4SgPn6{*6Id*>Bg`U0TJeF0U1i&nkll>_-@mVSycFh`bP>94{ z{sbAcpG1+^PyM$L)|9i&4+TfwW8{~2S>-Jdp@YfvopIBq?86cxJf{k^ov?i@oJ6Ie z;1;e*iF=|i31&_sPEz8vptS$}~xu;L0??>)Ne3?mb z;Onb|$?NZ!DrpFb+-%s*$@->lq3*k^PbjgEnK|auBy;5b zep#{R$?5D`=cV_FA3ur5m#|KqB*?$@P78QO7GRHxWg?g^6slS++@yWPs$}!B*)@7- z&iWX(#YZ1z=lHEp)acpwk6-yYTtQ159Q9J;eA$sC9q5Y^i&FIGv7|m!NxR9y)#2W` z#X$AzX#WE&t6!Ya9?4ZVyZR?319l5p&b?%{oRayrLtH((++;P|hp?IM*J~d! zR@UmuNO8I#^=cccrN`LYn|7EQz2fb+$5JPGCjU!n5(ygWaqm;lhBED-W(Qr$gFNf5 z#@VYomUeI2q#e>YcJ1W*ZHyzFcB|>NIf}uH%LagzhrJFrQY5T63yK{35*IU=(Io^TscAg{t=g9a3N2nJwA=HXxrkE8O(Uiu-;bDp9J%mlt zOC<*h56#4v}QUQI<2t_v>cwfSjYFJj!5u4lu};rpf> zrtVivMrM#^2{+^OHFih0*Dg+agr#2}Af|t<8ERolAbL7IIIQj2?)}xibX;S6Ek9?t z&W>rxf9R_?zdx~&=$>$(rsD#}7o{lTi;|AAX2lkjmXeFX*jMy)-D2oijIR?l)Zn6) zn0~TDM;s^3@=ZXjXUFF3bT2izGIa{Nd`a?x?Qwu{Db==+R zS5<8%wP!!Nwr%>?prJtX3;Y;ZMwfP>*VY=v?PqKXh)J)=>?g+QpFV9N(j|nHejcs8 z_EhUmC|#_pGL8=y(&QA;Gil3Y{F)$k)xS!M?Sh zn+X~!=Vv}A@0i8cdriUi=A=&V^|sA_y3K?gXjOUD>ic1LrUfmpxmhoMCTG5*I(|sw ztpDpT71uvChPyz{VtH-u=NB)11TAVWF1iPyIi#cnv^tliK3lwG$F~t&7T3#A79#v-cks zWdm+k#O@2HG2VwuLUi8lEgNVr^g~qyJ_va1Gf-Y+&=@Z+pi87CaWxVe1N zwhedF?WW;-d&i;g=X9T$8I7+!S?n1unIv(LmOhZv3ttOdDehS+TpICxMmFNNzNz@4 zraavG5-`TL@eiJG;Z`EfSk8U8QdC0PTl8r1%F}c%s++28KPQliAoz9>eGh)bAKk{k zAm;Gx7JcK)03%b($%S4{XM(kWNCB23hqOAGD|U$B;F+b}JEJv}c`WBza-NRUM6a!F zj!yVK?V5K**Zp;w%)nJ8&9K-P)g_M%H;JvGu>{k}54>ArjCz)D9Tqj@AHZ@2NTeAn zyI}G&MXze{q&F({m@n6L2xQ%HGc1NR`{!b(e0rCjt;>5%(IT}0W;HztpEY|=*ls}g z&d!s>97Els)Vt8E3`#NNl3lkKq(AQ^z_~#gyeWGxzeS?HYJr*nxVE@MT zEf2n?=GHrj6NterIE9n@b?!n-LYoG0pFF)d6zPZ?k(mPBs4x+{ES4fGaoGkXahG2+ z6J{Z-B_2{vUrcV=banX4j_*(FBUMxrJXhLgFLvjeoP9s-{fd0}OUssh-kG}3tErYn z85yUqPbREkD-WQ%{80U$1%hs)YTm4BITwVNGrJ$wu4#1~ot7khKl|RE=!cToSkm7~ z-nL|SYqJ#9c9ZcS)h z82Lu~?mSDM^Tc?5Msdf8BzA>+G%1cHZYcvb3HN$9i5C@o%gk&ZX zS!It1NC{lY2&Na&+RfB!hr3W4$0Z_MAuqW&+g6)v^E@_3p7WFY*SpMJ_xX*9p2#ql zCzi|G7mj-$=FPxmucp;zg_f}|I4#O4H1(PCudYlbU%EDTR^b(`8|hsEC1&NFl~Abi z;{rdT07;BD+k@w?8@zlGvq;R~O04~|zp|;DW%wf2!?TGpoRoc>6u%tfQX2)%arS)~ z#KHI+VYzAs7wCnsh zcg5lxyI=@~Rm}!uZl>6k#q8joO~NWiu}`_|>{YenquL(xU}~Fj~BdThiLe}nOvxSXwyS1^K_M#Ty#jB4LE%NeBoXLZ9Z&Zzcvvk0M*H1 z0l@{w|F63@4~M!9`^J^hqM@jfeJP|2k|iTa2-!+X%phB~8T%3wvSf+uYqEyOE(Y0( zWEuO;FjRJ-?7R2+s_wh{d7k??-sg9`$M0SI(UE1o-)q0l^K*XA&zYW&A|PEuw@8C&08%#G(W5*W4%&d~zA+X9lERpbTw_XLoe3!`3u7*xS8eQn z0j~0N5gYWgmjR}hg!&)yp42dd!a$wAjh4|;q{1`57?Oeb2 z%~@U9{;najWaYitQrpV0*Ud9^B*m1u{!88YV-qd$8H-3|Kl45tQAeVXPwyYYZUPK`%aI4hyqk&4Qls`XUM2QH=8KLEun9f{IrFl^M$9DqSCsZ8lcw z+fNqL;Dz8O1n&bDv+nNpIl;fpB*Ci~r`IuEkxkFmcfRRq7G}ynMBL}uR174<3{Zwj zNXk`iN~LUVS;xG!is02MDr$k8HkR)efWr&LsX^?i`3n3b-XxdKtxphyTOlLxj29xN zMi{ex_dg94I?*Say4uX%5d@ahaD3g`mo?2L3{uT})o; z)&apMV6yG!U)7WSWqmX(<#A@t+*K=kouKCtIXNpJCFQ^1gK(A7^VflIgsEN)0q5Wg zf;3bB8BoxDoogaNeWN{e37|)UQLbP%f|`xQj-bdAO*ufZCNISIn>YHBu~)F5Ux_?y zzun_k;yYzs;}zByO&V~;I(kxykWGO5zDRYZgFJ=h95}iU-I53%$djecb51O(@m(Uz zI;1bbHsdZfDNaU)7DM&sMi$U=+6dYR1}>!z|L9rH+z*`K%rb1`?&3pt^eHiVxs44; zOO_CDJ1~{}Pk3a*b68aB_wW0}H19nVx_95|{o`IK;*(x!a)(B@r9nC|`d(U_l+4{n z*o5`}(PO*ewV|x`eO|3^1 zkdQ~b9@`VM2QR!Rnv350lA68XM!L-OC^S&$__~E#yM5-*_w3}!5+93T+VKyh_5ATX zM^M3-KOB*F8`Y6--n?nc8+-3g?yg4|`QS-jMNalU;*O@Z+RFS8Pi7QcZl{GR)>z)%Va3={NnOd4kE;X2Uk#_azTOzRO0yoQ zjrS24NTWQ8DukVe<4uSmc?Y9t_FUDUUI$-$-WUK|Kvx0r9sCQT9+0jr1P*wpB)kcK z7B*%x+UD9{E+S_GZw(uxG(H2Hbj%pea4r7jEkEj?)%)};Zeil8?O2p*K-li`@T(At zJrL&MXqo*GOSMU?3ejQU(_1hA+u&fqUay9uE&d#Zyu8%3v`!0kpk29V>^GrooS>{prt^dLxXCjKHvgZP&E#5g=w1ILvCTPiN-t2ZKmP zmO_Q?G$pDK9}V<$is;?~Zw4R@n(xmy%Tz~(hSJzRkgyr`g_vn8b3^7-<)Aq9__cDN zVglusj5vZvJ?ToqBC$kMMpdHoz<4J<0l%*Zk&eBNWdx0~*@KOKIoYLNh*PId<>#fQ zr=R1)0NC`k7?~xhJO;o9WNgZPU^(nHCjkHyB1te*VYYmq2f_W9@f{VldX4TR9>m}9 zq.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..0ecbd30a9aff96 --- /dev/null +++ b/examples/thermostat/nxp/zap/BUILD.gn @@ -0,0 +1,36 @@ +# 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..771592217b7cf3 --- /dev/null +++ b/examples/thermostat/nxp/zap/thermostat_matter_thread.matter @@ -0,0 +1,2122 @@ +// This IDL was generated automatically by ZAP. +// It is for view/code review purposes only. + +struct ModeTagStruct { + optional vendor_id mfgCode = 0; + enum16 value = 1; +} + +struct ModeOptionStruct { + char_string<64> label = 0; + int8u mode = 1; + ModeTagStruct modeTags[] = 2; +} + +struct ApplicationStruct { + int16u catalogVendorID = 0; + char_string applicationID = 1; +} + +struct ErrorStateStruct { + enum8 errorStateID = 0; + optional char_string<64> errorStateLabel = 1; + optional char_string<64> errorStateDetails = 2; +} + +struct LabelStruct { + char_string<16> label = 0; + char_string<16> value = 1; +} + +struct OperationalStateStruct { + enum8 operationalStateID = 0; + optional char_string<64> operationalStateLabel = 1; +} + +/** 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; + } + + 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 { + struct DeviceTypeStruct { + devtype_id deviceType = 0; + int16u revision = 1; + } + + 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; + } + + 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 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; + } + + 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 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 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 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..c600dd11918a36 --- /dev/null +++ b/examples/thermostat/nxp/zap/thermostat_matter_thread.zap @@ -0,0 +1,16489 @@ +{ + "featureLevel": 96, + "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": [ + { + "name": "MA-rootdevice", + "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 + } + ] + } + ] + }, + { + "name": "MA-thermostat", + "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": "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": "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": "OnOffStartUpOnOff", + "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": "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, + "endpointVersion": 1, + "deviceIdentifier": 22 + }, + { + "endpointTypeName": "MA-thermostat", + "endpointTypeIndex": 1, + "profileId": 259, + "endpointId": 1, + "networkId": 0, + "endpointVersion": 1, + "deviceIdentifier": 769 + } + ], + "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..ed25f04ae02a55 --- /dev/null +++ b/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter @@ -0,0 +1,1978 @@ +// This IDL was generated automatically by ZAP. +// It is for view/code review purposes only. + +struct ModeTagStruct { + optional vendor_id mfgCode = 0; + enum16 value = 1; +} + +struct ModeOptionStruct { + char_string<64> label = 0; + int8u mode = 1; + ModeTagStruct modeTags[] = 2; +} + +struct ApplicationStruct { + int16u catalogVendorID = 0; + char_string applicationID = 1; +} + +struct ErrorStateStruct { + enum8 errorStateID = 0; + optional char_string<64> errorStateLabel = 1; + optional char_string<64> errorStateDetails = 2; +} + +struct LabelStruct { + char_string<16> label = 0; + char_string<16> value = 1; +} + +struct OperationalStateStruct { + enum8 operationalStateID = 0; + optional char_string<64> operationalStateLabel = 1; +} + +/** 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; + } + + 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 { + struct DeviceTypeStruct { + devtype_id deviceType = 0; + int16u revision = 1; + } + + 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; + } + + 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 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; + } + + 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 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 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 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..6da2d2bf7a2def --- /dev/null +++ b/examples/thermostat/nxp/zap/thermostat_matter_wifi.zap @@ -0,0 +1,16489 @@ +{ + "featureLevel": 96, + "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": [ + { + "name": "MA-rootdevice", + "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 + } + ] + } + ] + }, + { + "name": "MA-thermostat", + "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": "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": "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": "OnOffStartUpOnOff", + "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": "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, + "endpointVersion": 1, + "deviceIdentifier": 22 + }, + { + "endpointTypeName": "MA-thermostat", + "endpointTypeIndex": 1, + "profileId": 259, + "endpointId": 1, + "networkId": 0, + "endpointVersion": 1, + "deviceIdentifier": 769 + } + ], + "log": [] +} \ No newline at end of file diff --git a/src/crypto/tests/BUILD.gn b/src/crypto/tests/BUILD.gn index 0f2fde50996481..209d60e9536c39 100644 --- a/src/crypto/tests/BUILD.gn +++ b/src/crypto/tests/BUILD.gn @@ -57,7 +57,7 @@ chip_test_suite("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..d40479aba793ef --- /dev/null +++ b/src/lib/shell/streamer_nxp.cpp @@ -0,0 +1,249 @@ +/* + * + * 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_component_serial_manager.h" +#include "fsl_os_abstraction.h" +#include "fsl_clock.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 24462da32a920c..d9954757e1f844 100644 --- a/src/lwip/BUILD.gn +++ b/src/lwip/BUILD.gn @@ -31,6 +31,7 @@ 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 == "nxp" || lwip_platform == "qpg" || lwip_platform == "mbed" || lwip_platform == "psoc6" || lwip_platform == "cyw30739" || lwip_platform == "bl602" || lwip_platform == "mw320" || @@ -67,6 +68,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") { @@ -165,6 +168,10 @@ 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 d0706b47ec91cd..9bdecee2241c2d 100644 --- a/src/platform/BUILD.gn +++ b/src/platform/BUILD.gn @@ -224,6 +224,16 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { defines += [ "CHIP_DEVICE_LAYER_TARGET_K32W=1", "CHIP_DEVICE_LAYER_TARGET=nxp/k32w/k32w0", + ] + } else if (chip_device_platform == "nxp") { + import("//build_overrides/nxp_sdk.gni") + import("${nxp_sdk_build_root}/nxp_sdk.gni") + defines += [ + # Nxp common files are used by default + # If platform-specific files are to be used instead, EXTERNAL_COMPONENTNAMEMANAGERIMPL_HEADER should be defined + "CHIP_DEVICE_LAYER_TARGET_NXP=1", + "CHIP_DEVICE_LAYER_TARGET=${nxp_device_layer}", + "CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE=${chip_enable_ble}", ] } else if (chip_device_platform == "telink") { defines += [ @@ -479,6 +489,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 b70b576644318e..54440109b7f4a9 100644 --- a/src/platform/device.gni +++ b/src/platform/device.gni @@ -124,6 +124,12 @@ if (chip_device_platform == "bl702" || chip_device_platform == "bl702l") { } } +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" @@ -149,6 +155,10 @@ if (chip_device_platform == "cc13x2_26x2") { _chip_device_layer = "qpg" } else if (chip_device_platform == "k32w0") { _chip_device_layer = "nxp/k32w/k32w0" +}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") { @@ -241,7 +251,8 @@ assert( chip_device_platform == "external" || chip_device_platform == "linux" || chip_device_platform == "tizen" || chip_device_platform == "nrfconnect" || - chip_device_platform == "k32w0" || chip_device_platform == "qpg" || + chip_device_platform == "k32w0" ||chip_device_platform == "nxp" || + chip_device_platform == "qpg" || chip_device_platform == "telink" || chip_device_platform == "mbed" || chip_device_platform == "psoc6" || chip_device_platform == "android" || chip_device_platform == "ameba" || chip_device_platform == "cyw30739" || diff --git a/src/platform/nxp/BUILD.gn b/src/platform/nxp/BUILD.gn new file mode 100644 index 00000000000000..7f62bb964077ac --- /dev/null +++ b/src/platform/nxp/BUILD.gn @@ -0,0 +1,23 @@ +# 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" + ] +} \ No newline at end of file diff --git a/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h b/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h new file mode 100644 index 00000000000000..b2a91fddd25961 --- /dev/null +++ b/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h @@ -0,0 +1,109 @@ +/* + * + * 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 \ No newline at end of file diff --git a/src/platform/nxp/common/CHIPDevicePlatformEvent.h b/src/platform/nxp/common/CHIPDevicePlatformEvent.h new file mode 100644 index 00000000000000..227a8f3e6e6265 --- /dev/null +++ b/src/platform/nxp/common/CHIPDevicePlatformEvent.h @@ -0,0 +1,125 @@ +/* + * + * 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 \ No newline at end of file diff --git a/src/platform/nxp/common/ConfigurationManagerImpl.cpp b/src/platform/nxp/common/ConfigurationManagerImpl.cpp new file mode 100644 index 00000000000000..ac46a3fd0cb25e --- /dev/null +++ b/src/platform/nxp/common/ConfigurationManagerImpl.cpp @@ -0,0 +1,316 @@ +/* + * + * 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 +#include +#include "NXPConfig.h" +#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 + + // If the fail-safe was armed when the device last shutdown, initiate a factory reset. + if (GetFailSafeArmed(failSafeArmed) == CHIP_NO_ERROR && failSafeArmed) + { + ChipLogProgress(DeviceLayer, "Detected fail-safe armed on reboot; initiating factory reset"); + InitiateFactoryReset(); + } + 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..8c3163ca91a683 --- /dev/null +++ b/src/platform/nxp/common/ConnectivityManagerImpl.cpp @@ -0,0 +1,508 @@ +/* + * + * 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 +#include +#include +#include +#include "NetworkCommissioningDriver.h" + +#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..86353e08baeb9d --- /dev/null +++ b/src/platform/nxp/common/ConnectivityManagerImpl.h @@ -0,0 +1,189 @@ +/* + * + * 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..7d2a90f27e9b26 --- /dev/null +++ b/src/platform/nxp/common/DiagnosticDataProviderImpl.cpp @@ -0,0 +1,333 @@ +/* + * + * 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 +#include +#include "DiagnosticDataProviderImpl.h" + +#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..4a9cd27f7f18c0 --- /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..ec6ded663abfed --- /dev/null +++ b/src/platform/nxp/common/KeyValueStoreManagerImpl.cpp @@ -0,0 +1,98 @@ +/* + * + * 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 "lib/support/CHIPMem.h" +#include "NXPConfig.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..3b1e52fe83bb20 --- /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 +#include +#include "fsl_debug_console.h" + +#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..39660ddfc6ee04 --- /dev/null +++ b/src/platform/nxp/common/NXPConfig.cpp @@ -0,0 +1,610 @@ +/* + * + * 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 +#include +#include "board.h" +#include "FunctionLib.h" +#include "FreeRTOS.h" + +/* 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..b8d7cb95992df9 --- /dev/null +++ b/src/platform/nxp/common/NXPConfig.h @@ -0,0 +1,202 @@ +/* + * + * 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..ed32cab697a167 --- /dev/null +++ b/src/platform/nxp/common/NetworkCommissioningDriver.h @@ -0,0 +1,113 @@ +/* + * + * 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..d1ad38a5598922 --- /dev/null +++ b/src/platform/nxp/common/NetworkCommissioningWiFiDriver.cpp @@ -0,0 +1,445 @@ +/* + * + * 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 +#include +#include "NetworkCommissioningDriver.h" +#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..3b0d34a05ced0b --- /dev/null +++ b/src/platform/nxp/common/OTAImageProcessorImpl.cpp @@ -0,0 +1,358 @@ +/* + * + * 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..b35ecef6ad3fae --- /dev/null +++ b/src/platform/nxp/common/OTAImageProcessorImpl.h @@ -0,0 +1,85 @@ +/* + * + * 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..be5296f1a9e461 --- /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..a018ed4fdd6550 --- /dev/null +++ b/src/platform/nxp/common/SystemNXPPlatformDefaultConfig.h @@ -0,0 +1,88 @@ +/* + * + * 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..c146b1c7168e3e --- /dev/null +++ b/src/platform/nxp/common/ThreadStackManagerImpl.cpp @@ -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 + * 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..4d47bad43e0a6a --- /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..818f633d2b0262 --- /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 +#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..5c124431ea5293 --- /dev/null +++ b/src/platform/nxp/common/factory_data/FactoryDataProvider.h @@ -0,0 +1,120 @@ +/* + * + * 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 \ No newline at end of file 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..112d412fa32276 --- /dev/null +++ b/src/platform/nxp/common/factory_data/FactoryDataProviderFwkImpl.cpp @@ -0,0 +1,134 @@ +/* + * + * 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..b41182c9c6e192 --- /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 \ No newline at end of file diff --git a/src/platform/nxp/common/ram_storage.c b/src/platform/nxp/common/ram_storage.c new file mode 100644 index 00000000000000..4a49c16942b2a6 --- /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); +} \ No newline at end of file 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..6b92f8cf95dce4 --- /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 += [ + "../../../Zephyr/BLEAdvertisingArbiter.cpp", + "../../../Zephyr/BLEManagerImpl.cpp", + "../../common/ble_zephyr/BLEManagerImpl.h", + # 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", + ] + } + + # 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..4c0336fa6e416b --- /dev/null +++ b/src/platform/nxp/rt/rw61x/BlePlatformConfig.h @@ -0,0 +1,39 @@ +/* + * + * 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..00a026428a89c9 --- /dev/null +++ b/src/platform/nxp/rt/rw61x/CHIPDevicePlatformConfig.h @@ -0,0 +1,46 @@ +/* + * + * 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" \ No newline at end of file diff --git a/src/platform/nxp/rt/rw61x/CHIPPlatformConfig.h b/src/platform/nxp/rt/rw61x/CHIPPlatformConfig.h new file mode 100644 index 00000000000000..b6e25a193e1c29 --- /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" \ No newline at end of file diff --git a/src/platform/nxp/rt/rw61x/InetPlatformConfig.h b/src/platform/nxp/rt/rw61x/InetPlatformConfig.h new file mode 100644 index 00000000000000..830cc3e8cf17e2 --- /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" \ No newline at end of file diff --git a/src/platform/nxp/rt/rw61x/PlatformManagerImpl.cpp b/src/platform/nxp/rt/rw61x/PlatformManagerImpl.cpp new file mode 100644 index 00000000000000..328b22f27734e0 --- /dev/null +++ b/src/platform/nxp/rt/rw61x/PlatformManagerImpl.cpp @@ -0,0 +1,347 @@ +/* + * + * 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 +#include +#include +#include +#include +#include "DiagnosticDataProviderImpl.h" +#include "fsl_adapter_rng.h" +#include "fsl_os_abstraction.h" +#include "fwk_platform_coex.h" + +#include + +#include MBEDTLS_PORT_INCLUDE + +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +#include "OtaSupport.h" +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +#include "ot_platform_common.h" +#include "fwk_platform_ot.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..d4b5761fd01d05 --- /dev/null +++ b/src/platform/nxp/rt/rw61x/SystemPlatformConfig.h @@ -0,0 +1,42 @@ +/* + * + * 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" \ No newline at end of file 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 7ce311d6499f19..09404eb284a39a 100644 --- a/src/system/BUILD.gn +++ b/src/system/BUILD.gn @@ -56,6 +56,8 @@ if (chip_device_platform == "cc13x2_26x2") { import("${qpg_sdk_build_root}/qpg_sdk.gni") } else if (chip_device_platform == "k32w0") { import("//build_overrides/k32w0_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") { @@ -174,6 +176,9 @@ source_set("system_config_header") { if (chip_device_platform == "k32w0") { public_deps += [ "${k32w0_sdk_build_root}:k32w0_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..fba6d09501152d --- /dev/null +++ b/third_party/nxp/rt_sdk/bt_ble/bt_ble.gni @@ -0,0 +1,229 @@ +# 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..62d45d06f1295b --- /dev/null +++ b/third_party/nxp/rt_sdk/lwip/common/lwipopts_common.h @@ -0,0 +1,619 @@ +/* + * 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 simulatenously 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..8319ad4afd73fd --- /dev/null +++ b/third_party/nxp/rt_sdk/lwip/lwip.gni @@ -0,0 +1,256 @@ +# 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/apps/mdns.h", + "${_lwip_root}/src/include/lwip/apps/mdns_domain.h", + "${_lwip_root}/src/include/lwip/apps/mdns_out.h", + "${_lwip_root}/src/include/lwip/apps/mdns_priv.h", + "${_lwip_root}/src/include/lwip/apps/mdns_opts.h", + "${_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/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/igmp.h", + "${_lwip_root}/src/include/lwip/prot/ieee.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/memp_priv.h", + "${_lwip_root}/src/include/lwip/priv/mem_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", + "${_lwip_root}/src/include/lwip/priv/api_msg.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..a90a2b3b43ddc2 --- /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..ca379ae3f87d92 --- /dev/null +++ b/third_party/nxp/rt_sdk/nxp_arm.gni @@ -0,0 +1,33 @@ +# 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..6305b635884bc0 --- /dev/null +++ b/third_party/nxp/rt_sdk/rw61x/rw61x.gni @@ -0,0 +1,685 @@ +# 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_HMAC.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClMacModes/src/mcuxClMacModes_ELS_Functions.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/mcuxClTrng/src/mcuxClTrng_RNG4.c", + "${ELS_PKC_CL_PATH}/src/comps/mcuxClSession/src/mcuxClSession.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..0f4cdfe5e6ffd2 --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/bt_pal/EM_platform.h @@ -0,0 +1,23 @@ + +/** + * \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..7a0ab1b639ee06 --- /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; + } +} \ No newline at end of file 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..88a95e8c4158bf --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/mbedtls/ksdk_mbedtls_software.c @@ -0,0 +1,206 @@ +/* + * 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_common.h" +#include "fsl_adapter_rng.h" +#include "ksdk_mbedtls.h" + +/******************************************************************************/ +/*************************** FreeRTOS ********************************************/ +/******************************************************************************/ +#if defined(USE_RTOS) && defined(SDK_OS_FREE_RTOS) && defined(MBEDTLS_FREESCALE_FREERTOS_CALLOC_ALT) +#include +#include "FreeRTOS.h" +#include "task.h" + +/*---------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..c6a5b1c4ec794b --- /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 \ No newline at end of file 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..2e6a43af5f4383 --- /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 \ No newline at end of file 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..e11dc6166673cb --- /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 \ No newline at end of file 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..5bb3edbc8e7016 --- /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 \ No newline at end of file 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..d045ab6b554252 --- /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); +} \ No newline at end of file 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..d434919d7e4930 --- /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_ */ \ No newline at end of file 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..1005f7e8d98e0c --- /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 \ No newline at end of file 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..04218b12b53615 --- /dev/null +++ b/third_party/nxp/rt_sdk/sdk_hook/zephyr/sys/slist.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 "sys/slist.h" + + +#if defined(__cplusplus) +} +#endif \ No newline at end of file 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..80a03b056c16f7 --- /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 \ No newline at end of file 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..f6337b87ad473e --- /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/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" ] + } +}