diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index 9467074fdbcfd4..dc56ae93a28e1d 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -1630,3 +1630,4 @@ Zigbee zigbeealliance zigbeethread zsdk +TBR diff --git a/.github/workflows/examples-nxp.yaml b/.github/workflows/examples-nxp.yaml index fc929eff2601c0..e8e335997db24d 100644 --- a/.github/workflows/examples-nxp.yaml +++ b/.github/workflows/examples-nxp.yaml @@ -242,7 +242,6 @@ jobs: ./scripts/build/build_examples.py \ --target nxp-rw61x-freertos-all-clusters-wifi \ --target nxp-rw61x-freertos-all-clusters-thread \ - --target nxp-rw61x-freertos-all-clusters-thread-wifi \ --target nxp-rw61x-freertos-all-clusters-wifi-ota-cmake \ build \ --copy-artifacts-to out/artifacts \ @@ -265,7 +264,6 @@ jobs: ./scripts/build/build_examples.py \ --target nxp-rw61x-freertos-laundry-washer-wifi \ --target nxp-rw61x-freertos-laundry-washer-thread \ - --target nxp-rw61x-freertos-laundry-washer-thread-wifi \ build \ --copy-artifacts-to out/artifacts \ " diff --git a/docs/guides/nxp/nxp_otbr_guide.md b/docs/guides/nxp/nxp_otbr_guide.md new file mode 100644 index 00000000000000..fd993f02e5376a --- /dev/null +++ b/docs/guides/nxp/nxp_otbr_guide.md @@ -0,0 +1,107 @@ +# Thread Border Router usage + +This document describes the use of the Thread Border router and secondary +network interface for a Matter application + +
+ +- [Thread Border Router usage](#thread-border-router-usage) + - [Thread Border Router overview](#thread-border-router-overview) + - [Using the Thread Border Router management cluster](#using-the-thread-border-router-management-cluster) + - [Using the Secondary Network commissioning interface](#using-the-secondary-network-commissioning-interface) + - [Using the Thread credential sharing mechanism](#using-the-thread-credential-sharing-mechanism) + +
+ + + +## Thread Border Router overview + +This section contains an overview of the Border Router architecture and +describes the general use cases. + + + +## Using the Thread Border Router management cluster + +The Thread Border Router management cluster allows provisioning of the Thread +interface using a Matter commissioner. + +After the device has been provisioned over WIFI the set active dataset command +can be used to configure the Thread active dataset on the border router. Once +the dataset is set successfully the Thread network interface will be enabled and +the device will create a new PAN or join an existing one if already present. +Note that this command cannot be used on a device that already has an active +dataset configured. In this situation the set pending dataset command must be +used instead. + +Before using the set active dataset command a fail-safe timer must be armed +(recommend using a timeout of 120 seconds): + +``` +ubuntu@ubuntu:~$ ./chip-tool generalcommissioning arm-fail-safe timeout-seconds 1 node-id 0 +``` + +Then an active dataset in HEX TLV format (the same type used to provision a +Matter over Thread device using the `ble-thread` command) can be used to +provision the Border Router. What the active dataset should be is outside the +scope of this README but as an example one can be obtained from the OpenThread +cli on an already provisioned device using the `dataset active -x` command. + +Note that the Thread Border Router management cluster has been set to endpoint 2 +in the zap file. + +``` +ubuntu@ubuntu:~$ ./chip-tool threadborderroutermanagement set-active-dataset-request hex: node id 2 +``` + +If the active dataset command is successful, a commissioning complete command +must be send to disarm the fail-safe timer and commit the configuration to +non-volatile storage. + +``` +ubuntu@ubuntu:~$ ./chip-tool-19-jul generalcommissioning commissioning-complete node-id 0 +``` + +Note that this command cannot be used on a device that already has an active +dataset configured. In this situation the set pending dataset command must be +used instead. + +``` +ubuntu@ubuntu:~$ ./chip-tool threadborderroutermanagement set-pending-dataset-request hex: node id 2 +``` + +To read the active dataset of an already provisioned device, for example to make +a joining Border Router use the same Thread network as an already configured +one, the get active dataset command can be used: + +``` +ubuntu@ubuntu:~$ ./chip-tool-19-jul threadborderroutermanagement get-active-dataset-request node-id 2 +``` + + + +## Using the Secondary Network commissioning interface + +To use the secondary network commissioning interface over Thread the device must +not be provisioned over WIFI. The regular `ble-thread` pairing is used as for +any other Matter over Thread device. The chip-tool will read all the endpoints +of the device and discover Thread network commissioning cluster on endpoint 3 +and use that to provision the device. As for any other Matter over Thread device +a Thread Border Router is required in this case. + +``` +ubuntu@ubuntu:~$ ./chip-tool pairing ble-thread node-id hex: 20202021 3840 +``` + + + +## Using the Thread credential sharing mechanism + +The details about using the credential sharing mechanism are in the ot-nxp repo +border router application +[readme](https://github.com/NXP/ot-nxp/blob/v1.4.0-pvw1/examples/br/README-OTBR.md). +See `Ephemeral Key functionality` section. + +Note that all OpenThread commands executed from then Matter CLI must have +`otcli` added before the command. diff --git a/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn b/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn index b0e1c1c47a98ea..bdc878cc0f5250 100644 --- a/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn +++ b/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn @@ -35,15 +35,10 @@ assert(target_os == "freertos") assert(nxp_platform == "rt/rw61x") declare_args() { - # Allows to start the tcp download test app - tcp_download = false - - # Allows to start the wifi connect test app - wifi_connect = false - - # The 2 params below are used only if tcp_download or wifi_connect are true, otherwise they're unused. - wifi_ssid = "" - wifi_password = "" + # Allows to connect to a predefine Wi-Fi network at boot + wifi_auto_connect_at_boot = false + wifi_auto_connect_at_boot_ssid = "" + wifi_auto_connect_at_boot_password = "" # Setup discriminator as argument setup_discriminator = 3840 @@ -53,10 +48,6 @@ example_platform_dir = "${nxp_sdk_matter_support_root}/examples/platform/${nxp_platform}" common_example_dir = "${chip_root}/examples/platform/nxp/common" -if (tcp_download == true && wifi_connect == true) { - assert("Cannot enable tcp_download and wifi_connect at the same time!") -} - app_common_folder = "all-clusters-app/all-clusters-common" # Create here the SDK instance. @@ -213,42 +204,21 @@ rt_executable("all_cluster_app") { ] } - if (wifi_connect) { + if (wifi_auto_connect_at_boot) { + assert(wifi_auto_connect_at_boot_ssid != "" && + wifi_auto_connect_at_boot_password != "", + "WiFi SSID and password must be specified at build time!") + defines += [ - "WIFI_CONNECT_TASK=1", - "WIFI_CONNECT=1", + "CONFIG_CHIP_APP_WIFI_CONNECT_AT_BOOT=1", + "CONFIG_CHIP_APP_WIFI_SSID=\"${wifi_auto_connect_at_boot_ssid}\"", + "CONFIG_CHIP_APP_WIFI_PASSWORD=\"${wifi_auto_connect_at_boot_password}\"", ] - if (!chip_enable_matter_cli) { - assert(wifi_ssid != "" && wifi_password != "", - "WiFi SSID and password must be specified at build time!") - } - - if (wifi_ssid != "") { - defines += [ "WIFI_SSID=\"${wifi_ssid}\"" ] - } - - if (wifi_password != "") { - defines += [ "WIFI_PASSWORD=\"${wifi_password}\"" ] - } - include_dirs += [ "${common_example_dir}/wifi_connect/include" ] sources += [ "${common_example_dir}/wifi_connect/source/WifiConnect.cpp" ] } - if (tcp_download) { - defines += [ "CONFIG_CHIP_TCP_DOWNLOAD=1" ] - defines += [ - "WIFI_CONNECT=1", - "WIFI_SSID=\"${wifi_ssid}\"", - "WIFI_PASSWORD=\"${wifi_password}\"", - ] - - include_dirs += [ "${common_example_dir}/tcp_download_test/include" ] - sources += - [ "${common_example_dir}/tcp_download_test/source/TcpDownload.cpp" ] - } - # In case a dedicated assert function needs to be supported the flag sdk_fsl_assert_support should be set to false # The would add to the build a dedicated application assert implementation. if (!sdk_fsl_assert_support) { diff --git a/examples/all-clusters-app/nxp/rt/rw61x/README.md b/examples/all-clusters-app/nxp/rt/rw61x/README.md index 9356e4b8fe3617..61d3f008697a58 100644 --- a/examples/all-clusters-app/nxp/rt/rw61x/README.md +++ b/examples/all-clusters-app/nxp/rt/rw61x/README.md @@ -16,6 +16,7 @@ commissioning and different cluster control. - [Testing the example](#testing-the-example) - [Matter Shell](#testing-the-all-clusters-application-with-matter-cli-enabled) - [OTA Software Update](#ota-software-update) +- [Thread Border Router overview](#thread-border-router-overview)
@@ -124,8 +125,13 @@ user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rw61x #### Building with Matter over Wifi + OpenThread Border Router configuration on RW612 -This configuration requires enabling the Matter CLI in order to control the -Thread network on the Border Router. +This configuration supports the Thread Border Router management cluster to +provision the Thread credentials. Enabling the Matter CLI in order to control +the Thread network on the Border Router is optional but recommended for other +features like the Thread credential sharing. + +Note that the Thread Border Router management cluster is only supported on the +thermostat application for now. - Build Matter with Border Router configuration with BLE commissioning (ble-wifi) : @@ -142,6 +148,13 @@ out/debug/chip-rw61x-all-cluster-example. Optional GN options that can be added when building an application: +- To enable the + [secondary network commissioning interface](../../../../../docs/guides/nxp/nxp_otbr_guide.md#using-the-secondary-network-commissioning-interface), + the arguments `chip_enable_secondary_nwk_if=true` and + `chip_device_config_thread_network_endpoint_id=2` must be added to the _gn + gen_ command. Note that this is only supported when building the Matter over + Wifi + OpenThread Border Router configuration. Note that is only supported + on the on the thermostat application for now. - To enable the [matter CLI](README.md#testing-the-all-clusters-application-with-matter-cli-enabled), the argument `chip_enable_matter_cli=true` must be added to the _gn gen_ @@ -265,9 +278,11 @@ The "ble-thread" pairing method can be used in order to commission the device. #### Matter over wifi with openthread border router configuration : -In order to create or join a Thread network on the Matter Border Router, the -`otcli` commands from the matter CLI can be used. For more information about -using the matter shell, follow instructions from +In order to create or join a Thread network on the Matter Border Router, the TBR +management cluster or the `otcli` commands from the matter CLI can be used. For +more information about using the TBR management cluster follow instructions from +['Using the TBR management cluster'](../../../../../docs/guides/nxp/nxp_otbr_guide.md#using-the-thread-border-router-management-cluster). +For more information about using the matter shell, follow instructions from ['Testing the all-clusters application with Matter CLI'](#testing-the-all-clusters-application-with-matter-cli-enabled). In this configuration, the device can be commissioned over Wi-Fi with the @@ -393,3 +408,13 @@ Over-The-Air software updates are supported with the RW61x all-clusters example. The process to follow in order to perform a software update is described in the dedicated guide ['Matter Over-The-Air Software Update with NXP RW61x example applications'](../../../../../docs/guides/nxp/nxp_rw61x_ota_software_update.md). + + + +## Thread Border Router overview + +To enable Thread Border Router support see the [build](README.md#building) +section. + +The complete Border Router guide is located +[here](../../../../../docs/guides/nxp/nxp_otbr_guide.md). diff --git a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter index 9b30603b156ee2..a261fb4070e0ed 100644 --- a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter +++ b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter @@ -3464,6 +3464,7 @@ cluster DoorLock = 257 { nullable fabric_idx creatorFabricIndex = 2; nullable fabric_idx lastModifiedFabricIndex = 3; nullable int16u nextCredentialIndex = 4; + optional nullable octet_string credentialData = 5; } request struct ClearCredentialRequest { diff --git a/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.matter b/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.matter index ee845c7c6cffda..ca3d431c3e81e8 100644 --- a/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.matter +++ b/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.matter @@ -2613,9 +2613,9 @@ endpoint 1 { } server cluster TemperatureMeasurement { - persist attribute measuredValue default = 0x800; - persist attribute minMeasuredValue default = 0x800; - persist attribute maxMeasuredValue default = 0x800; + persist attribute measuredValue default = 0; + persist attribute minMeasuredValue default = -5000; + persist attribute maxMeasuredValue default = 7500; persist attribute tolerance default = 0; callback attribute generatedCommandList; callback attribute acceptedCommandList; diff --git a/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.zap b/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.zap index 7e58d312609fc7..c5ad356e6d292a 100644 --- a/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.zap +++ b/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.zap @@ -3107,7 +3107,7 @@ "storageOption": "NVM", "singleton": 0, "bounded": 0, - "defaultValue": "0x800", + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3123,7 +3123,7 @@ "storageOption": "NVM", "singleton": 0, "bounded": 0, - "defaultValue": "0x800", + "defaultValue": "-5000", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3139,7 +3139,7 @@ "storageOption": "NVM", "singleton": 0, "bounded": 0, - "defaultValue": "0x800", + "defaultValue": "7500", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter b/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter index fc6ef7614fc562..36a7822ede2aa3 100644 --- a/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter +++ b/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter @@ -2301,6 +2301,7 @@ cluster DoorLock = 257 { nullable fabric_idx creatorFabricIndex = 2; nullable fabric_idx lastModifiedFabricIndex = 3; nullable int16u nextCredentialIndex = 4; + optional nullable octet_string credentialData = 5; } request struct ClearCredentialRequest { diff --git a/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn b/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn index 580a3ad556702b..cb0b7ba0a96439 100644 --- a/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn +++ b/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn @@ -35,15 +35,10 @@ assert(target_os == "freertos") assert(nxp_platform == "rt/rw61x") declare_args() { - # Allows to start the tcp download test app - tcp_download = false - - # Allows to start the wifi connect test app - wifi_connect = false - - # The 2 params below are used only if tcp_download or wifi_connect are true, otherwise they're unused. - wifi_ssid = "" - wifi_password = "" + # Allows to connect to a predefine Wi-Fi network at boot + wifi_auto_connect_at_boot = false + wifi_auto_connect_at_boot_ssid = "" + wifi_auto_connect_at_boot_password = "" # Setup discriminator as argument setup_discriminator = 3840 @@ -53,10 +48,6 @@ example_platform_dir = "${nxp_sdk_matter_support_root}/examples/platform/${nxp_platform}" common_example_dir = "${chip_root}/examples/platform/nxp/common" -if (tcp_download == true && wifi_connect == true) { - assert("Cannot enable tcp_download and wifi_connect at the same time!") -} - # Use NXP custom zap files for laundry-washer device-type app_common_folder = "laundry-washer-app/nxp/zap" @@ -218,42 +209,21 @@ rt_executable("laundry-washer") { ] } - if (wifi_connect) { + if (wifi_auto_connect_at_boot) { + assert(wifi_auto_connect_at_boot_ssid != "" && + wifi_auto_connect_at_boot_password != "", + "WiFi SSID and password must be specified at build time!") + defines += [ - "WIFI_CONNECT_TASK=1", - "WIFI_CONNECT=1", + "CONFIG_CHIP_APP_WIFI_CONNECT_AT_BOOT=1", + "CONFIG_CHIP_APP_WIFI_SSID=\"${wifi_auto_connect_at_boot_ssid}\"", + "CONFIG_CHIP_APP_WIFI_PASSWORD=\"${wifi_auto_connect_at_boot_password}\"", ] - if (!chip_enable_matter_cli) { - assert(wifi_ssid != "" && wifi_password != "", - "WiFi SSID and password must be specified at build time!") - } - - if (wifi_ssid != "") { - defines += [ "WIFI_SSID=\"${wifi_ssid}\"" ] - } - - if (wifi_password != "") { - defines += [ "WIFI_PASSWORD=\"${wifi_password}\"" ] - } - include_dirs += [ "${common_example_dir}/wifi_connect/include" ] sources += [ "${common_example_dir}/wifi_connect/source/WifiConnect.cpp" ] } - if (tcp_download) { - defines += [ "CONFIG_CHIP_TCP_DOWNLOAD=1" ] - defines += [ - "WIFI_CONNECT=1", - "WIFI_SSID=\"${wifi_ssid}\"", - "WIFI_PASSWORD=\"${wifi_password}\"", - ] - - include_dirs += [ "${common_example_dir}/tcp_download_test/include" ] - sources += - [ "${common_example_dir}/tcp_download_test/source/TcpDownload.cpp" ] - } - # In case a dedicated assert function needs to be supported the flag sdk_fsl_assert_support should be set to false # The would add to the build a dedicated application assert implementation. if (!sdk_fsl_assert_support) { diff --git a/examples/lock-app/lock-common/lock-app.matter b/examples/lock-app/lock-common/lock-app.matter index 0b316c77592d7e..45e530bbff9449 100644 --- a/examples/lock-app/lock-common/lock-app.matter +++ b/examples/lock-app/lock-common/lock-app.matter @@ -2728,6 +2728,7 @@ cluster DoorLock = 257 { nullable fabric_idx creatorFabricIndex = 2; nullable fabric_idx lastModifiedFabricIndex = 3; nullable int16u nextCredentialIndex = 4; + optional nullable octet_string credentialData = 5; } request struct ClearCredentialRequest { diff --git a/examples/lock-app/nxp/zap/lock-app.matter b/examples/lock-app/nxp/zap/lock-app.matter index 7c39ef0fe254eb..91e023d6607a6c 100644 --- a/examples/lock-app/nxp/zap/lock-app.matter +++ b/examples/lock-app/nxp/zap/lock-app.matter @@ -2304,6 +2304,7 @@ cluster DoorLock = 257 { nullable fabric_idx creatorFabricIndex = 2; nullable fabric_idx lastModifiedFabricIndex = 3; nullable int16u nextCredentialIndex = 4; + optional nullable octet_string credentialData = 5; } request struct ClearCredentialRequest { diff --git a/examples/lock-app/qpg/zap/lock.matter b/examples/lock-app/qpg/zap/lock.matter index 303b079b910cac..1d367e9eaeb42b 100644 --- a/examples/lock-app/qpg/zap/lock.matter +++ b/examples/lock-app/qpg/zap/lock.matter @@ -2401,6 +2401,7 @@ cluster DoorLock = 257 { nullable fabric_idx creatorFabricIndex = 2; nullable fabric_idx lastModifiedFabricIndex = 3; nullable int16u nextCredentialIndex = 4; + optional nullable octet_string credentialData = 5; } request struct ClearCredentialRequest { diff --git a/examples/placeholder/linux/apps/app1/config.matter b/examples/placeholder/linux/apps/app1/config.matter index de9603d2627962..6fcce30fe6b2a0 100644 --- a/examples/placeholder/linux/apps/app1/config.matter +++ b/examples/placeholder/linux/apps/app1/config.matter @@ -4098,6 +4098,7 @@ cluster DoorLock = 257 { nullable fabric_idx creatorFabricIndex = 2; nullable fabric_idx lastModifiedFabricIndex = 3; nullable int16u nextCredentialIndex = 4; + optional nullable octet_string credentialData = 5; } request struct ClearCredentialRequest { @@ -4749,6 +4750,7 @@ cluster DoorLock = 257 { nullable fabric_idx creatorFabricIndex = 2; nullable fabric_idx lastModifiedFabricIndex = 3; nullable int16u nextCredentialIndex = 4; + optional nullable octet_string credentialData = 5; } request struct ClearCredentialRequest { diff --git a/examples/placeholder/linux/apps/app2/config.matter b/examples/placeholder/linux/apps/app2/config.matter index 2b6528d55ad018..b2be5a5715779c 100644 --- a/examples/placeholder/linux/apps/app2/config.matter +++ b/examples/placeholder/linux/apps/app2/config.matter @@ -4055,6 +4055,7 @@ cluster DoorLock = 257 { nullable fabric_idx creatorFabricIndex = 2; nullable fabric_idx lastModifiedFabricIndex = 3; nullable int16u nextCredentialIndex = 4; + optional nullable octet_string credentialData = 5; } request struct ClearCredentialRequest { @@ -4706,6 +4707,7 @@ cluster DoorLock = 257 { nullable fabric_idx creatorFabricIndex = 2; nullable fabric_idx lastModifiedFabricIndex = 3; nullable int16u nextCredentialIndex = 4; + optional nullable octet_string credentialData = 5; } request struct ClearCredentialRequest { diff --git a/examples/platform/nxp/common/app_task/include/AppTaskBase.h b/examples/platform/nxp/common/app_task/include/AppTaskBase.h index 38770fa0e5ec26..ab29af27c29561 100644 --- a/examples/platform/nxp/common/app_task/include/AppTaskBase.h +++ b/examples/platform/nxp/common/app_task/include/AppTaskBase.h @@ -169,6 +169,17 @@ class AppTaskBase */ static void InitServer(intptr_t arg); +#if CHIP_DEVICE_CONFIG_ENABLE_TBR + /** + * \brief Initialize the Thread Border Router management cluster. + * + * Called when the border router function is up and running. This cluster stays disabled + * when the application is used as a Matter over Thread device. + * + */ + void EnableTbrManagementCluster(); +#endif + /** * Commissioning handlers * Generic implementation is provided within this class diff --git a/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp b/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp index c62be98d22c9b1..2646ffca4ef26d 100644 --- a/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp +++ b/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp @@ -30,6 +30,7 @@ #include #include + #include #include "lib/core/ErrorStr.h" @@ -56,8 +57,8 @@ #include #endif -#if CONFIG_CHIP_TCP_DOWNLOAD -#include "TcpDownload.h" +#if CONFIG_CHIP_APP_WIFI_CONNECT_AT_BOOT +#include "WifiConnect.h" #endif #if CONFIG_OPERATIONAL_KEYSTORE @@ -97,6 +98,11 @@ #include #endif +#if CHIP_DEVICE_CONFIG_ENABLE_TBR +#include "platform/OpenThread/GenericThreadBorderRouterDelegate.h" +#include +#endif + #ifndef CONFIG_THREAD_DEVICE_TYPE #define CONFIG_THREAD_DEVICE_TYPE kThreadDeviceType_Router #endif @@ -120,12 +126,23 @@ app::Clusters::NetworkCommissioning::Instance sNetworkCommissioningInstance(0, chip::NXP::App::GetAppTask().GetEthernetDriverInstance()); #endif +#if CHIP_DEVICE_CONFIG_ENABLE_TBR +static constexpr EndpointId kThreadBRMgmtEndpoint = 2; +static CharSpan sBrName("NXP-BR", strlen("NXP-BR")); +#endif + #if CHIP_CONFIG_ENABLE_ICD_SERVER || (CONFIG_CHIP_TEST_EVENT && CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR) static uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; #endif +#ifdef SMOKE_CO_ALARM +static uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, + 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, + 0xcc, 0xdd, 0xee, 0xff }; +#endif + #if CONFIG_NET_L2_OPENTHREAD void LockOpenThreadTask(void) { @@ -197,6 +214,14 @@ void chip::NXP::App::AppTaskBase::InitServer(intptr_t arg) #if CONFIG_CHIP_OTA_PROVIDER InitOTAServer(); #endif + +#if CONFIG_CHIP_APP_WIFI_CONNECT_AT_BOOT + VerifyOrDie(WifiConnectAtboot(chip::NXP::App::GetAppTask().GetWifiDriverInstance()) == CHIP_NO_ERROR); +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_TBR + GetAppTask().EnableTbrManagementCluster(); +#endif } CHIP_ERROR chip::NXP::App::AppTaskBase::Init() @@ -326,10 +351,6 @@ CHIP_ERROR chip::NXP::App::AppTaskBase::Init() } #endif -#if CONFIG_CHIP_TCP_DOWNLOAD - EnableTcpDownloadComponent(); -#endif - exit: return err; } @@ -443,3 +464,19 @@ void chip::NXP::App::AppTaskBase::PrintCurrentVersion() ChipLogProgress(DeviceLayer, "Current Software Version: %s, %d", currentSoftwareVer, static_cast(currentVersion)); } + +#if CHIP_DEVICE_CONFIG_ENABLE_TBR +void chip::NXP::App::AppTaskBase::EnableTbrManagementCluster() +{ + auto * persistentStorage = &Server::GetInstance().GetPersistentStorage(); + + static ThreadBorderRouterManagement::GenericOpenThreadBorderRouterDelegate sThreadBRDelegate(persistentStorage); + static ThreadBorderRouterManagement::ServerInstance sThreadBRMgmtInstance(kThreadBRMgmtEndpoint, &sThreadBRDelegate, + Server::GetInstance().GetFailSafeContext()); + + // Initialize TBR name + sThreadBRDelegate.SetThreadBorderRouterName(sBrName); + // Initialize TBR cluster + sThreadBRMgmtInstance.Init(); +} +#endif diff --git a/examples/platform/nxp/common/device_callbacks/include/CommonDeviceCallbacks.h b/examples/platform/nxp/common/device_callbacks/include/CommonDeviceCallbacks.h index 4cbd5028ce58b3..fc8b2ed1774b93 100644 --- a/examples/platform/nxp/common/device_callbacks/include/CommonDeviceCallbacks.h +++ b/examples/platform/nxp/common/device_callbacks/include/CommonDeviceCallbacks.h @@ -40,7 +40,7 @@ class CommonDeviceCallbacks : public chip::DeviceManager::CHIPDeviceManagerCallb virtual void OnInternetConnectivityChange(const chip::DeviceLayer::ChipDeviceEvent * event); virtual void OnSessionEstablished(const chip::DeviceLayer::ChipDeviceEvent * event); virtual void OnInterfaceIpAddressChanged(const chip::DeviceLayer::ChipDeviceEvent * event); -#if CHIP_ENABLE_OPENTHREAD && CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED +#if CHIP_ENABLE_OPENTHREAD virtual void OnComissioningComplete(const chip::DeviceLayer::ChipDeviceEvent * event); #endif }; diff --git a/examples/platform/nxp/common/device_callbacks/source/CommonDeviceCallbacks.cpp b/examples/platform/nxp/common/device_callbacks/source/CommonDeviceCallbacks.cpp index 2e40fdefb2e119..1bab4b09f58eda 100644 --- a/examples/platform/nxp/common/device_callbacks/source/CommonDeviceCallbacks.cpp +++ b/examples/platform/nxp/common/device_callbacks/source/CommonDeviceCallbacks.cpp @@ -23,7 +23,9 @@ * **/ #include "CommonDeviceCallbacks.h" +#include "AppTaskBase.h" +#include #include #include #include @@ -73,7 +75,7 @@ void chip::NXP::App::CommonDeviceCallbacks::DeviceEventCallback(const ChipDevice OnInterfaceIpAddressChanged(event); break; -#if CHIP_ENABLE_OPENTHREAD && CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED +#if CHIP_ENABLE_OPENTHREAD case DeviceEventType::kCommissioningComplete: CommonDeviceCallbacks::OnComissioningComplete(event); break; @@ -153,9 +155,25 @@ void chip::NXP::App::CommonDeviceCallbacks::OnSessionEstablished(chip::DeviceLay /* Empty */ } -#if CHIP_ENABLE_OPENTHREAD && CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED +#if CHIP_ENABLE_OPENTHREAD void chip::NXP::App::CommonDeviceCallbacks::OnComissioningComplete(const chip::DeviceLayer::ChipDeviceEvent * event) { +#ifndef _NO_GENERIC_THREAD_NETWORK_COMMISSIONING_DRIVER_ +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + if (ConnectivityMgr().IsWiFiStationConnected()) + { + // Disable thr nwk commissioining cluster + app::Clusters::NetworkCommissioning::Attributes::InterfaceEnabled::Set(CHIP_DEVICE_CONFIG_THREAD_NETWORK_ENDPOINT_ID, 0); + } + else if (ConnectivityMgr().IsThreadProvisioned()) + { + // Set WIFI cluster interface attribute to disable. + app::Clusters::NetworkCommissioning::Attributes::InterfaceEnabled::Set(0, 0); + } +#endif // CHIP_DEVICE_CONFIG_ENABLE_WPA +#endif // _NO_GENERIC_THREAD_NETWORK_COMMISSIONING_DRIVER_ + +#if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED /* * 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. @@ -171,5 +189,6 @@ void chip::NXP::App::CommonDeviceCallbacks::OnComissioningComplete(const chip::D PlatformMgrImpl().StopBLEConnectivity(); ThreadStackMgrImpl().UnlockThreadStack(); } +#endif } #endif diff --git a/examples/platform/nxp/common/wifi_connect/include/WifiConnect.h b/examples/platform/nxp/common/wifi_connect/include/WifiConnect.h new file mode 100644 index 00000000000000..ea0b5cc9f4d8c1 --- /dev/null +++ b/examples/platform/nxp/common/wifi_connect/include/WifiConnect.h @@ -0,0 +1,42 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file WifiConnect.h + * + * Wi-Fi Connect Module allowing to join a pre-defined Wi-Fi network + * + **/ + +#pragma once + +#include + +namespace chip { +namespace NXP { +namespace App { + +/* + * Function allowing to join a Wi-Fi network based on Wi-Fi build credentials + * Must be called after completing Wi-Fi driver initialization + */ +CHIP_ERROR WifiConnectAtboot(chip::DeviceLayer::NetworkCommissioning::WiFiDriver * wifiDriver); + +} // namespace App +} // namespace NXP +} // namespace chip diff --git a/examples/platform/nxp/common/wifi_connect/source/WifiConnect.cpp b/examples/platform/nxp/common/wifi_connect/source/WifiConnect.cpp new file mode 100644 index 00000000000000..438bee5040795f --- /dev/null +++ b/examples/platform/nxp/common/wifi_connect/source/WifiConnect.cpp @@ -0,0 +1,53 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "WifiConnect.h" +#include +#include +#include + +namespace chip { +namespace NXP { +namespace App { + +CHIP_ERROR WifiConnectAtboot(chip::DeviceLayer::NetworkCommissioning::WiFiDriver * wifiDriver) +{ + VerifyOrReturnError(wifiDriver != nullptr, CHIP_ERROR_NOT_IMPLEMENTED); + + /* In case WiFi connect at boot is enabled try to set SSID to the predefined value */ + ByteSpan ssidSpan = ByteSpan(Uint8::from_const_char(CONFIG_CHIP_APP_WIFI_SSID), strlen(CONFIG_CHIP_APP_WIFI_SSID)); + ByteSpan passwordSpan = ByteSpan(Uint8::from_const_char(CONFIG_CHIP_APP_WIFI_PASSWORD), strlen(CONFIG_CHIP_APP_WIFI_PASSWORD)); + VerifyOrReturnError(IsSpanUsable(ssidSpan) && IsSpanUsable(passwordSpan), CHIP_ERROR_INVALID_ARGUMENT); + + chip::DeviceLayer::NetworkCommissioning::NetworkIterator * networks = wifiDriver->GetNetworks(); + /* In case Wi-Fi driver has already Wi-Fi network information, skip the connect stage */ + if (networks == nullptr || networks->Count() == 0) + { + uint8_t networkIndex; + chip::MutableCharSpan debugText; + chip::DeviceLayer::NetworkCommissioning::Status status = + wifiDriver->AddOrUpdateNetwork(ssidSpan, passwordSpan, debugText, networkIndex); + VerifyOrReturnError(status == chip::DeviceLayer::NetworkCommissioning::Status::kSuccess, CHIP_ERROR_CONNECTION_ABORTED); + wifiDriver->ConnectNetwork(ssidSpan, nullptr); + } + return CHIP_NO_ERROR; +} + +} // namespace App +} // namespace NXP +} // namespace chip diff --git a/examples/platform/silabs/OTAConfig.h b/examples/platform/silabs/OTAConfig.h index c97202e401f266..07d61037a9b2ca 100644 --- a/examples/platform/silabs/OTAConfig.h +++ b/examples/platform/silabs/OTAConfig.h @@ -29,7 +29,7 @@ #include #endif -#if (SL_MATTER_GN_BUILD == 0) +#if (SL_MATTER_GN_BUILD == 0) && defined(SILABS_OTA_ENABLED) #include "sl_matter_ota_config.h" #endif diff --git a/examples/thermostat/nxp/rt/rw61x/BUILD.gn b/examples/thermostat/nxp/rt/rw61x/BUILD.gn index 30af1be0e99a38..f377845cd49f98 100644 --- a/examples/thermostat/nxp/rt/rw61x/BUILD.gn +++ b/examples/thermostat/nxp/rt/rw61x/BUILD.gn @@ -35,15 +35,10 @@ assert(target_os == "freertos") assert(nxp_platform == "rt/rw61x") declare_args() { - # Allows to start the tcp download test app - tcp_download = false - - # Allows to start the wifi connect test app - wifi_connect = false - - # The 2 params below are used only if tcp_download or wifi_connect are true, otherwise they're unused. - wifi_ssid = "" - wifi_password = "" + # Allows to connect to a predefine Wi-Fi network at boot + wifi_auto_connect_at_boot = false + wifi_auto_connect_at_boot_ssid = "" + wifi_auto_connect_at_boot_password = "" # Setup discriminator as argument setup_discriminator = 3840 @@ -55,10 +50,6 @@ example_platform_dir = "${nxp_sdk_matter_support_root}/examples/platform/${nxp_platform}" common_example_dir = "${chip_root}/examples/platform/nxp/common" -if (tcp_download == true && wifi_connect == true) { - assert("Cannot enable tcp_download and wifi_connect at the same time!") -} - # Use NXP custom zap files for thermostatdevice-types app_common_folder = "thermostat/nxp/zap" @@ -107,10 +98,17 @@ rt_sdk("sdk") { # Indicate the default path to OpenThreadConfig.h include_dirs += [ "${example_platform_dir}/app/project_include/openthread" ] - # For matter with BR feature, increase FreeRTOS heap size + # For matter with BR feature, increase FreeRTOS heap size and enable TBR cluster if (chip_enable_wifi && chip_enable_openthread) { - defines += [ "configTOTAL_HEAP_SIZE=(size_t)(170 * 1024)" ] + defines += [ + "configTOTAL_HEAP_SIZE=(size_t)(170 * 1024)", + "CHIP_DEVICE_CONFIG_ENABLE_TBR=1", + ] } + + defines += [ + "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", + ] } # Create the SDK driver instance. @@ -224,42 +222,21 @@ rt_executable("thermostat") { ] } - if (wifi_connect) { + if (wifi_auto_connect_at_boot) { + assert(wifi_auto_connect_at_boot_ssid != "" && + wifi_auto_connect_at_boot_password != "", + "WiFi SSID and password must be specified at build time!") + defines += [ - "WIFI_CONNECT_TASK=1", - "WIFI_CONNECT=1", + "CONFIG_CHIP_APP_WIFI_CONNECT_AT_BOOT=1", + "CONFIG_CHIP_APP_WIFI_SSID=\"${wifi_auto_connect_at_boot_ssid}\"", + "CONFIG_CHIP_APP_WIFI_PASSWORD=\"${wifi_auto_connect_at_boot_password}\"", ] - if (!chip_enable_matter_cli) { - assert(wifi_ssid != "" && wifi_password != "", - "WiFi SSID and password must be specified at build time!") - } - - if (wifi_ssid != "") { - defines += [ "WIFI_SSID=\"${wifi_ssid}\"" ] - } - - if (wifi_password != "") { - defines += [ "WIFI_PASSWORD=\"${wifi_password}\"" ] - } - include_dirs += [ "${common_example_dir}/wifi_connect/include" ] sources += [ "${common_example_dir}/wifi_connect/source/WifiConnect.cpp" ] } - if (tcp_download) { - defines += [ "CONFIG_CHIP_TCP_DOWNLOAD=1" ] - defines += [ - "WIFI_CONNECT=1", - "WIFI_SSID=\"${wifi_ssid}\"", - "WIFI_PASSWORD=\"${wifi_password}\"", - ] - - include_dirs += [ "${common_example_dir}/tcp_download_test/include" ] - sources += - [ "${common_example_dir}/tcp_download_test/source/TcpDownload.cpp" ] - } - # In case a dedicated assert function needs to be supported the flag sdk_fsl_assert_support should be set to false # The would add to the build a dedicated application assert implementation. if (!sdk_fsl_assert_support) { @@ -298,10 +275,6 @@ rt_executable("thermostat") { # Consequently, some sections will need to be shifted ldflags += [ "-Wl,--defsym=__m_mcuboot_size__=0x20000" ] } - - defines += [ - "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", - ] } output_dir = root_out_dir diff --git a/examples/thermostat/nxp/zap/BUILD.gn b/examples/thermostat/nxp/zap/BUILD.gn index c3a3df7bd6729e..f3c652493dd3fb 100644 --- a/examples/thermostat/nxp/zap/BUILD.gn +++ b/examples/thermostat/nxp/zap/BUILD.gn @@ -20,7 +20,10 @@ import("${chip_root}/src/app/chip_data_model.gni") import("${chip_root}/src/platform/device.gni") chip_data_model("zap") { - if (chip_enable_wifi) { + if (chip_enable_wifi && chip_enable_openthread) { + # zap config for matter-over-wifi with BR + zap_file = "thermostat_matter_br.zap" + } else if (chip_enable_wifi) { # zap config for matter-over-wifi zap_file = "thermostat_matter_wifi.zap" } else { diff --git a/examples/thermostat/nxp/zap/thermostat_matter_br.matter b/examples/thermostat/nxp/zap/thermostat_matter_br.matter new file mode 100644 index 00000000000000..bb72c0caceaf27 --- /dev/null +++ b/examples/thermostat/nxp/zap/thermostat_matter_br.matter @@ -0,0 +1,2766 @@ +// This IDL was generated automatically by ZAP. +// It is for view/code review purposes only. + +enum AreaTypeTag : enum8 { + kAisle = 0; + kAttic = 1; + kBackDoor = 2; + kBackYard = 3; + kBalcony = 4; + kBallroom = 5; + kBathroom = 6; + kBedroom = 7; + kBorder = 8; + kBoxroom = 9; + kBreakfastRoom = 10; + kCarport = 11; + kCellar = 12; + kCloakroom = 13; + kCloset = 14; + kConservatory = 15; + kCorridor = 16; + kCraftRoom = 17; + kCupboard = 18; + kDeck = 19; + kDen = 20; + kDining = 21; + kDrawingRoom = 22; + kDressingRoom = 23; + kDriveway = 24; + kElevator = 25; + kEnsuite = 26; + kEntrance = 27; + kEntryway = 28; + kFamilyRoom = 29; + kFoyer = 30; + kFrontDoor = 31; + kFrontYard = 32; + kGameRoom = 33; + kGarage = 34; + kGarageDoor = 35; + kGarden = 36; + kGardenDoor = 37; + kGuestBathroom = 38; + kGuestBedroom = 39; + kGuestRestroom = 40; + kGuestRoom = 41; + kGym = 42; + kHallway = 43; + kHearthRoom = 44; + kKidsRoom = 45; + kKidsBedroom = 46; + kKitchen = 47; + kLarder = 48; + kLaundryRoom = 49; + kLawn = 50; + kLibrary = 51; + kLivingRoom = 52; + kLounge = 53; + kMediaTVRoom = 54; + kMudRoom = 55; + kMusicRoom = 56; + kNursery = 57; + kOffice = 58; + kOutdoorKitchen = 59; + kOutside = 60; + kPantry = 61; + kParkingLot = 62; + kParlor = 63; + kPatio = 64; + kPlayRoom = 65; + kPoolRoom = 66; + kPorch = 67; + kPrimaryBathroom = 68; + kPrimaryBedroom = 69; + kRamp = 70; + kReceptionRoom = 71; + kRecreationRoom = 72; + kRestroom = 73; + kRoof = 74; + kSauna = 75; + kScullery = 76; + kSewingRoom = 77; + kShed = 78; + kSideDoor = 79; + kSideYard = 80; + kSittingRoom = 81; + kSnug = 82; + kSpa = 83; + kStaircase = 84; + kSteamRoom = 85; + kStorageRoom = 86; + kStudio = 87; + kStudy = 88; + kSunRoom = 89; + kSwimmingPool = 90; + kTerrace = 91; + kUtilityRoom = 92; + kWard = 93; + kWorkshop = 94; +} + +enum AtomicRequestTypeEnum : enum8 { + kBeginWrite = 0; + kCommitWrite = 1; + kRollbackWrite = 2; +} + +enum FloorSurfaceTag : enum8 { + kCarpet = 0; + kCeramic = 1; + kConcrete = 2; + kCork = 3; + kDeepCarpet = 4; + kDirt = 5; + kEngineeredWood = 6; + kGlass = 7; + kGrass = 8; + kHardwood = 9; + kLaminate = 10; + kLinoleum = 11; + kMat = 12; + kMetal = 13; + kPlastic = 14; + kPolishedConcrete = 15; + kRubber = 16; + kRug = 17; + kSand = 18; + kStone = 19; + kTatami = 20; + kTerrazzo = 21; + kTile = 22; + kVinyl = 23; +} + +enum LandmarkTag : enum8 { + kAirConditioner = 0; + kAirPurifier = 1; + kBackDoor = 2; + kBarStool = 3; + kBathMat = 4; + kBathtub = 5; + kBed = 6; + kBookshelf = 7; + kChair = 8; + kChristmasTree = 9; + kCoatRack = 10; + kCoffeeTable = 11; + kCookingRange = 12; + kCouch = 13; + kCountertop = 14; + kCradle = 15; + kCrib = 16; + kDesk = 17; + kDiningTable = 18; + kDishwasher = 19; + kDoor = 20; + kDresser = 21; + kLaundryDryer = 22; + kFan = 23; + kFireplace = 24; + kFreezer = 25; + kFrontDoor = 26; + kHighChair = 27; + kKitchenIsland = 28; + kLamp = 29; + kLitterBox = 30; + kMirror = 31; + kNightstand = 32; + kOven = 33; + kPetBed = 34; + kPetBowl = 35; + kPetCrate = 36; + kRefrigerator = 37; + kScratchingPost = 38; + kShoeRack = 39; + kShower = 40; + kSideDoor = 41; + kSink = 42; + kSofa = 43; + kStove = 44; + kTable = 45; + kToilet = 46; + kTrashCan = 47; + kLaundryWasher = 48; + kWindow = 49; + kWineCooler = 50; +} + +enum PositionTag : enum8 { + kLeft = 0; + kRight = 1; + kTop = 2; + kBottom = 3; + kMiddle = 4; + kRow = 5; + kColumn = 6; +} + +enum RelativePositionTag : enum8 { + kUnder = 0; + kNextTo = 1; + kAround = 2; + kOn = 3; + kAbove = 4; + kFrontOf = 5; + kBehind = 6; +} + +enum TestGlobalEnum : enum8 { + kSomeValue = 0; + kSomeOtherValue = 1; + kFinalValue = 2; +} + +bitmap TestGlobalBitmap : bitmap32 { + kFirstBit = 0x1; + kSecondBit = 0x2; +} + +struct TestGlobalStruct { + char_string<128> name = 0; + nullable TestGlobalBitmap myBitmap = 1; + optional nullable TestGlobalEnum myEnum = 2; +} + +struct LocationDescriptorStruct { + char_string<128> locationName = 0; + nullable int16s floorNumber = 1; + nullable AreaTypeTag areaType = 2; +} + +struct AtomicAttributeStatusStruct { + attrib_id attributeID = 0; + status statusCode = 1; +} + +/** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ +cluster Identify = 3 { + revision 4; + + 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). */ +cluster Identify = 3 { + revision 4; + + 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 group configuration and manipulation. */ +cluster Groups = 4 { + revision 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<16> groupName = 1; + } + + response struct AddGroupResponse = 0 { + enum8 status = 0; + group_id groupID = 1; + } + + request struct ViewGroupRequest { + group_id groupID = 0; + } + + response struct ViewGroupResponse = 1 { + enum8 status = 0; + group_id groupID = 1; + char_string<16> groupName = 2; + } + + request struct GetGroupMembershipRequest { + group_id groupList[] = 0; + } + + response struct GetGroupMembershipResponse = 2 { + nullable int8u capacity = 0; + group_id groupList[] = 1; + } + + request struct RemoveGroupRequest { + group_id groupID = 0; + } + + response struct RemoveGroupResponse = 3 { + enum8 status = 0; + group_id groupID = 1; + } + + request struct AddGroupIfIdentifyingRequest { + group_id groupID = 0; + char_string<16> groupName = 1; + } + + /** Command description for AddGroup */ + fabric command access(invoke: manage) AddGroup(AddGroupRequest): AddGroupResponse = 0; + /** Command description for ViewGroup */ + fabric command ViewGroup(ViewGroupRequest): ViewGroupResponse = 1; + /** Command description for GetGroupMembership */ + fabric command GetGroupMembership(GetGroupMembershipRequest): GetGroupMembershipResponse = 2; + /** Command description for RemoveGroup */ + fabric command access(invoke: manage) RemoveGroup(RemoveGroupRequest): RemoveGroupResponse = 3; + /** Command description for RemoveAllGroups */ + fabric command access(invoke: manage) RemoveAllGroups(): DefaultSuccess = 4; + /** Command description for AddGroupIfIdentifying */ + fabric command access(invoke: manage) AddGroupIfIdentifying(AddGroupIfIdentifyingRequest): DefaultSuccess = 5; +} + +/** The Descriptor Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for describing a node, its endpoints and clusters. */ +cluster Descriptor = 29 { + revision 2; + + bitmap Feature : bitmap32 { + kTagList = 0x1; + } + + struct DeviceTypeStruct { + devtype_id deviceType = 0; + int16u revision = 1; + } + + struct SemanticTagStruct { + nullable vendor_id mfgCode = 0; + enum8 namespaceID = 1; + enum8 tag = 2; + optional nullable char_string label = 3; + } + + readonly attribute DeviceTypeStruct deviceTypeList[] = 0; + readonly attribute cluster_id serverList[] = 1; + readonly attribute cluster_id clientList[] = 2; + readonly attribute endpoint_no partsList[] = 3; + readonly attribute optional SemanticTagStruct tagList[] = 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; +} + +/** The Binding Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for supporting the binding table. */ +cluster Binding = 30 { + revision 1; // NOTE: Default/not specifically set + + 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 access(write: manage) 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. */ +cluster AccessControl = 31 { + revision 2; + + enum AccessControlEntryAuthModeEnum : enum8 { + kPASE = 1; + kCASE = 2; + kGroup = 3; + } + + enum AccessControlEntryPrivilegeEnum : enum8 { + kView = 1; + kProxyView = 2; + kOperate = 3; + kManage = 4; + kAdminister = 5; + } + + enum AccessRestrictionTypeEnum : enum8 { + kAttributeAccessForbidden = 0; + kAttributeWriteForbidden = 1; + kCommandForbidden = 2; + kEventForbidden = 3; + } + + enum ChangeTypeEnum : enum8 { + kChanged = 0; + kAdded = 1; + kRemoved = 2; + } + + bitmap Feature : bitmap32 { + kExtension = 0x1; + kManagedDevice = 0x2; + } + + struct AccessRestrictionStruct { + AccessRestrictionTypeEnum type = 0; + nullable int32u id = 1; + } + + struct CommissioningAccessRestrictionEntryStruct { + endpoint_no endpoint = 0; + cluster_id cluster = 1; + AccessRestrictionStruct restrictions[] = 2; + } + + fabric_scoped struct AccessRestrictionEntryStruct { + fabric_sensitive endpoint_no endpoint = 0; + fabric_sensitive cluster_id cluster = 1; + fabric_sensitive AccessRestrictionStruct restrictions[] = 2; + fabric_idx fabricIndex = 254; + } + + 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; + } + + fabric_sensitive info event access(read: administer) FabricRestrictionReviewUpdate = 2 { + int64u token = 0; + optional long_char_string instruction = 1; + optional long_char_string ARLRequestFlowUrl = 2; + fabric_idx fabricIndex = 254; + } + + attribute access(read: administer, write: administer) AccessControlEntryStruct acl[] = 0; + attribute access(read: administer, write: administer) optional AccessControlExtensionStruct extension[] = 1; + readonly attribute int16u subjectsPerAccessControlEntry = 2; + readonly attribute int16u targetsPerAccessControlEntry = 3; + readonly attribute int16u accessControlEntriesPerFabric = 4; + readonly attribute optional CommissioningAccessRestrictionEntryStruct commissioningARL[] = 5; + readonly attribute optional AccessRestrictionEntryStruct arl[] = 6; + 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 ReviewFabricRestrictionsRequest { + CommissioningAccessRestrictionEntryStruct arl[] = 0; + } + + response struct ReviewFabricRestrictionsResponse = 1 { + int64u token = 0; + } + + /** This command signals to the service associated with the device vendor that the fabric administrator would like a review of the current restrictions on the accessing fabric. */ + fabric command access(invoke: administer) ReviewFabricRestrictions(ReviewFabricRestrictionsRequest): ReviewFabricRestrictionsResponse = 0; +} + +/** 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. */ +cluster BasicInformation = 40 { + revision 3; + + 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 optional char_string<16> manufacturingDate = 11; + readonly attribute optional char_string<32> partNumber = 12; + readonly attribute optional long_char_string<256> productURL = 13; + readonly attribute optional char_string<64> productLabel = 14; + readonly attribute optional char_string<32> serialNumber = 15; + attribute access(write: manage) optional boolean localConfigDisabled = 16; + readonly attribute optional boolean reachable = 17; + readonly attribute char_string<32> uniqueID = 18; + readonly attribute CapabilityMinimaStruct capabilityMinima = 19; + readonly attribute optional ProductAppearanceStruct productAppearance = 20; + readonly attribute int32u specificationVersion = 21; + readonly attribute int16u maxPathsPerInvoke = 22; + 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 MfgSpecificPing(): DefaultSuccess = 0; +} + +/** Provides an interface for providing OTA software updates */ +cluster OtaSoftwareUpdateProvider = 41 { + revision 1; // NOTE: Default/not specifically set + + enum ApplyUpdateActionEnum : enum8 { + kProceed = 0; + kAwaitNextAction = 1; + kDiscontinue = 2; + } + + enum DownloadProtocolEnum : enum8 { + kBDXSynchronous = 0; + kBDXAsynchronous = 1; + kHTTPS = 2; + kVendorSpecific = 3; + } + + enum StatusEnum : 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; + DownloadProtocolEnum 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 { + StatusEnum 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 { + ApplyUpdateActionEnum 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 */ +cluster OtaSoftwareUpdateRequestor = 42 { + revision 1; // NOTE: Default/not specifically set + + enum AnnouncementReasonEnum : enum8 { + kSimpleAnnouncement = 0; + kUpdateAvailable = 1; + kUrgentUpdateAvailable = 2; + } + + enum ChangeReasonEnum : enum8 { + kUnknown = 0; + kSuccess = 1; + kFailure = 2; + kTimeOut = 3; + kDelayByProvider = 4; + } + + enum UpdateStateEnum : 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 { + UpdateStateEnum previousState = 0; + UpdateStateEnum newState = 1; + ChangeReasonEnum 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 access(write: administer) ProviderLocation defaultOTAProviders[] = 0; + readonly attribute boolean updatePossible = 1; + readonly attribute UpdateStateEnum 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; + AnnouncementReasonEnum announcementReason = 2; + optional octet_string<512> metadataForNode = 3; + endpoint_no endpoint = 4; + } + + /** Announce the presence of an OTA Provider */ + 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 */ +cluster LocalizationConfiguration = 43 { + revision 1; // NOTE: Default/not specifically set + + attribute access(write: manage) 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. */ +cluster TimeFormatLocalization = 44 { + revision 1; // NOTE: Default/not specifically set + + 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; + kUseActiveLocale = 255; + } + + enum HourFormatEnum : enum8 { + k12hr = 0; + k24hr = 1; + kUseActiveLocale = 255; + } + + bitmap Feature : bitmap32 { + kCalendarFormat = 0x1; + } + + attribute access(write: manage) HourFormatEnum hourFormat = 0; + attribute access(write: manage) optional CalendarTypeEnum activeCalendarType = 1; + readonly attribute optional 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. */ +cluster UnitLocalization = 45 { + revision 1; + + enum TempUnitEnum : enum8 { + kFahrenheit = 0; + kCelsius = 1; + kKelvin = 2; + } + + bitmap Feature : bitmap32 { + kTemperatureUnit = 0x1; + } + + attribute access(write: manage) optional 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 manage global aspects of the Commissioning flow. */ +cluster GeneralCommissioning = 48 { + revision 1; // NOTE: Default/not specifically set + + enum CommissioningErrorEnum : enum8 { + kOK = 0; + kValueOutsideRange = 1; + kInvalidAuthentication = 2; + kNoFailSafe = 3; + kBusyWithOtherAdmin = 4; + kRequiredTCNotAccepted = 5; + kTCAcknowledgementsNotReceived = 6; + kTCMinVersionNotMet = 7; + } + + enum RegulatoryLocationTypeEnum : enum8 { + kIndoor = 0; + kOutdoor = 1; + kIndoorOutdoor = 2; + } + + bitmap Feature : bitmap32 { + kTermsAndConditions = 0x1; + } + + 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; + provisional readonly attribute access(read: administer) optional int16u TCAcceptedVersion = 5; + provisional readonly attribute access(read: administer) optional int16u TCMinRequiredVersion = 6; + provisional readonly attribute access(read: administer) optional bitmap16 TCAcknowledgements = 7; + provisional readonly attribute access(read: administer) optional boolean TCAcknowledgementsRequired = 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 ArmFailSafeRequest { + int16u expiryLengthSeconds = 0; + int64u breadcrumb = 1; + } + + response struct ArmFailSafeResponse = 1 { + CommissioningErrorEnum errorCode = 0; + char_string<128> debugText = 1; + } + + request struct SetRegulatoryConfigRequest { + RegulatoryLocationTypeEnum newRegulatoryConfig = 0; + char_string<2> countryCode = 1; + int64u breadcrumb = 2; + } + + response struct SetRegulatoryConfigResponse = 3 { + CommissioningErrorEnum errorCode = 0; + char_string debugText = 1; + } + + response struct CommissioningCompleteResponse = 5 { + CommissioningErrorEnum errorCode = 0; + char_string debugText = 1; + } + + request struct SetTCAcknowledgementsRequest { + int16u TCVersion = 0; + bitmap16 TCUserResponse = 1; + } + + response struct SetTCAcknowledgementsResponse = 7 { + CommissioningErrorEnum errorCode = 0; + } + + /** Arm the persistent fail-safe timer with an expiry time of now + ExpiryLengthSeconds using device clock */ + command access(invoke: administer) ArmFailSafe(ArmFailSafeRequest): ArmFailSafeResponse = 0; + /** Set the regulatory configuration to be used during commissioning */ + command access(invoke: administer) SetRegulatoryConfig(SetRegulatoryConfigRequest): SetRegulatoryConfigResponse = 2; + /** Signals the Server that the Client has successfully completed all steps of Commissioning/Recofiguration needed during fail-safe period. */ + fabric command access(invoke: administer) CommissioningComplete(): CommissioningCompleteResponse = 4; + /** This command sets the user acknowledgements received in the Enhanced Setup Flow Terms and Conditions into the node. */ + command access(invoke: administer) SetTCAcknowledgements(SetTCAcknowledgementsRequest): SetTCAcknowledgementsResponse = 6; +} + +/** Functionality to configure, enable, disable network credentials and access on a Matter device. */ +cluster NetworkCommissioning = 49 { + revision 1; // NOTE: Default/not specifically set + + 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; + kPerDeviceCredentials = 0x8; + } + + bitmap ThreadCapabilitiesBitmap : bitmap16 { + kIsBorderRouterCapable = 0x1; + kIsRouterCapable = 0x2; + kIsSleepyEndDeviceCapable = 0x4; + kIsFullThreadDevice = 0x8; + kIsSynchronizedSleepyEndDeviceCapable = 0x10; + } + + bitmap WiFiSecurityBitmap : bitmap8 { + kUnencrypted = 0x1; + kWEP = 0x2; + kWPAPersonal = 0x4; + kWPA2Personal = 0x8; + kWPA3Personal = 0x10; + kWPA3MatterPDC = 0x20; + } + + struct NetworkInfoStruct { + octet_string<32> networkID = 0; + boolean connected = 1; + optional nullable octet_string<20> networkIdentifier = 2; + optional nullable octet_string<20> clientIdentifier = 3; + } + + 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 optional int8u scanMaxTimeSeconds = 2; + readonly attribute optional 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; + provisional readonly attribute optional WiFiBandEnum supportedWiFiBands[] = 8; + provisional readonly attribute optional ThreadCapabilitiesBitmap supportedThreadFeatures = 9; + provisional readonly attribute optional int16u threadVersion = 10; + 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; + } + + response struct ScanNetworksResponse = 1 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional char_string debugText = 1; + optional WiFiInterfaceScanResultStruct wiFiScanResults[] = 2; + optional ThreadInterfaceScanResultStruct threadScanResults[] = 3; + } + + request struct AddOrUpdateWiFiNetworkRequest { + octet_string<32> ssid = 0; + octet_string<64> credentials = 1; + optional int64u breadcrumb = 2; + optional octet_string<140> networkIdentity = 3; + optional octet_string<20> clientIdentifier = 4; + optional octet_string<32> possessionNonce = 5; + } + + request struct AddOrUpdateThreadNetworkRequest { + octet_string<254> operationalDataset = 0; + optional int64u breadcrumb = 1; + } + + request struct RemoveNetworkRequest { + octet_string<32> networkID = 0; + optional int64u breadcrumb = 1; + } + + response struct NetworkConfigResponse = 5 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional char_string<512> debugText = 1; + optional int8u networkIndex = 2; + optional octet_string<140> clientIdentity = 3; + optional octet_string<64> possessionSignature = 4; + } + + request struct ConnectNetworkRequest { + octet_string<32> networkID = 0; + optional int64u breadcrumb = 1; + } + + response struct ConnectNetworkResponse = 7 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional char_string debugText = 1; + nullable int32s errorValue = 2; + } + + request struct ReorderNetworkRequest { + octet_string<32> networkID = 0; + int8u networkIndex = 1; + optional int64u breadcrumb = 2; + } + + request struct QueryIdentityRequest { + octet_string<20> keyIdentifier = 0; + optional octet_string<32> possessionNonce = 1; + } + + response struct QueryIdentityResponse = 10 { + octet_string<140> identity = 0; + optional octet_string<64> possessionSignature = 1; + } + + /** Detemine the set of networks the device sees as available. */ + command access(invoke: administer) ScanNetworks(ScanNetworksRequest): ScanNetworksResponse = 0; + /** Add or update the credentials for a given Wi-Fi network. */ + command access(invoke: administer) AddOrUpdateWiFiNetwork(AddOrUpdateWiFiNetworkRequest): NetworkConfigResponse = 2; + /** Add or update the credentials for a given Thread network. */ + command access(invoke: administer) AddOrUpdateThreadNetwork(AddOrUpdateThreadNetworkRequest): NetworkConfigResponse = 3; + /** Remove the definition of a given network (including its credentials). */ + command access(invoke: administer) RemoveNetwork(RemoveNetworkRequest): NetworkConfigResponse = 4; + /** Connect to the specified network, using previously-defined credentials. */ + command access(invoke: administer) ConnectNetwork(ConnectNetworkRequest): ConnectNetworkResponse = 6; + /** Modify the order in which networks will be presented in the Networks attribute. */ + command access(invoke: administer) ReorderNetwork(ReorderNetworkRequest): NetworkConfigResponse = 8; + /** Retrieve details about and optionally proof of possession of a network client identity. */ + command access(invoke: administer) QueryIdentity(QueryIdentityRequest): QueryIdentityResponse = 9; +} + +/** The cluster provides commands for retrieving unstructured diagnostic logs from a Node that may be used to aid in diagnostics. */ +cluster DiagnosticLogs = 50 { + revision 1; // NOTE: Default/not specifically set + + enum IntentEnum : enum8 { + kEndUserSupport = 0; + kNetworkDiag = 1; + kCrashLogs = 2; + } + + enum StatusEnum : enum8 { + kSuccess = 0; + kExhausted = 1; + kNoLogs = 2; + kBusy = 3; + kDenied = 4; + } + + enum TransferProtocolEnum : enum8 { + kResponsePayload = 0; + kBDX = 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 RetrieveLogsRequestRequest { + IntentEnum intent = 0; + TransferProtocolEnum requestedProtocol = 1; + optional char_string<32> transferFileDesignator = 2; + } + + response struct RetrieveLogsResponse = 1 { + StatusEnum status = 0; + long_octet_string logContent = 1; + optional epoch_us UTCTimeStamp = 2; + optional systime_us timeSinceBoot = 3; + } + + /** Retrieving diagnostic logs from a Node */ + command RetrieveLogsRequest(RetrieveLogsRequestRequest): RetrieveLogsResponse = 0; +} + +/** 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. */ +cluster GeneralDiagnostics = 51 { + revision 2; + + 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; + } + + bitmap Feature : bitmap32 { + kDataModelTest = 0x1; + } + + 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 optional int64u upTime = 2; + readonly attribute optional int32u totalOperationalHours = 3; + readonly attribute optional BootReasonEnum bootReason = 4; + readonly attribute optional HardwareFaultEnum activeHardwareFaults[] = 5; + readonly attribute optional RadioFaultEnum activeRadioFaults[] = 6; + readonly attribute optional 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; + } + + response struct TimeSnapshotResponse = 2 { + systime_ms systemTimeMs = 0; + nullable posix_ms posixTimeMs = 1; + } + + request struct PayloadTestRequestRequest { + octet_string<16> enableKey = 0; + int8u value = 1; + int16u count = 2; + } + + response struct PayloadTestResponse = 4 { + octet_string payload = 0; + } + + /** Provide a means for certification tests to trigger some test-plan-specific events */ + command access(invoke: manage) TestEventTrigger(TestEventTriggerRequest): DefaultSuccess = 0; + /** Take a snapshot of system time and epoch time. */ + command TimeSnapshot(): TimeSnapshotResponse = 1; + /** Request a variable length payload response. */ + command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; +} + +/** 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 */ +cluster ThreadNetworkDiagnostics = 53 { + revision 2; + + 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 optional int64u overrunCount = 6; + readonly attribute NeighborTableStruct neighborTable[] = 7; + readonly attribute RouteTableStruct routeTable[] = 8; + readonly attribute nullable int32u partitionId = 9; + readonly attribute nullable int16u weighting = 10; + readonly attribute nullable int16u dataVersion = 11; + readonly attribute nullable int16u stableDataVersion = 12; + readonly attribute nullable int8u leaderRouterId = 13; + readonly attribute optional int16u detachedRoleCount = 14; + readonly attribute optional int16u childRoleCount = 15; + readonly attribute optional int16u routerRoleCount = 16; + readonly attribute optional int16u leaderRoleCount = 17; + readonly attribute optional int16u attachAttemptCount = 18; + readonly attribute optional int16u partitionIdChangeCount = 19; + readonly attribute optional int16u betterPartitionAttachAttemptCount = 20; + readonly attribute optional int16u parentChangeCount = 21; + readonly attribute optional int32u txTotalCount = 22; + readonly attribute optional int32u txUnicastCount = 23; + readonly attribute optional int32u txBroadcastCount = 24; + readonly attribute optional int32u txAckRequestedCount = 25; + readonly attribute optional int32u txAckedCount = 26; + readonly attribute optional int32u txNoAckRequestedCount = 27; + readonly attribute optional int32u txDataCount = 28; + readonly attribute optional int32u txDataPollCount = 29; + readonly attribute optional int32u txBeaconCount = 30; + readonly attribute optional int32u txBeaconRequestCount = 31; + readonly attribute optional int32u txOtherCount = 32; + readonly attribute optional int32u txRetryCount = 33; + readonly attribute optional int32u txDirectMaxRetryExpiryCount = 34; + readonly attribute optional int32u txIndirectMaxRetryExpiryCount = 35; + readonly attribute optional int32u txErrCcaCount = 36; + readonly attribute optional int32u txErrAbortCount = 37; + readonly attribute optional int32u txErrBusyChannelCount = 38; + readonly attribute optional int32u rxTotalCount = 39; + readonly attribute optional int32u rxUnicastCount = 40; + readonly attribute optional int32u rxBroadcastCount = 41; + readonly attribute optional int32u rxDataCount = 42; + readonly attribute optional int32u rxDataPollCount = 43; + readonly attribute optional int32u rxBeaconCount = 44; + readonly attribute optional int32u rxBeaconRequestCount = 45; + readonly attribute optional int32u rxOtherCount = 46; + readonly attribute optional int32u rxAddressFilteredCount = 47; + readonly attribute optional int32u rxDestAddrFilteredCount = 48; + readonly attribute optional int32u rxDuplicatedCount = 49; + readonly attribute optional int32u rxErrNoFrameCount = 50; + readonly attribute optional int32u rxErrUnknownNeighborCount = 51; + readonly attribute optional int32u rxErrInvalidSrcAddrCount = 52; + readonly attribute optional int32u rxErrSecCount = 53; + readonly attribute optional int32u rxErrFcsCount = 54; + readonly attribute optional int32u rxErrOtherCount = 55; + readonly attribute optional nullable int64u activeTimestamp = 56; + readonly attribute optional nullable int64u pendingTimestamp = 57; + readonly attribute optional 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; + + /** Reception of this command SHALL reset the OverrunCount attributes to 0 */ + command access(invoke: manage) ResetCounts(): 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. */ +cluster WiFiNetworkDiagnostics = 54 { + revision 1; // NOTE: Default/not specifically set + + 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 associationFailureCause = 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 optional nullable int32u beaconLostCount = 5; + readonly attribute optional nullable int32u beaconRxCount = 6; + readonly attribute optional nullable int32u packetMulticastRxCount = 7; + readonly attribute optional nullable int32u packetMulticastTxCount = 8; + readonly attribute optional nullable int32u packetUnicastRxCount = 9; + readonly attribute optional nullable int32u packetUnicastTxCount = 10; + readonly attribute optional nullable int64u currentMaxRate = 11; + readonly attribute optional 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; + + /** Reception of this command SHALL reset the Breacon and Packet related count attributes to 0 */ + command ResetCounts(): DefaultSuccess = 0; +} + +/** Commands to trigger a Node to allow a new Administrator to commission it. */ +cluster AdministratorCommissioning = 60 { + revision 1; // NOTE: Default/not specifically set + + enum CommissioningWindowStatusEnum : enum8 { + kWindowNotOpen = 0; + kEnhancedWindowOpen = 1; + kBasicWindowOpen = 2; + } + + enum StatusCode : enum8 { + kBusy = 2; + kPAKEParameterError = 3; + kWindowNotOpen = 4; + } + + bitmap Feature : bitmap32 { + kBasic = 0x1; + } + + readonly attribute CommissioningWindowStatusEnum windowStatus = 0; + readonly attribute nullable fabric_idx adminFabricIndex = 1; + readonly attribute nullable vendor_id 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<32> salt = 4; + } + + request struct OpenBasicCommissioningWindowRequest { + int16u commissioningTimeout = 0; + } + + /** This command is used by a current Administrator to instruct a Node to go into commissioning mode using enhanced commissioning method. */ + timed command access(invoke: administer) OpenCommissioningWindow(OpenCommissioningWindowRequest): DefaultSuccess = 0; + /** This command is used by a current Administrator to instruct a Node to go into commissioning mode using basic commissioning method, if the node supports it. */ + timed command access(invoke: administer) OpenBasicCommissioningWindow(OpenBasicCommissioningWindowRequest): DefaultSuccess = 1; + /** This command is used by a current Administrator to instruct a Node to revoke any active Open Commissioning Window or Open Basic Commissioning Window command. */ + 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. */ +cluster OperationalCredentials = 62 { + revision 1; // NOTE: Default/not specifically set + + 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<32> attestationNonce = 0; + } + + response struct AttestationResponse = 1 { + octet_string<900> attestationElements = 0; + octet_string<64> attestationSignature = 1; + } + + request struct CertificateChainRequestRequest { + CertificateChainTypeEnum certificateType = 0; + } + + response struct CertificateChainResponse = 3 { + octet_string<600> certificate = 0; + } + + request struct CSRRequestRequest { + octet_string<32> CSRNonce = 0; + optional boolean isForUpdateNOC = 1; + } + + response struct CSRResponse = 5 { + octet_string NOCSRElements = 0; + octet_string attestationSignature = 1; + } + + request struct AddNOCRequest { + octet_string<400> NOCValue = 0; + optional octet_string<400> ICACValue = 1; + octet_string<16> IPKValue = 2; + int64u caseAdminSubject = 3; + vendor_id adminVendorId = 4; + } + + request struct UpdateNOCRequest { + octet_string NOCValue = 0; + optional octet_string ICACValue = 1; + } + + response struct NOCResponse = 8 { + NodeOperationalCertStatusEnum statusCode = 0; + optional fabric_idx fabricIndex = 1; + optional char_string<128> debugText = 2; + } + + request struct UpdateFabricLabelRequest { + char_string<32> label = 0; + } + + request struct RemoveFabricRequest { + fabric_idx fabricIndex = 0; + } + + request struct AddTrustedRootCertificateRequest { + octet_string rootCACertificate = 0; + } + + /** Sender is requesting attestation information from the receiver. */ + command access(invoke: administer) AttestationRequest(AttestationRequestRequest): AttestationResponse = 0; + /** Sender is requesting a device attestation certificate from the receiver. */ + command access(invoke: administer) CertificateChainRequest(CertificateChainRequestRequest): CertificateChainResponse = 2; + /** Sender is requesting a certificate signing request (CSR) from the receiver. */ + command access(invoke: administer) CSRRequest(CSRRequestRequest): CSRResponse = 4; + /** Sender is requesting to add the new node operational certificates. */ + command access(invoke: administer) AddNOC(AddNOCRequest): NOCResponse = 6; + /** Sender is requesting to update the node operational certificates. */ + fabric command access(invoke: administer) UpdateNOC(UpdateNOCRequest): NOCResponse = 7; + /** This command SHALL be used by an Administrative Node to set the user-visible Label field for a given Fabric, as reflected by entries in the Fabrics attribute. */ + fabric command access(invoke: administer) UpdateFabricLabel(UpdateFabricLabelRequest): NOCResponse = 9; + /** This command is used by Administrative Nodes to remove a given fabric index and delete all associated fabric-scoped data. */ + command access(invoke: administer) RemoveFabric(RemoveFabricRequest): NOCResponse = 10; + /** This command SHALL add a Trusted Root CA Certificate, provided as its CHIP Certificate representation. */ + command access(invoke: administer) AddTrustedRootCertificate(AddTrustedRootCertificateRequest): DefaultSuccess = 11; +} + +/** The Group Key Management Cluster is the mechanism by which group keys are managed. */ +cluster GroupKeyManagement = 63 { + revision 1; // NOTE: Default/not specifically set + + enum GroupKeySecurityPolicyEnum : enum8 { + kTrustFirst = 0; + kCacheAndSync = 1; + } + + bitmap Feature : bitmap32 { + kCacheAndSync = 0x1; + } + + fabric_scoped struct GroupInfoMapStruct { + group_id groupId = 1; + endpoint_no endpoints[] = 2; + optional char_string<16> groupName = 3; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct GroupKeyMapStruct { + group_id groupId = 1; + int16u groupKeySetID = 2; + fabric_idx fabricIndex = 254; + } + + struct GroupKeySetStruct { + int16u groupKeySetID = 0; + GroupKeySecurityPolicyEnum groupKeySecurityPolicy = 1; + nullable octet_string<16> epochKey0 = 2; + nullable epoch_us epochStartTime0 = 3; + nullable octet_string<16> epochKey1 = 4; + nullable epoch_us epochStartTime1 = 5; + nullable octet_string<16> epochKey2 = 6; + nullable epoch_us epochStartTime2 = 7; + } + + attribute access(write: manage) GroupKeyMapStruct groupKeyMap[] = 0; + readonly attribute GroupInfoMapStruct groupTable[] = 1; + readonly attribute int16u maxGroupsPerFabric = 2; + readonly attribute int16u maxGroupKeysPerFabric = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct KeySetWriteRequest { + GroupKeySetStruct groupKeySet = 0; + } + + request struct KeySetReadRequest { + int16u groupKeySetID = 0; + } + + response struct KeySetReadResponse = 2 { + GroupKeySetStruct groupKeySet = 0; + } + + request struct KeySetRemoveRequest { + int16u groupKeySetID = 0; + } + + response struct KeySetReadAllIndicesResponse = 5 { + int16u groupKeySetIDs[] = 0; + } + + /** Write a new set of keys for the given key set id. */ + fabric command access(invoke: administer) KeySetWrite(KeySetWriteRequest): DefaultSuccess = 0; + /** Read the keys for a given key set id. */ + fabric command access(invoke: administer) KeySetRead(KeySetReadRequest): KeySetReadResponse = 1; + /** Revoke a Root Key from a Group */ + fabric command access(invoke: administer) KeySetRemove(KeySetRemoveRequest): DefaultSuccess = 3; + /** Return the list of Group Key Sets associated with the accessing fabric */ + 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. */ +cluster FixedLabel = 64 { + revision 1; // NOTE: Default/not specifically set + + 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. */ +cluster UserLabel = 65 { + revision 1; // NOTE: Default/not specifically set + + 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. */ +cluster Thermostat = 513 { + revision 7; + + enum ACCapacityFormatEnum : enum8 { + kBTUh = 0; + } + + enum ACCompressorTypeEnum : enum8 { + kUnknown = 0; + kT1 = 1; + kT2 = 2; + kT3 = 3; + } + + enum ACLouverPositionEnum : enum8 { + kClosed = 1; + kOpen = 2; + kQuarter = 3; + kHalf = 4; + kThreeQuarters = 5; + } + + enum ACRefrigerantTypeEnum : enum8 { + kUnknown = 0; + kR22 = 1; + kR410a = 2; + kR407c = 3; + } + + enum ACTypeEnum : enum8 { + kUnknown = 0; + kCoolingFixed = 1; + kHeatPumpFixed = 2; + kCoolingInverter = 3; + kHeatPumpInverter = 4; + } + + enum ControlSequenceOfOperationEnum : enum8 { + kCoolingOnly = 0; + kCoolingWithReheat = 1; + kHeatingOnly = 2; + kHeatingWithReheat = 3; + kCoolingAndHeating = 4; + kCoolingAndHeatingWithReheat = 5; + } + + enum PresetScenarioEnum : enum8 { + kOccupied = 1; + kUnoccupied = 2; + kSleep = 3; + kWake = 4; + kVacation = 5; + kGoingToSleep = 6; + kUserDefined = 254; + } + + enum SetpointChangeSourceEnum : enum8 { + kManual = 0; + kSchedule = 1; + kExternal = 2; + } + + enum SetpointRaiseLowerModeEnum : enum8 { + kHeat = 0; + kCool = 1; + kBoth = 2; + } + + enum StartOfWeekEnum : enum8 { + kSunday = 0; + kMonday = 1; + kTuesday = 2; + kWednesday = 3; + kThursday = 4; + kFriday = 5; + kSaturday = 6; + } + + enum SystemModeEnum : enum8 { + kOff = 0; + kAuto = 1; + kCool = 3; + kHeat = 4; + kEmergencyHeat = 5; + kPrecooling = 6; + kFanOnly = 7; + kDry = 8; + kSleep = 9; + } + + enum TemperatureSetpointHoldEnum : enum8 { + kSetpointHoldOff = 0; + kSetpointHoldOn = 1; + } + + enum ThermostatRunningModeEnum : enum8 { + kOff = 0; + kCool = 3; + kHeat = 4; + } + + bitmap ACErrorCodeBitmap : bitmap32 { + kCompressorFail = 0x1; + kRoomSensorFail = 0x2; + kOutdoorSensorFail = 0x4; + kCoilSensorFail = 0x8; + kFanFail = 0x10; + } + + bitmap Feature : bitmap32 { + kHeating = 0x1; + kCooling = 0x2; + kOccupancy = 0x4; + kScheduleConfiguration = 0x8; + kSetback = 0x10; + kAutoMode = 0x20; + kLocalTemperatureNotExposed = 0x40; + kMatterScheduleConfiguration = 0x80; + kPresets = 0x100; + } + + bitmap HVACSystemTypeBitmap : bitmap8 { + kCoolingStage = 0x3; + kHeatingStage = 0xC; + kHeatingIsHeatPump = 0x10; + kHeatingUsesFuel = 0x20; + } + + bitmap OccupancyBitmap : bitmap8 { + kOccupied = 0x1; + } + + bitmap PresetTypeFeaturesBitmap : bitmap16 { + kAutomatic = 0x1; + kSupportsNames = 0x2; + } + + bitmap ProgrammingOperationModeBitmap : bitmap8 { + kScheduleActive = 0x1; + kAutoRecovery = 0x2; + kEconomy = 0x4; + } + + bitmap RelayStateBitmap : bitmap16 { + kHeat = 0x1; + kCool = 0x2; + kFan = 0x4; + kHeatStage2 = 0x8; + kCoolStage2 = 0x10; + kFanStage2 = 0x20; + kFanStage3 = 0x40; + } + + bitmap RemoteSensingBitmap : bitmap8 { + kLocalTemperature = 0x1; + kOutdoorTemperature = 0x2; + kOccupancy = 0x4; + } + + bitmap ScheduleDayOfWeekBitmap : bitmap8 { + kSunday = 0x1; + kMonday = 0x2; + kTuesday = 0x4; + kWednesday = 0x8; + kThursday = 0x10; + kFriday = 0x20; + kSaturday = 0x40; + kAway = 0x80; + } + + bitmap ScheduleModeBitmap : bitmap8 { + kHeatSetpointPresent = 0x1; + kCoolSetpointPresent = 0x2; + } + + bitmap ScheduleTypeFeaturesBitmap : bitmap16 { + kSupportsPresets = 0x1; + kSupportsSetpoints = 0x2; + kSupportsNames = 0x4; + kSupportsOff = 0x8; + } + + struct ScheduleTransitionStruct { + ScheduleDayOfWeekBitmap dayOfWeek = 0; + int16u transitionTime = 1; + optional octet_string<16> presetHandle = 2; + optional SystemModeEnum systemMode = 3; + optional temperature coolingSetpoint = 4; + optional temperature heatingSetpoint = 5; + } + + struct ScheduleStruct { + nullable octet_string<16> scheduleHandle = 0; + SystemModeEnum systemMode = 1; + optional char_string<64> name = 2; + optional octet_string<16> presetHandle = 3; + ScheduleTransitionStruct transitions[] = 4; + nullable boolean builtIn = 5; + } + + struct PresetStruct { + nullable octet_string<16> presetHandle = 0; + PresetScenarioEnum presetScenario = 1; + optional nullable char_string<64> name = 2; + optional temperature coolingSetpoint = 3; + optional temperature heatingSetpoint = 4; + nullable boolean builtIn = 5; + } + + struct PresetTypeStruct { + PresetScenarioEnum presetScenario = 0; + int8u numberOfPresets = 1; + PresetTypeFeaturesBitmap presetTypeFeatures = 2; + } + + struct ScheduleTypeStruct { + SystemModeEnum systemMode = 0; + int8u numberOfSchedules = 1; + ScheduleTypeFeaturesBitmap scheduleTypeFeatures = 2; + } + + struct WeeklyScheduleTransitionStruct { + int16u transitionTime = 0; + nullable temperature heatSetpoint = 1; + nullable temperature coolSetpoint = 2; + } + + readonly attribute nullable temperature localTemperature = 0; + readonly attribute optional nullable temperature outdoorTemperature = 1; + readonly attribute optional OccupancyBitmap occupancy = 2; + readonly attribute optional temperature absMinHeatSetpointLimit = 3; + readonly attribute optional temperature absMaxHeatSetpointLimit = 4; + readonly attribute optional temperature absMinCoolSetpointLimit = 5; + readonly attribute optional temperature absMaxCoolSetpointLimit = 6; + readonly attribute optional int8u PICoolingDemand = 7; + readonly attribute optional int8u PIHeatingDemand = 8; + attribute access(write: manage) optional HVACSystemTypeBitmap HVACSystemTypeConfiguration = 9; + attribute access(write: manage) optional int8s localTemperatureCalibration = 16; + attribute optional temperature occupiedCoolingSetpoint = 17; + attribute optional temperature occupiedHeatingSetpoint = 18; + attribute optional temperature unoccupiedCoolingSetpoint = 19; + attribute optional temperature unoccupiedHeatingSetpoint = 20; + attribute access(write: manage) optional temperature minHeatSetpointLimit = 21; + attribute access(write: manage) optional temperature maxHeatSetpointLimit = 22; + attribute access(write: manage) optional temperature minCoolSetpointLimit = 23; + attribute access(write: manage) optional temperature maxCoolSetpointLimit = 24; + attribute access(write: manage) optional int8s minSetpointDeadBand = 25; + attribute access(write: manage) optional RemoteSensingBitmap remoteSensing = 26; + attribute access(write: manage) ControlSequenceOfOperationEnum controlSequenceOfOperation = 27; + attribute access(write: manage) SystemModeEnum systemMode = 28; + readonly attribute optional ThermostatRunningModeEnum thermostatRunningMode = 30; + readonly attribute optional StartOfWeekEnum startOfWeek = 32; + readonly attribute optional int8u numberOfWeeklyTransitions = 33; + readonly attribute optional int8u numberOfDailyTransitions = 34; + attribute access(write: manage) optional TemperatureSetpointHoldEnum temperatureSetpointHold = 35; + attribute access(write: manage) optional nullable int16u temperatureSetpointHoldDuration = 36; + attribute access(write: manage) optional ProgrammingOperationModeBitmap thermostatProgrammingOperationMode = 37; + readonly attribute optional RelayStateBitmap thermostatRunningState = 41; + readonly attribute optional SetpointChangeSourceEnum setpointChangeSource = 48; + readonly attribute optional nullable int16s setpointChangeAmount = 49; + readonly attribute optional epoch_s setpointChangeSourceTimestamp = 50; + attribute access(write: manage) optional nullable int8u occupiedSetback = 52; + readonly attribute optional nullable int8u occupiedSetbackMin = 53; + readonly attribute optional nullable int8u occupiedSetbackMax = 54; + attribute access(write: manage) optional nullable int8u unoccupiedSetback = 55; + readonly attribute optional nullable int8u unoccupiedSetbackMin = 56; + readonly attribute optional nullable int8u unoccupiedSetbackMax = 57; + attribute access(write: manage) optional int8u emergencyHeatDelta = 58; + attribute access(write: manage) optional ACTypeEnum ACType = 64; + attribute access(write: manage) optional int16u ACCapacity = 65; + attribute access(write: manage) optional ACRefrigerantTypeEnum ACRefrigerantType = 66; + attribute access(write: manage) optional ACCompressorTypeEnum ACCompressorType = 67; + attribute access(write: manage) optional ACErrorCodeBitmap ACErrorCode = 68; + attribute access(write: manage) optional ACLouverPositionEnum ACLouverPosition = 69; + readonly attribute optional nullable temperature ACCoilTemperature = 70; + attribute access(write: manage) optional ACCapacityFormatEnum ACCapacityformat = 71; + readonly attribute optional PresetTypeStruct presetTypes[] = 72; + readonly attribute optional ScheduleTypeStruct scheduleTypes[] = 73; + readonly attribute optional int8u numberOfPresets = 74; + readonly attribute optional int8u numberOfSchedules = 75; + readonly attribute optional int8u numberOfScheduleTransitions = 76; + readonly attribute optional nullable int8u numberOfScheduleTransitionPerDay = 77; + readonly attribute optional nullable octet_string<16> activePresetHandle = 78; + readonly attribute optional nullable octet_string<16> activeScheduleHandle = 79; + attribute access(write: manage) optional PresetStruct presets[] = 80; + attribute access(write: manage) optional ScheduleStruct schedules[] = 81; + readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 82; + 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 { + SetpointRaiseLowerModeEnum mode = 0; + int8s amount = 1; + } + + response struct GetWeeklyScheduleResponse = 0 { + int8u numberOfTransitionsForSequence = 0; + ScheduleDayOfWeekBitmap dayOfWeekForSequence = 1; + ScheduleModeBitmap modeForSequence = 2; + WeeklyScheduleTransitionStruct transitions[] = 3; + } + + request struct SetWeeklyScheduleRequest { + int8u numberOfTransitionsForSequence = 0; + ScheduleDayOfWeekBitmap dayOfWeekForSequence = 1; + ScheduleModeBitmap modeForSequence = 2; + WeeklyScheduleTransitionStruct transitions[] = 3; + } + + request struct GetWeeklyScheduleRequest { + ScheduleDayOfWeekBitmap daysToReturn = 0; + ScheduleModeBitmap modeToReturn = 1; + } + + request struct SetActiveScheduleRequestRequest { + octet_string<16> scheduleHandle = 0; + } + + request struct SetActivePresetRequestRequest { + nullable octet_string<16> presetHandle = 0; + } + + response struct AtomicResponse = 253 { + status statusCode = 0; + AtomicAttributeStatusStruct attributeStatus[] = 1; + optional int16u timeout = 2; + } + + request struct AtomicRequestRequest { + AtomicRequestTypeEnum requestType = 0; + attrib_id attributeRequests[] = 1; + optional int16u timeout = 2; + } + + /** Upon receipt, the attributes for the indicated setpoint(s) SHALL have the amount specified in the Amount field added to them. */ + command SetpointRaiseLower(SetpointRaiseLowerRequest): DefaultSuccess = 0; + /** This command is used to update the thermostat weekly setpoint schedule from a management system. */ + command access(invoke: manage) SetWeeklySchedule(SetWeeklyScheduleRequest): DefaultSuccess = 1; + /** The Current Weekly Schedule Command is sent from the server in response to the Get Weekly Schedule Command. */ + command GetWeeklySchedule(GetWeeklyScheduleRequest): GetWeeklyScheduleResponse = 2; + /** This command is used to clear the weekly schedule. */ + command access(invoke: manage) ClearWeeklySchedule(): DefaultSuccess = 3; + /** Upon receipt, if the Schedules attribute contains a ScheduleStruct whose ScheduleHandle field matches the value of the ScheduleHandle field, the server SHALL set the thermostat's ActiveScheduleHandle attribute to the value of the ScheduleHandle field. */ + command SetActiveScheduleRequest(SetActiveScheduleRequestRequest): DefaultSuccess = 5; + /** ID */ + command SetActivePresetRequest(SetActivePresetRequestRequest): DefaultSuccess = 6; + /** Begins, Commits or Cancels an atomic write */ + command access(invoke: manage) AtomicRequest(AtomicRequestRequest): AtomicResponse = 254; +} + +/** Manage the Thread network of Thread Border Router */ +provisional cluster ThreadBorderRouterManagement = 1106 { + revision 1; + + bitmap Feature : bitmap32 { + kPANChange = 0x1; + } + + provisional readonly attribute char_string<63> borderRouterName = 0; + provisional readonly attribute octet_string<254> borderAgentID = 1; + provisional readonly attribute int16u threadVersion = 2; + provisional readonly attribute boolean interfaceEnabled = 3; + provisional readonly attribute nullable int64u activeDatasetTimestamp = 4; + provisional readonly attribute nullable int64u pendingDatasetTimestamp = 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; + + response struct DatasetResponse = 2 { + octet_string<254> dataset = 0; + } + + request struct SetActiveDatasetRequestRequest { + octet_string<254> activeDataset = 0; + optional int64u breadcrumb = 1; + } + + request struct SetPendingDatasetRequestRequest { + octet_string<254> pendingDataset = 0; + } + + /** Command to request the active operational dataset of the Thread network to which the border router is connected. This command must be sent over a valid CASE session */ + command access(invoke: manage) GetActiveDatasetRequest(): DatasetResponse = 0; + /** Command to request the pending dataset of the Thread network to which the border router is connected. This command must be sent over a valid CASE session */ + command access(invoke: manage) GetPendingDatasetRequest(): DatasetResponse = 1; + /** Command to set or update the active Dataset of the Thread network to which the Border Router is connected. */ + command access(invoke: manage) SetActiveDatasetRequest(SetActiveDatasetRequestRequest): DefaultSuccess = 3; + /** Command set or update the pending Dataset of the Thread network to which the Border Router is connected. */ + command access(invoke: manage) SetPendingDatasetRequest(SetPendingDatasetRequestRequest): DefaultSuccess = 4; +} + +endpoint 0 { + device type ma_rootdevice = 22, version 1; + + binding cluster OtaSoftwareUpdateProvider; + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster AccessControl { + emits event AccessControlEntryChanged; + emits event AccessControlExtensionChanged; + callback attribute acl; + callback attribute extension; + callback attribute subjectsPerAccessControlEntry; + callback attribute targetsPerAccessControlEntry; + callback attribute accessControlEntriesPerFabric; + callback attribute attributeList; + ram attribute featureMap default = 0; + callback attribute clusterRevision; + } + + server cluster BasicInformation { + emits event StartUp; + emits event ShutDown; + emits event Leave; + callback attribute dataModelRevision; + callback attribute vendorName; + callback attribute vendorID; + callback attribute productName; + callback attribute productID; + persist attribute nodeLabel; + callback attribute location; + callback attribute hardwareVersion; + callback attribute hardwareVersionString; + callback attribute softwareVersion; + callback attribute softwareVersionString; + callback attribute manufacturingDate; + callback attribute partNumber; + callback attribute productURL; + callback attribute productLabel; + callback attribute serialNumber; + persist attribute localConfigDisabled default = 0; + callback attribute uniqueID; + callback attribute capabilityMinima; + callback attribute specificationVersion; + callback attribute maxPathsPerInvoke; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 3; + } + + server cluster OtaSoftwareUpdateRequestor { + emits event StateTransition; + emits event VersionApplied; + emits event DownloadError; + callback attribute defaultOTAProviders; + 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; + + handle command AnnounceOTAProvider; + } + + server cluster LocalizationConfiguration { + persist attribute activeLocale default = "en-US"; + callback attribute supportedLocales; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster TimeFormatLocalization { + persist attribute hourFormat default = 0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster UnitLocalization { + ram attribute temperatureUnit; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0x1; + ram attribute clusterRevision default = 1; + } + + server cluster GeneralCommissioning { + ram attribute breadcrumb default = 0x0000000000000000; + callback attribute basicCommissioningInfo; + callback attribute regulatoryConfig; + callback attribute locationCapability; + callback attribute supportsConcurrentConnection; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command ArmFailSafe; + handle command ArmFailSafeResponse; + handle command SetRegulatoryConfig; + handle command SetRegulatoryConfigResponse; + handle command CommissioningComplete; + handle command CommissioningCompleteResponse; + } + + 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; + callback attribute supportedWiFiBands; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 1; + ram attribute clusterRevision default = 1; + + handle command ScanNetworks; + handle command ScanNetworksResponse; + handle command AddOrUpdateWiFiNetwork; + handle command AddOrUpdateThreadNetwork; + handle command RemoveNetwork; + handle command NetworkConfigResponse; + handle command ConnectNetwork; + handle command ConnectNetworkResponse; + handle command ReorderNetwork; + } + + server cluster DiagnosticLogs { + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command RetrieveLogsRequest; + handle command RetrieveLogsResponse; + } + + server cluster GeneralDiagnostics { + emits event BootReason; + callback attribute networkInterfaces; + callback attribute rebootCount; + callback attribute upTime; + callback attribute totalOperationalHours; + callback attribute bootReason; + callback attribute testEventTriggersEnabled default = false; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + + handle command TestEventTrigger; + handle command TimeSnapshot; + handle command TimeSnapshotResponse; + } + + server cluster WiFiNetworkDiagnostics { + callback attribute bssid; + callback attribute securityType; + callback attribute wiFiVersion; + callback attribute channelNumber; + callback attribute rssi; + callback attribute currentMaxRate; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster AdministratorCommissioning { + callback attribute windowStatus; + callback attribute adminFabricIndex; + callback attribute adminVendorId; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command OpenCommissioningWindow; + handle command RevokeCommissioning; + } + + 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; + + handle command AttestationRequest; + handle command AttestationResponse; + handle command CertificateChainRequest; + handle command CertificateChainResponse; + handle command CSRRequest; + handle command CSRResponse; + handle command AddNOC; + handle command UpdateNOC; + handle command NOCResponse; + handle command UpdateFabricLabel; + handle command RemoveFabric; + handle command AddTrustedRootCertificate; + } + + server cluster GroupKeyManagement { + callback attribute groupKeyMap; + callback attribute groupTable; + callback attribute maxGroupsPerFabric; + callback attribute maxGroupKeysPerFabric; + callback attribute featureMap; + callback attribute clusterRevision; + + handle command KeySetWrite; + handle command KeySetRead; + handle command KeySetReadResponse; + handle command KeySetRemove; + handle command KeySetReadAllIndices; + handle command KeySetReadAllIndicesResponse; + } +} +endpoint 1 { + device type ma_thermostat = 769, version 1; + + binding cluster Identify; + + server cluster Identify { + ram attribute identifyTime default = 0x0000; + ram attribute identifyType default = 0x0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 4; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Groups { + ram attribute nameSupport; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 4; + + handle command AddGroup; + handle command AddGroupResponse; + handle command ViewGroup; + handle command ViewGroupResponse; + handle command GetGroupMembership; + handle command GetGroupMembershipResponse; + handle command RemoveGroup; + handle command RemoveGroupResponse; + handle command RemoveAllGroups; + handle command AddGroupIfIdentifying; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + 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 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; + 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 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 = 7; + + handle command SetpointRaiseLower; + } +} +endpoint 2 { + device type ma_thread_border_router = 145, version 1; + + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster ThreadNetworkDiagnostics { + callback attribute channel; + callback attribute routingRole; + callback attribute networkName; + callback attribute panId; + callback attribute extendedPanId; + callback attribute meshLocalPrefix; + callback attribute neighborTable; + callback attribute routeTable; + callback attribute partitionId; + callback attribute weighting; + callback attribute dataVersion; + callback attribute stableDataVersion; + callback attribute leaderRouterId; + callback attribute securityPolicy; + callback attribute channelPage0Mask; + callback attribute operationalDatasetComponents; + callback attribute activeNetworkFaultsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 2; + } + + server cluster ThreadBorderRouterManagement { + callback attribute borderRouterName; + callback attribute borderAgentID; + callback attribute threadVersion; + callback attribute interfaceEnabled; + callback attribute activeDatasetTimestamp; + callback attribute pendingDatasetTimestamp; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 1; + + handle command GetActiveDatasetRequest; + handle command GetPendingDatasetRequest; + handle command DatasetResponse; + handle command SetActiveDatasetRequest; + handle command SetPendingDatasetRequest; + } +} +endpoint 3 { + device type ma_secondary_network_interface = 25, version 1; + + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + 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 supportedThreadFeatures; + ram attribute threadVersion; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command ScanNetworks; + handle command ScanNetworksResponse; + handle command AddOrUpdateThreadNetwork; + handle command RemoveNetwork; + handle command NetworkConfigResponse; + handle command ConnectNetwork; + handle command ConnectNetworkResponse; + handle command ReorderNetwork; + } +} + + diff --git a/examples/thermostat/nxp/zap/thermostat_matter_br.zap b/examples/thermostat/nxp/zap/thermostat_matter_br.zap new file mode 100644 index 00000000000000..3586eeb6b2320d --- /dev/null +++ b/examples/thermostat/nxp/zap/thermostat_matter_br.zap @@ -0,0 +1,5392 @@ +{ + "fileFormat": 2, + "featureLevel": 103, + "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", + "category": "matter", + "version": "chip-v1" + } + ], + "endpointTypes": [ + { + "id": 1, + "name": "MA-rootdevice", + "deviceTypeRef": { + "code": 22, + "profileId": 259, + "label": "MA-rootdevice", + "name": "MA-rootdevice" + }, + "deviceTypes": [ + { + "code": 22, + "profileId": 259, + "label": "MA-rootdevice", + "name": "MA-rootdevice" + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 22 + ], + "deviceTypeName": "MA-rootdevice", + "deviceTypeCode": 22, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "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": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": "server", + "enabled": 1, + "attributes": [ + { + "name": "DataModelRevision", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": "UniqueID", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SpecificationVersion", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxPathsPerInvoke", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "3", + "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", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "QueryImageResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ApplyUpdateRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ApplyUpdateResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "NotifyUpdateApplied", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + } + ] + }, + { + "name": "OTA Software Update Requestor", + "code": 42, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_REQUESTOR_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AnnounceOTAProvider", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "DefaultOTAProviders", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "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": "UpdateStateEnum", + "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": "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": "StateTransition", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "VersionApplied", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "DownloadError", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "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": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "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": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "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": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ArmFailSafe", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ArmFailSafeResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "SetRegulatoryConfig", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "SetRegulatoryConfigResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "CommissioningComplete", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "CommissioningCompleteResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 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": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ScanNetworks", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ScanNetworksResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "AddOrUpdateWiFiNetwork", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "AddOrUpdateThreadNetwork", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RemoveNetwork", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "NetworkConfigResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ConnectNetwork", + "code": 6, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ConnectNetworkResponse", + "code": 7, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ReorderNetwork", + "code": 8, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 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": null, + "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": "SupportedWiFiBands", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "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": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RetrieveLogsResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "TestEventTrigger", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TimeSnapshot", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TimeSnapshotResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "NetworkInterfaces", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "BootReason", + "code": 3, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Wi-Fi 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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Administrator Commissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "WindowStatus", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "CommissioningWindowStatusEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminVendorId", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Operational Credentials", + "code": 62, + "mfgCode": null, + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AttestationRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "AttestationResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "CertificateChainRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "CertificateChainResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "CSRRequest", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "CSRResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "AddNOC", + "code": 6, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "UpdateNOC", + "code": 7, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "NOCResponse", + "code": 8, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "UpdateFabricLabel", + "code": 9, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RemoveFabric", + "code": 10, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "AddTrustedRootCertificate", + "code": 11, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "NOCs", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Fabrics", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "KeySetWrite", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetRead", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "KeySetRemove", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadAllIndices", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadAllIndicesResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "GroupKeyMap", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 2, + "name": "MA-thermostat", + "deviceTypeRef": { + "code": 769, + "profileId": 259, + "label": "MA-thermostat", + "name": "MA-thermostat" + }, + "deviceTypes": [ + { + "code": 769, + "profileId": 259, + "label": "MA-thermostat", + "name": "MA-thermostat" + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 769 + ], + "deviceTypeName": "MA-thermostat", + "deviceTypeCode": 769, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + } + ] + }, + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 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": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AddGroup", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "AddGroupResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ViewGroup", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ViewGroupResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "GetGroupMembership", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "GetGroupMembershipResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "RemoveGroup", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RemoveGroupResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "RemoveAllGroups", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "AddGroupIfIdentifying", + "code": 5, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 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": "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": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 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": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Thermostat", + "code": 513, + "mfgCode": null, + "define": "THERMOSTAT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "SetpointRaiseLower", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "LocalTemperature", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "temperature", + "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": "temperature", + "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": "temperature", + "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": "temperature", + "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": "temperature", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3200", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OccupiedCoolingSetpoint", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "temperature", + "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": "temperature", + "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": "temperature", + "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": "temperature", + "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": "temperature", + "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": "temperature", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3200", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ControlSequenceOfOperation", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "ControlSequenceOfOperationEnum", + "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": "SystemModeEnum", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "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": "7", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 3, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 145, + "profileId": 259, + "label": "MA-thread-border-router", + "name": "MA-thread-border-router" + }, + "deviceTypes": [ + { + "code": 145, + "profileId": 259, + "label": "MA-thread-border-router", + "name": "MA-thread-border-router" + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 145 + ], + "deviceTypeName": "MA-thread-border-router", + "deviceTypeCode": 145, + "deviceTypeProfileId": 259, + "clusters": [ + { + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RoutingRole", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "RoutingRoleEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NetworkName", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PanId", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ExtendedPanId", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeshLocalPrefix", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NeighborTable", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RouteTable", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartitionId", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Weighting", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "DataVersion", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "StableDataVersion", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LeaderRouterId", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SecurityPolicy", + "code": 59, + "mfgCode": null, + "side": "server", + "type": "SecurityPolicy", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ChannelPage0Mask", + "code": 60, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OperationalDatasetComponents", + "code": 61, + "mfgCode": null, + "side": "server", + "type": "OperationalDatasetComponents", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveNetworkFaultsList", + "code": 62, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Thread Border Router Management", + "code": 1106, + "mfgCode": null, + "define": "THREAD_BORDER_ROUTER_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "apiMaturity": "provisional", + "commands": [ + { + "name": "GetActiveDatasetRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "GetPendingDatasetRequest", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "DatasetResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "SetActiveDatasetRequest", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "SetPendingDatasetRequest", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "BorderRouterName", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BorderAgentID", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ThreadVersion", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "InterfaceEnabled", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveDatasetTimestamp", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PendingDatasetTimestamp", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 4, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 25, + "profileId": 259, + "label": "MA-secondary-network-interface", + "name": "MA-secondary-network-interface" + }, + "deviceTypes": [ + { + "code": 25, + "profileId": 259, + "label": "MA-secondary-network-interface", + "name": "MA-secondary-network-interface" + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 25 + ], + "deviceTypeName": "MA-secondary-network-interface", + "deviceTypeCode": 25, + "deviceTypeProfileId": 259, + "clusters": [ + { + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ScanNetworks", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ScanNetworksResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "AddOrUpdateThreadNetwork", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RemoveNetwork", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "NetworkConfigResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ConnectNetwork", + "code": 6, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ConnectNetworkResponse", + "code": 7, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ReorderNetwork", + "code": 8, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 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": null, + "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": "SupportedThreadFeatures", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "ThreadCapabilitiesBitmap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ThreadVersion", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + } + ], + "endpoints": [ + { + "endpointTypeName": "MA-rootdevice", + "endpointTypeIndex": 0, + "profileId": 259, + "endpointId": 0, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "MA-thermostat", + "endpointTypeIndex": 1, + "profileId": 259, + "endpointId": 1, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 2, + "profileId": 259, + "endpointId": 2, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 3, + "profileId": 259, + "endpointId": 3, + "networkId": 0, + "parentEndpointIdentifier": null + } + ] +} \ No newline at end of file diff --git a/examples/virtual-device-app/virtual-device-common/virtual-device-app.matter b/examples/virtual-device-app/virtual-device-common/virtual-device-app.matter index 07baa25e19ebc3..eb7e56997ead55 100644 --- a/examples/virtual-device-app/virtual-device-common/virtual-device-app.matter +++ b/examples/virtual-device-app/virtual-device-common/virtual-device-app.matter @@ -2939,6 +2939,7 @@ cluster DoorLock = 257 { nullable fabric_idx creatorFabricIndex = 2; nullable fabric_idx lastModifiedFabricIndex = 3; nullable int16u nextCredentialIndex = 4; + optional nullable octet_string credentialData = 5; } request struct ClearCredentialRequest { diff --git a/src/app/clusters/door-lock-server/door-lock-server.cpp b/src/app/clusters/door-lock-server/door-lock-server.cpp index 3842130aa356f1..43a044d0c4b9ec 100644 --- a/src/app/clusters/door-lock-server/door-lock-server.cpp +++ b/src/app/clusters/door-lock-server/door-lock-server.cpp @@ -900,6 +900,21 @@ void DoorLockServer::getCredentialStatusCommandHandler(chip::app::CommandHandler credentialExists); } +namespace { +bool IsAliroCredentialType(CredentialTypeEnum credentialType) +{ + switch (credentialType) + { + case CredentialTypeEnum::kAliroCredentialIssuerKey: + case CredentialTypeEnum::kAliroEvictableEndpointKey: + case CredentialTypeEnum::kAliroNonEvictableEndpointKey: + return true; + default: + return false; + } +} +} // anonymous namespace + void DoorLockServer::sendGetCredentialResponse(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, CredentialTypeEnum credentialType, uint16_t credentialIndex, @@ -921,10 +936,18 @@ void DoorLockServer::sendGetCredentialResponse(chip::app::CommandHandler * comma { response.lastModifiedFabricIndex.SetNonNull(credentialInfo->lastModifiedBy); } + if (IsAliroCredentialType(credentialType)) + { + response.credentialData.Emplace(credentialInfo->credentialData); + } } else { response.userIndex.SetNull(); + if (IsAliroCredentialType(credentialType)) + { + response.credentialData.Emplace(NullNullable); + } } uint16_t nextCredentialIndex = 0; if (findOccupiedCredentialSlot(commandPath.mEndpointId, credentialType, static_cast(credentialIndex + 1), diff --git a/src/app/zap-templates/zcl/data-model/chip/door-lock-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/door-lock-cluster.xml index 8ebb31df118d92..b25cd549d90091 100644 --- a/src/app/zap-templates/zcl/data-model/chip/door-lock-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/door-lock-cluster.xml @@ -491,6 +491,7 @@ limitations under the License. + diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index 1ba56719ab4549..6c7748e0898737 100644 --- a/src/controller/data_model/controller-clusters.matter +++ b/src/controller/data_model/controller-clusters.matter @@ -6263,6 +6263,7 @@ cluster DoorLock = 257 { nullable fabric_idx creatorFabricIndex = 2; nullable fabric_idx lastModifiedFabricIndex = 3; nullable int16u nextCredentialIndex = 4; + optional nullable octet_string credentialData = 5; } request struct ClearCredentialRequest { diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java index 2ce04c328ded6f..bb92218a4b4b59 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java @@ -35125,6 +35125,8 @@ public void onResponse(StructType invokeStructValue) { @Nullable Integer lastModifiedFabricIndex = null; final long nextCredentialIndexFieldID = 4L; @Nullable Integer nextCredentialIndex = null; + final long credentialDataFieldID = 5L; + @Nullable Optional credentialData = null; for (StructElement element: invokeStructValue.value()) { if (element.contextTagNum() == credentialExistsFieldID) { if (element.value(BaseTLVType.class).type() == TLVType.Boolean) { @@ -35151,9 +35153,14 @@ public void onResponse(StructType invokeStructValue) { UIntType castingValue = element.value(UIntType.class); nextCredentialIndex = castingValue.value(Integer.class); } + } else if (element.contextTagNum() == credentialDataFieldID) { + if (element.value(BaseTLVType.class).type() == TLVType.ByteArray) { + ByteArrayType castingValue = element.value(ByteArrayType.class); + credentialData = Optional.of(castingValue.value(byte[].class)); + } } } - callback.onSuccess(credentialExists, userIndex, creatorFabricIndex, lastModifiedFabricIndex, nextCredentialIndex); + callback.onSuccess(credentialExists, userIndex, creatorFabricIndex, lastModifiedFabricIndex, nextCredentialIndex, credentialData); }}, commandId, commandArgs, timedInvokeTimeoutMs); } @@ -35254,7 +35261,7 @@ public interface SetCredentialResponseCallback extends BaseClusterCallback { } public interface GetCredentialStatusResponseCallback extends BaseClusterCallback { - void onSuccess(Boolean credentialExists, @Nullable Integer userIndex, @Nullable Integer creatorFabricIndex, @Nullable Integer lastModifiedFabricIndex, @Nullable Integer nextCredentialIndex); + void onSuccess(Boolean credentialExists, @Nullable Integer userIndex, @Nullable Integer creatorFabricIndex, @Nullable Integer lastModifiedFabricIndex, @Nullable Integer nextCredentialIndex, @Nullable Optional credentialData); } public interface LockStateAttributeCallback extends BaseAttributeCallback { diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java index 40427e62794337..d10ce6b823d8d4 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java @@ -12382,7 +12382,7 @@ public void setCallbackDelegate(ClusterCommandCallback callback) { } @Override - public void onSuccess(Boolean credentialExists, @Nullable Integer userIndex, @Nullable Integer creatorFabricIndex, @Nullable Integer lastModifiedFabricIndex, @Nullable Integer nextCredentialIndex) { + public void onSuccess(Boolean credentialExists, @Nullable Integer userIndex, @Nullable Integer creatorFabricIndex, @Nullable Integer lastModifiedFabricIndex, @Nullable Integer nextCredentialIndex, @Nullable Optional credentialData) { Map responseValues = new LinkedHashMap<>(); CommandResponseInfo credentialExistsResponseValue = new CommandResponseInfo("credentialExists", "Boolean"); @@ -12395,6 +12395,8 @@ public void onSuccess(Boolean credentialExists, @Nullable Integer userIndex, @Nu responseValues.put(lastModifiedFabricIndexResponseValue, lastModifiedFabricIndex); CommandResponseInfo nextCredentialIndexResponseValue = new CommandResponseInfo("nextCredentialIndex", "Integer"); responseValues.put(nextCredentialIndexResponseValue, nextCredentialIndex); + CommandResponseInfo credentialDataResponseValue = new CommandResponseInfo("credentialData", "Optional"); + responseValues.put(credentialDataResponseValue, credentialData); callback.onSuccess(responseValues); } diff --git a/src/controller/java/generated/java/matter/controller/cluster/clusters/DoorLockCluster.kt b/src/controller/java/generated/java/matter/controller/cluster/clusters/DoorLockCluster.kt index ff0525a58d8c27..ad44768f35c71f 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/clusters/DoorLockCluster.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/clusters/DoorLockCluster.kt @@ -99,6 +99,7 @@ class DoorLockCluster(private val controller: MatterController, private val endp val creatorFabricIndex: UByte?, val lastModifiedFabricIndex: UByte?, val nextCredentialIndex: UShort?, + val credentialData: ByteArray?, ) class LockStateAttribute(val value: UByte?) @@ -1320,6 +1321,9 @@ class DoorLockCluster(private val controller: MatterController, private val endp val TAG_NEXT_CREDENTIAL_INDEX: Int = 4 var nextCredentialIndex_decoded: UShort? = null + val TAG_CREDENTIAL_DATA: Int = 5 + var credentialData_decoded: ByteArray? = null + while (!tlvReader.isEndOfContainer()) { val tag = tlvReader.peekElement().tag @@ -1385,6 +1389,25 @@ class DoorLockCluster(private val controller: MatterController, private val endp null } } + } + + if (tag == ContextSpecificTag(TAG_CREDENTIAL_DATA)) { + credentialData_decoded = + if (tlvReader.isNull()) { + tlvReader.getNull(tag) + null + } else { + if (!tlvReader.isNull()) { + if (tlvReader.isNextTag(tag)) { + tlvReader.getByteArray(tag) + } else { + null + } + } else { + tlvReader.getNull(tag) + null + } + } } else { tlvReader.skipElement() } @@ -1402,6 +1425,7 @@ class DoorLockCluster(private val controller: MatterController, private val endp creatorFabricIndex_decoded, lastModifiedFabricIndex_decoded, nextCredentialIndex_decoded, + credentialData_decoded, ) } diff --git a/src/controller/python/chip/clusters/Objects.py b/src/controller/python/chip/clusters/Objects.py index efefaf9059dd7f..6a9e0b8416fd5a 100644 --- a/src/controller/python/chip/clusters/Objects.py +++ b/src/controller/python/chip/clusters/Objects.py @@ -28861,6 +28861,7 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="creatorFabricIndex", Tag=2, Type=typing.Union[Nullable, uint]), ClusterObjectFieldDescriptor(Label="lastModifiedFabricIndex", Tag=3, Type=typing.Union[Nullable, uint]), ClusterObjectFieldDescriptor(Label="nextCredentialIndex", Tag=4, Type=typing.Union[Nullable, uint]), + ClusterObjectFieldDescriptor(Label="credentialData", Tag=5, Type=typing.Union[None, Nullable, bytes]), ]) credentialExists: 'bool' = False @@ -28868,6 +28869,7 @@ def descriptor(cls) -> ClusterObjectDescriptor: creatorFabricIndex: 'typing.Union[Nullable, uint]' = NullValue lastModifiedFabricIndex: 'typing.Union[Nullable, uint]' = NullValue nextCredentialIndex: 'typing.Union[Nullable, uint]' = NullValue + credentialData: 'typing.Union[None, Nullable, bytes]' = None @dataclass class ClearCredential(ClusterCommand): diff --git a/src/darwin/Framework/CHIP/templates/availability.yaml b/src/darwin/Framework/CHIP/templates/availability.yaml index 12458cdaec950d..3f65e9facfd3f1 100644 --- a/src/darwin/Framework/CHIP/templates/availability.yaml +++ b/src/darwin/Framework/CHIP/templates/availability.yaml @@ -9803,6 +9803,10 @@ - GlobalEchoResponse - StringEchoRequest - StringEchoResponse + command fields: + DoorLock: + GetCredentialStatusResponse: + - credentialData structs: AccessControl: # Targeting 1.4 diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h index 48e7175fa2c58b..7135f3d88d8357 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h @@ -7212,6 +7212,8 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) @property (nonatomic, copy) NSNumber * _Nullable lastModifiedFabricIndex MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)); @property (nonatomic, copy) NSNumber * _Nullable nextCredentialIndex MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)); + +@property (nonatomic, copy) NSData * _Nullable credentialData MTR_PROVISIONALLY_AVAILABLE; /** * Controls whether the command is a timed command (using Timed Invoke). * diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm index ce78c58b074d32..ec90ce4d023543 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm @@ -20631,6 +20631,8 @@ - (instancetype)init _lastModifiedFabricIndex = nil; _nextCredentialIndex = nil; + + _credentialData = nil; _timedInvokeTimeoutMs = nil; } return self; @@ -20645,6 +20647,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; other.creatorFabricIndex = self.creatorFabricIndex; other.lastModifiedFabricIndex = self.lastModifiedFabricIndex; other.nextCredentialIndex = self.nextCredentialIndex; + other.credentialData = self.credentialData; other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; return other; @@ -20652,7 +20655,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: credentialExists:%@; userIndex:%@; creatorFabricIndex:%@; lastModifiedFabricIndex:%@; nextCredentialIndex:%@; >", NSStringFromClass([self class]), _credentialExists, _userIndex, _creatorFabricIndex, _lastModifiedFabricIndex, _nextCredentialIndex]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: credentialExists:%@; userIndex:%@; creatorFabricIndex:%@; lastModifiedFabricIndex:%@; nextCredentialIndex:%@; credentialData:%@; >", NSStringFromClass([self class]), _credentialExists, _userIndex, _creatorFabricIndex, _lastModifiedFabricIndex, _nextCredentialIndex, [_credentialData base64EncodedStringWithOptions:0]]; return descriptionString; } @@ -20733,6 +20736,17 @@ - (CHIP_ERROR)_setFieldsFromDecodableStruct:(const chip::app::Clusters::DoorLock self.nextCredentialIndex = [NSNumber numberWithUnsignedShort:decodableStruct.nextCredentialIndex.Value()]; } } + { + if (decodableStruct.credentialData.HasValue()) { + if (decodableStruct.credentialData.Value().IsNull()) { + self.credentialData = nil; + } else { + self.credentialData = AsData(decodableStruct.credentialData.Value().Value()); + } + } else { + self.credentialData = nil; + } + } return CHIP_NO_ERROR; } diff --git a/src/platform/nxp/common/ConnectivityManagerImpl.cpp b/src/platform/nxp/common/ConnectivityManagerImpl.cpp index 09d716ac6ea77f..3473fc7515e640 100644 --- a/src/platform/nxp/common/ConnectivityManagerImpl.cpp +++ b/src/platform/nxp/common/ConnectivityManagerImpl.cpp @@ -95,10 +95,6 @@ CHIP_ERROR ConnectivityManagerImpl::_Init() GenericConnectivityManagerImpl_Thread::_Init(); #endif -#if CHIP_DEVICE_CONFIG_ENABLE_WPA - StartWiFiManagement(); -#endif - SuccessOrExit(err); exit: @@ -614,6 +610,11 @@ CHIP_ERROR ConnectivityManagerImpl::ProvisionWiFiNetwork(const char * ssid, uint VerifyOrExit(ssidLen <= IEEEtypes_SSID_SIZE, ret = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(mWiFiStationState != kWiFiStationState_Connecting, ret = CHIP_ERROR_BUSY); + // Need to enable the WIFI interface here when Thread is enabled as a secondary network interface. We don't want to enable + // WIFI from the init phase anymore and we will only do it in case the commissioner is provisioning the device with + // the WIFI credentials. + StartWiFiManagement(); + memset(pNetworkData, 0, sizeof(struct wlan_network)); if (ssidLen < WLAN_NETWORK_NAME_MAX_LENGTH) diff --git a/src/platform/nxp/common/DnssdImpl.cpp b/src/platform/nxp/common/DnssdImpl.cpp index d0069cebcf1c4a..439327017897b2 100644 --- a/src/platform/nxp/common/DnssdImpl.cpp +++ b/src/platform/nxp/common/DnssdImpl.cpp @@ -1,6 +1,7 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2024 Project CHIP Authors + * Copyright 2024 NXP * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,922 +17,118 @@ */ #include "lib/dnssd/platform/Dnssd.h" -#include -#include -#include -#include -#include +#include "platform/CHIPDeviceLayer.h" -#include +#include +#include +#include -#include -#include +#include +#include using namespace ::chip::DeviceLayer; -using namespace chip::DeviceLayer::Internal; namespace chip { namespace Dnssd { -#define USE_MDNS_NEXT_SERVICE_API 1 - -// Support both operational and commissionable discovery, so buffers sizes must be worst case. -static constexpr uint8_t kMaxMdnsServiceTxtEntriesNumber = - std::max(Dnssd::CommissionAdvertisingParameters::kTxtMaxNumber, Dnssd::OperationalAdvertisingParameters::kTxtMaxNumber); -static constexpr size_t kTotalMdnsServiceTxtValueSize = std::max(Dnssd::CommissionAdvertisingParameters::kTxtTotalValueSize, - Dnssd::OperationalAdvertisingParameters::kTxtTotalValueSize); -static constexpr size_t kTotalMdnsServiceTxtKeySize = - std::max(Dnssd::CommissionAdvertisingParameters::kTxtTotalKeySize, Dnssd::OperationalAdvertisingParameters::kTxtTotalKeySize); - -static constexpr size_t kTotalMdnsServiceTxtBufferSize = - kTotalMdnsServiceTxtKeySize + kMaxMdnsServiceTxtEntriesNumber + kTotalMdnsServiceTxtValueSize; - -// For each fabric we can register one _matter._tcp and one _matterc._udp service -static constexpr uint32_t kServiceListSize = CHIP_CONFIG_MAX_FABRICS * 2; - -static const char * GetProtocolString(DnssdServiceProtocol protocol) -{ - return protocol == DnssdServiceProtocol::kDnssdProtocolUdp ? "_udp" : "_tcp"; -} - -struct DnsServiceTxtEntries -{ - uint8_t mBuffer[kTotalMdnsServiceTxtBufferSize]; - Dnssd::TextEntry mTxtEntries[kMaxMdnsServiceTxtEntriesNumber]; -}; - -struct mDnsQueryCtx -{ - void * matterCtx; - chip::Dnssd::DnssdService mMdnsService; - DnsServiceTxtEntries mServiceTxtEntry; - char mServiceType[chip::Dnssd::kDnssdTypeAndProtocolMaxSize + 1]; - CHIP_ERROR error; - union - { - otMdnsBrowser mBrowseInfo; - otMdnsSrvResolver mSrvInfo; - otMdnsTxtResolver mTxtInfo; - otMdnsAddressResolver mAddrInfo; - }; - union - { - DnsBrowseCallback mDnsBrowseCallback; - DnsResolveCallback mDnsResolveCallback; - }; - - mDnsQueryCtx(void * context, DnsBrowseCallback aBrowseCallback) - { - matterCtx = context; - mDnsBrowseCallback = aBrowseCallback; - error = CHIP_NO_ERROR; - } - mDnsQueryCtx(void * context, DnsResolveCallback aResolveCallback) - { - matterCtx = context; - mDnsResolveCallback = aResolveCallback; - error = CHIP_NO_ERROR; - } -}; - -enum ResolveStep : uint8_t -{ - kResolveStepSrv = 0, - kResolveStepTxt, - kResolveStepIpAddr, -}; - -static const char * GetProtocolString(DnssdServiceProtocol protocol); - -static void OtBrowseCallback(otInstance * aInstance, const otMdnsBrowseResult * aResult); -static void OtServiceCallback(otInstance * aInstance, const otMdnsSrvResult * aResult); -static void OtTxtCallback(otInstance * aInstance, const otMdnsTxtResult * aResult); -static void OtAddressCallback(otInstance * aInstance, const otMdnsAddressResult * aResult); - -static void DispatchBrowseEmpty(intptr_t context); -static void DispatchBrowse(intptr_t context); - -static void DispatchTxtResolve(intptr_t context); -static void DispatchAddressResolve(intptr_t context); -static void DispatchResolve(intptr_t context); -static void DispatchResolveError(intptr_t context); - -static void HandleResolveCleanup(mDnsQueryCtx & resolveContext, ResolveStep stepType); - -static CHIP_ERROR ResolveBySrp(otInstance * thrInstancePtr, char * serviceName, mDnsQueryCtx * context, DnssdService * mdnsReq); -static CHIP_ERROR BrowseBySrp(otInstance * thrInstancePtr, char * serviceName, mDnsQueryCtx * context); -static CHIP_ERROR FromSrpCacheToMdnsData(const otSrpServerService * service, const otSrpServerHost * host, - const DnssdService * mdnsQueryReq, chip::Dnssd::DnssdService & mdnsService, - DnsServiceTxtEntries & serviceTxtEntries); - -static CHIP_ERROR FromServiceTypeToMdnsData(chip::Dnssd::DnssdService & mdnsService, const char * aServiceType); - -static bool bBrowseInProgress = false; -// ID 0 is reserved for host -static uint32_t mRegisterServiceId = 1; -static uint8_t mNetifIndex = 0; - -// Matter currently only supports one browse and resolve operation at a time so there is no need to create a list -// If the Matter implementation evolves in the future this functionality can be extended to a list. -static mDnsQueryCtx * mBrowseContext = nullptr; -static mDnsQueryCtx * mResolveContext = nullptr; - -#if USE_MDNS_NEXT_SERVICE_API -static otMdnsService * mServiceList[kServiceListSize]; -static uint32_t mServiceListFreeIndex; -#endif - CHIP_ERROR ChipDnssdInit(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context) { - CHIP_ERROR error = CHIP_NO_ERROR; - otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); - struct netif * extNetif = (ConnectivityManagerImpl().GetExternalInterface()).GetPlatformInterface(); + NxpChipDnssdInit(initCallback, errorCallback, context); + OpenThreadDnssdInit(initCallback, errorCallback, context); - // Don't try to do anything until the mDNS server is started - VerifyOrExit(otMdnsIsEnabled(thrInstancePtr), error = CHIP_ERROR_INCORRECT_STATE); - - mNetifIndex = netif_get_index(extNetif); - -exit: - initCallback(context, error); - return error; + return CHIP_NO_ERROR; } void ChipDnssdShutdown() { - otMdnsSetEnabled(ThreadStackMgrImpl().OTInstance(), false, 0); + NxpChipDnssdShutdown(); } -#if USE_MDNS_NEXT_SERVICE_API -CHIP_ERROR ChipDnssdRemoveServices() -{ - otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); - otMdnsService otServiceData = { 0 }; - otMdnsIterator * iterator = nullptr; - ChipError error = CHIP_NO_ERROR; - otError otError = OT_ERROR_NONE; - otMdnsEntryState state; - - const char * hostName = ConnectivityManagerImpl().GetHostName(); - - iterator = otMdnsAllocateIterator(thrInstancePtr); - VerifyOrExit(iterator != nullptr, error = CHIP_ERROR_NO_MEMORY); - - mServiceListFreeIndex = 0; - - while (mServiceListFreeIndex <= kServiceListSize) - { - // allocate memory for new entry if the entry is not allready allocated from previous iteration - if (mServiceList[mServiceListFreeIndex] == nullptr) - { - mServiceList[mServiceListFreeIndex] = static_cast(Platform::MemoryAlloc(sizeof(otMdnsService))); - VerifyOrExit(mServiceList[mServiceListFreeIndex] != nullptr, error = CHIP_ERROR_NO_MEMORY); - } - - otError = otMdnsGetNextService(thrInstancePtr, iterator, mServiceList[mServiceListFreeIndex], &state); - if (otError == OT_ERROR_NOT_FOUND) - { - Platform::MemoryFree(mServiceList[mServiceListFreeIndex]); - mServiceList[mServiceListFreeIndex] = nullptr; - break; - } - - if ((0 == strcmp(mServiceList[mServiceListFreeIndex]->mHostName, hostName)) && - ((0 == strcmp(mServiceList[mServiceListFreeIndex]->mServiceType, "_matter._tcp")) || - (0 == strcmp(mServiceList[mServiceListFreeIndex]->mServiceType, "_matterc._udp")))) - { - mServiceListFreeIndex++; - } - } - -exit: - if (iterator != nullptr) - { - otMdnsFreeIterator(thrInstancePtr, iterator); - } - return error; -} -#else -CHIP_ERROR ChipDnssdRemoveServices() -{ - otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); - otMdnsService otServiceData = { 0 }; - - otServiceData.mHostName = ConnectivityManagerImpl().GetHostName(); - - otServiceData.mServiceType = "_matter._tcp"; - otMdnsUnregisterServiceType(thrInstancePtr, &otServiceData, OT_MDNS_SERVICE_MARK_FOR_UNREGISTER); - otServiceData.mServiceType = "_matterc._udp"; - otMdnsUnregisterServiceType(thrInstancePtr, &otServiceData, OT_MDNS_SERVICE_MARK_FOR_UNREGISTER); - - return CHIP_NO_ERROR; -} -#endif CHIP_ERROR ChipDnssdPublishService(const DnssdService * service, DnssdPublishCallback callback, void * context) { - ReturnErrorCodeIf(service == nullptr, CHIP_ERROR_INVALID_ARGUMENT); - - otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); - uint32_t txtBufferOffset = 0; - otError otErr = OT_ERROR_NONE; - otMdnsService otServiceData = { 0 }; - -#if USE_MDNS_NEXT_SERVICE_API - bool bRegisterService = true; -#endif - - char serviceType[chip::Dnssd::kDnssdTypeAndProtocolMaxSize + 1] = ""; - snprintf(serviceType, sizeof(serviceType), "%s.%s", service->mType, GetProtocolString(service->mProtocol)); - - // secure space for the raw TXT data in the worst-case scenario relevant for Matter: - // each entry consists of txt_entry_size (1B) + txt_entry_key + "=" + txt_entry_data - uint8_t txtBuffer[kMaxMdnsServiceTxtEntriesNumber + kTotalMdnsServiceTxtBufferSize] = { 0 }; - - // Don't try to do anything until the mDNS server is started - VerifyOrReturnValue(otMdnsIsEnabled(thrInstancePtr), CHIP_NO_ERROR); - - // Create TXT Data as one string from multiple key entries - for (uint32_t i = 0; i < service->mTextEntrySize; i++) + if (ConnectivityMgr().IsWiFiStationConnected()) { - uint32_t keySize = strlen(service->mTextEntries[i].mKey); - // add TXT entry len, + 1 is for '=' - *(txtBuffer + txtBufferOffset++) = keySize + service->mTextEntries[i].mDataSize + 1; - - // add TXT entry key - memcpy(txtBuffer + txtBufferOffset, service->mTextEntries[i].mKey, keySize); - txtBufferOffset += keySize; - - // add TXT entry value if pointer is not null, if pointer is null it means we have bool value - if (service->mTextEntries[i].mData) - { - *(txtBuffer + txtBufferOffset++) = '='; - memcpy(txtBuffer + txtBufferOffset, service->mTextEntries[i].mData, service->mTextEntries[i].mDataSize); - txtBufferOffset += service->mTextEntries[i].mDataSize; - } - } - -#if USE_MDNS_NEXT_SERVICE_API - for (uint32_t i = 0; i < mServiceListFreeIndex; i++) - { - if ((0 == strcmp(mServiceList[i]->mHostName, service->mHostName)) && - (0 == strcmp(mServiceList[i]->mServiceInstance, service->mName)) && - (0 == strcmp(mServiceList[i]->mServiceType, serviceType))) - { - if ((mServiceList[i]->mTxtDataLength == txtBufferOffset) && - (0 == memcmp(txtBuffer, mServiceList[i]->mTxtData, txtBufferOffset))) - { - // In this case the service is - bRegisterService = false; - } - Platform::MemoryFree(mServiceList[i]); - if (i < --mServiceListFreeIndex) - { - // move last element in place of the removed one - mServiceList[i] = mServiceList[mServiceListFreeIndex]; - mServiceList[mServiceListFreeIndex] = nullptr; - } - else - { - mServiceList[i] = nullptr; - } - break; - } - } -#endif - if (bRegisterService) - { - if (strcmp(service->mHostName, "") != 0) - { - otServiceData.mHostName = service->mHostName; - } - - otServiceData.mServiceInstance = service->mName; - otServiceData.mServiceType = serviceType; - otServiceData.mSubTypeLabels = service->mSubTypes; - otServiceData.mSubTypeLabelsLength = service->mSubTypeSize; - otServiceData.mPort = service->mPort; - otServiceData.mTtl = service->mTtlSeconds; - otServiceData.mTxtData = txtBuffer; - otServiceData.mTxtDataLength = txtBufferOffset; - - otErr = otMdnsRegisterService(thrInstancePtr, &otServiceData, mRegisterServiceId++, NULL); + ReturnErrorOnFailure(NxpChipDnssdPublishService(service, callback, context)); } - - return MapOpenThreadError(otErr); -} - -#if USE_MDNS_NEXT_SERVICE_API -CHIP_ERROR ChipDnssdFinalizeServiceUpdate() -{ - otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); - - for (uint32_t i = 0; i < mServiceListFreeIndex; i++) + else if (ConnectivityMgr().IsThreadProvisioned()) { - if (mServiceList[i] != nullptr) - { - otMdnsUnregisterService(thrInstancePtr, mServiceList[i]); - Platform::MemoryFree(mServiceList[i]); - mServiceList[i] = nullptr; - } + ReturnErrorOnFailure(OpenThreadDnssdPublishService(service, callback, context)); } - mServiceListFreeIndex = 0; return CHIP_NO_ERROR; } -#else -CHIP_ERROR ChipDnssdFinalizeServiceUpdate() -{ - otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); - otMdnsService otServiceData = { 0 }; - - otServiceData.mHostName = ConnectivityManagerImpl().GetHostName(); - - otServiceData.mServiceType = "_matter._tcp"; - otMdnsUnregisterServiceType(thrInstancePtr, &otServiceData, OT_MDNS_SERVICE_UNREGISTER_MARKED_SERVICE); - otServiceData.mServiceType = "_matterc._udp"; - otMdnsUnregisterServiceType(thrInstancePtr, &otServiceData, OT_MDNS_SERVICE_UNREGISTER_MARKED_SERVICE); - - return CHIP_NO_ERROR; -} -#endif - -CHIP_ERROR ChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, Inet::IPAddressType addressType, - Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context, intptr_t * browseIdentifier) -{ - *browseIdentifier = reinterpret_cast(nullptr); - CHIP_ERROR error = CHIP_NO_ERROR; - CHIP_ERROR srpBrowseError = CHIP_NO_ERROR; - otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); - - if (type == nullptr || callback == nullptr) - return CHIP_ERROR_INVALID_ARGUMENT; - - mBrowseContext = Platform::New(context, callback); - VerifyOrReturnError(mBrowseContext != nullptr, CHIP_ERROR_NO_MEMORY); - - // First try to browse the service in the SRP cache - snprintf(mBrowseContext->mServiceType, sizeof(mBrowseContext->mServiceType), "%s.%s", type, GetProtocolString(protocol)); - // After browsing in the SRP cache we will continue with regular mDNS browse - srpBrowseError = BrowseBySrp(thrInstancePtr, mBrowseContext->mServiceType, mBrowseContext); - - // Proceed to generate a mDNS query - mBrowseContext->mBrowseInfo.mServiceType = mBrowseContext->mServiceType; - mBrowseContext->mBrowseInfo.mSubTypeLabel = nullptr; - mBrowseContext->mBrowseInfo.mInfraIfIndex = mNetifIndex; - mBrowseContext->mBrowseInfo.mCallback = OtBrowseCallback; - - error = MapOpenThreadError(otMdnsStartBrowser(thrInstancePtr, &mBrowseContext->mBrowseInfo)); - - if (CHIP_NO_ERROR == error) - { - bBrowseInProgress = true; - *browseIdentifier = reinterpret_cast(mBrowseContext); - } - else - { - if (srpBrowseError == CHIP_NO_ERROR) - { - // In this case, we need to send a final browse indication to signal the Matter App that there are no more - // browse results coming - mBrowseContext->error = error; - DeviceLayer::PlatformMgr().ScheduleWork(DispatchBrowseEmpty, reinterpret_cast(mBrowseContext)); - } - else - { - Platform::Delete(mBrowseContext); - mBrowseContext = nullptr; - } - } - return error; -} - -CHIP_ERROR ChipDnssdStopBrowse(intptr_t browseIdentifier) -{ - mDnsQueryCtx * browseContext = reinterpret_cast(browseIdentifier); - otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); - otError error = OT_ERROR_INVALID_ARGS; - - // browseContext is only valid when bBrowseInProgress is true. The Matter stack can call this function even with a browseContext - // that has been freed in DispatchBrowseEmpty. - if ((true == bBrowseInProgress) && (browseContext)) - { - browseContext->error = MapOpenThreadError(otMdnsStopBrowser(thrInstancePtr, &browseContext->mBrowseInfo)); - - // browse context will be freed in DispatchBrowseEmpty - DispatchBrowseEmpty(reinterpret_cast(browseContext)); - } - return MapOpenThreadError(error); -} - -CHIP_ERROR ChipDnssdResolve(DnssdService * browseResult, Inet::InterfaceId interface, DnssdResolveCallback callback, void * context) -{ - ChipError error = CHIP_ERROR_NOT_FOUND; - - if (browseResult == nullptr || callback == nullptr) - return CHIP_ERROR_INVALID_ARGUMENT; - - otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); - - mResolveContext = Platform::New(context, callback); - VerifyOrReturnError(mResolveContext != nullptr, CHIP_ERROR_NO_MEMORY); - - // First try to find the service in the SRP cache, use default.service.arpa as domain name - snprintf(mResolveContext->mServiceType, sizeof(mResolveContext->mServiceType), "%s.%s", browseResult->mType, - GetProtocolString(browseResult->mProtocol)); - - error = ResolveBySrp(thrInstancePtr, mResolveContext->mServiceType, mResolveContext, browseResult); - // If the SRP cache returns not found, proceed to generate a MDNS query - if (CHIP_ERROR_NOT_FOUND == error) - { - // The otMdnsSrvResolver structure contains only pointers to instance name and service type strings - // Use the memory from mMdnsService.mName to store the instance name string we are looking for - Platform::CopyString(mResolveContext->mMdnsService.mName, sizeof(mResolveContext->mMdnsService.mName), browseResult->mName); - - mResolveContext->mSrvInfo.mInfraIfIndex = mNetifIndex; - mResolveContext->mSrvInfo.mCallback = OtServiceCallback; - mResolveContext->mSrvInfo.mServiceInstance = mResolveContext->mMdnsService.mName; - mResolveContext->mSrvInfo.mServiceType = mResolveContext->mServiceType; - - return MapOpenThreadError(otMdnsStartSrvResolver(thrInstancePtr, &mResolveContext->mSrvInfo)); - } - else - { - return error; - } -} -void ChipDnssdResolveNoLongerNeeded(const char * instanceName) -{ - if (mResolveContext != nullptr) - { - if (strcmp(instanceName, mResolveContext->mMdnsService.mName) == 0) - { - otMdnsStopSrvResolver(ThreadStackMgrImpl().OTInstance(), &mResolveContext->mSrvInfo); - - Platform::Delete(mResolveContext); - mResolveContext = nullptr; - } - } -} - -CHIP_ERROR ChipDnssdReconfirmRecord(const char * hostname, chip::Inet::IPAddress address, chip::Inet::InterfaceId interface) -{ - return CHIP_ERROR_NOT_IMPLEMENTED; -} - -CHIP_ERROR BrowseBySrp(otInstance * thrInstancePtr, char * serviceName, mDnsQueryCtx * context) -{ - const otSrpServerHost * host = nullptr; - const otSrpServerService * service = nullptr; - CHIP_ERROR error = CHIP_ERROR_NOT_FOUND; - - while ((host = otSrpServerGetNextHost(thrInstancePtr, host)) != nullptr) - { - while ((service = otSrpServerHostGetNextService(host, service)) != nullptr) - { - if ((false == otSrpServerServiceIsDeleted(service)) && - (0 == strncmp(otSrpServerServiceGetServiceName(service), serviceName, strlen(serviceName)))) - { - mDnsQueryCtx * serviceContext = Platform::New(context->matterCtx, context->mDnsBrowseCallback); - if (serviceContext != nullptr) - { - if (CHIP_NO_ERROR == - FromSrpCacheToMdnsData(service, host, nullptr, serviceContext->mMdnsService, - serviceContext->mServiceTxtEntry)) - { - // Set error to CHIP_NO_ERROR to signal that there was at least one service found in the cache - error = CHIP_NO_ERROR; - DeviceLayer::PlatformMgr().ScheduleWork(DispatchBrowse, reinterpret_cast(serviceContext)); - } - else - { - Platform::Delete(serviceContext); - } - } - } - } - } - return error; -} - -CHIP_ERROR ResolveBySrp(otInstance * thrInstancePtr, char * serviceName, mDnsQueryCtx * context, DnssdService * mdnsReq) -{ - const otSrpServerHost * host = nullptr; - const otSrpServerService * service = nullptr; - CHIP_ERROR error = CHIP_ERROR_NOT_FOUND; - - while ((host = otSrpServerGetNextHost(thrInstancePtr, host)) != nullptr) - { - while ((service = otSrpServerHostGetNextService(host, service)) != nullptr) - { - if ((false == otSrpServerServiceIsDeleted(service)) && - (0 == strncmp(otSrpServerServiceGetServiceName(service), serviceName, strlen(serviceName))) && - (0 == strncmp(otSrpServerServiceGetInstanceName(service), mdnsReq->mName, strlen(mdnsReq->mName)))) - { - error = FromSrpCacheToMdnsData(service, host, mdnsReq, context->mMdnsService, context->mServiceTxtEntry); - if (error == CHIP_NO_ERROR) - { - DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolve, reinterpret_cast(context)); - } - break; - } - } - - if (error == CHIP_NO_ERROR) - { - break; - } - } - - return error; -} - -CHIP_ERROR FromSrpCacheToMdnsData(const otSrpServerService * service, const otSrpServerHost * host, - const DnssdService * mdnsQueryReq, chip::Dnssd::DnssdService & mdnsService, - DnsServiceTxtEntries & serviceTxtEntries) +CHIP_ERROR ChipDnssdRemoveServices() { - const char * tmpName; - const uint8_t * txtStringPtr; - size_t substringSize; - uint8_t addrNum = 0; - uint16_t txtDataLen; - const otIp6Address * ip6AddrPtr = otSrpServerHostGetAddresses(host, &addrNum); - - if (mdnsQueryReq != nullptr) - { - Platform::CopyString(mdnsService.mName, sizeof(mdnsService.mName), mdnsQueryReq->mName); - Platform::CopyString(mdnsService.mType, sizeof(mdnsService.mType), mdnsQueryReq->mType); - mdnsService.mProtocol = mdnsQueryReq->mProtocol; - } - else + if (ConnectivityMgr().IsWiFiStationConnected()) { - tmpName = otSrpServerServiceGetInstanceName(service); - // Extract from the .... the part - size_t substringSize = strchr(tmpName, '.') - tmpName; - if (substringSize >= ArraySize(mdnsService.mName)) - { - return CHIP_ERROR_INVALID_ARGUMENT; - } - Platform::CopyString(mdnsService.mName, substringSize + 1, tmpName); - - // Extract from the .... the part. - tmpName = tmpName + substringSize + 1; - substringSize = strchr(tmpName, '.') - tmpName; - if (substringSize >= ArraySize(mdnsService.mType)) - { - return CHIP_ERROR_INVALID_ARGUMENT; - } - Platform::CopyString(mdnsService.mType, substringSize + 1, tmpName); - - // Extract from the .... the part. - tmpName = tmpName + substringSize + 1; - substringSize = strchr(tmpName, '.') - tmpName; - if (substringSize >= (chip::Dnssd::kDnssdProtocolTextMaxSize + 1)) - { - return CHIP_ERROR_INVALID_ARGUMENT; - } - if (strncmp(tmpName, "_udp", substringSize) == 0) - { - mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolUdp; - } - else if (strncmp(tmpName, "_tcp", substringSize) == 0) - { - mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolTcp; - } - else - { - mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolUnknown; - } + ReturnErrorOnFailure(NxpChipDnssdRemoveServices()); } - - // Extract from the .. the part. - tmpName = otSrpServerHostGetFullName(host); - substringSize = strchr(tmpName, '.') - tmpName; - if (substringSize >= ArraySize(mdnsService.mHostName)) + else if (ConnectivityMgr().IsThreadProvisioned()) { - return CHIP_ERROR_INVALID_ARGUMENT; + ReturnErrorOnFailure(OpenThreadDnssdRemoveServices()); } - Platform::CopyString(mdnsService.mHostName, substringSize + 1, tmpName); - mdnsService.mPort = otSrpServerServiceGetPort(service); - - // All SRP cache hits come from the Thread Netif - mdnsService.mInterface = ConnectivityManagerImpl().GetThreadInterface(); - - mdnsService.mAddressType = Inet::IPAddressType::kIPv6; - mdnsService.mAddress = std::optional(ToIPAddress(*ip6AddrPtr)); - - // Extract TXT record SRP service - txtStringPtr = otSrpServerServiceGetTxtData(service, &txtDataLen); - if (txtDataLen != 0) - { - otDnsTxtEntryIterator iterator; - otDnsInitTxtEntryIterator(&iterator, txtStringPtr, txtDataLen); - - otDnsTxtEntry txtEntry; - chip::FixedBufferAllocator alloc(serviceTxtEntries.mBuffer); - - uint8_t entryIndex = 0; - while ((otDnsGetNextTxtEntry(&iterator, &txtEntry) == OT_ERROR_NONE) && entryIndex < 64) - { - if (txtEntry.mKey == nullptr || txtEntry.mValue == nullptr) - continue; - - serviceTxtEntries.mTxtEntries[entryIndex].mKey = alloc.Clone(txtEntry.mKey); - serviceTxtEntries.mTxtEntries[entryIndex].mData = alloc.Clone(txtEntry.mValue, txtEntry.mValueLength); - serviceTxtEntries.mTxtEntries[entryIndex].mDataSize = txtEntry.mValueLength; - entryIndex++; - } - - ReturnErrorCodeIf(alloc.AnyAllocFailed(), CHIP_ERROR_BUFFER_TOO_SMALL); - - mdnsService.mTextEntries = serviceTxtEntries.mTxtEntries; - mdnsService.mTextEntrySize = entryIndex; - } - else - { - mdnsService.mTextEntrySize = 0; - } - - mdnsService.mSubTypes = nullptr; - mdnsService.mSubTypeSize = 0; return CHIP_NO_ERROR; } -static CHIP_ERROR FromServiceTypeToMdnsData(chip::Dnssd::DnssdService & mdnsService, const char * aServiceType) +CHIP_ERROR ChipDnssdFinalizeServiceUpdate() { - char protocol[chip::Dnssd::kDnssdProtocolTextMaxSize + 1]; - const char * protocolSubstringStart; - size_t substringSize; - - // Extract from the . the part. - substringSize = strchr(aServiceType, '.') - aServiceType; - if (substringSize >= ArraySize(mdnsService.mType)) - { - return CHIP_ERROR_INVALID_ARGUMENT; - } - Platform::CopyString(mdnsService.mType, ArraySize(mdnsService.mType), aServiceType); - - // Extract from the .. the . part. - protocolSubstringStart = aServiceType + substringSize; - - // Check that the protocolSubstringStart starts wit a '.' to be sure we are in the right place - if (strchr(protocolSubstringStart, '.') == nullptr) + if (ConnectivityMgr().IsWiFiStationConnected()) { - return CHIP_ERROR_INVALID_ARGUMENT; + ReturnErrorOnFailure(NxpChipDnssdFinalizeServiceUpdate()); } - - // Jump over '.' in protocolSubstringStart and substract the string terminator from the size - substringSize = strlen(++protocolSubstringStart) - 1; - if (substringSize >= ArraySize(protocol)) + else if (ConnectivityMgr().IsThreadProvisioned()) { - return CHIP_ERROR_INVALID_ARGUMENT; + ReturnErrorOnFailure(OpenThreadDnssdFinalizeServiceUpdate()); } - Platform::CopyString(protocol, ArraySize(protocol), protocolSubstringStart); - - if (strncmp(protocol, "_udp", chip::Dnssd::kDnssdProtocolTextMaxSize) == 0) - { - mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolUdp; - } - else if (strncmp(protocol, "_tcp", chip::Dnssd::kDnssdProtocolTextMaxSize) == 0) - { - mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolTcp; - } - else - { - mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolUnknown; - } - return CHIP_NO_ERROR; } -static void OtBrowseCallback(otInstance * aInstance, const otMdnsBrowseResult * aResult) +CHIP_ERROR ChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, chip::Inet::IPAddressType addressType, + chip::Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context, + intptr_t * browseIdentifier) { - CHIP_ERROR error; - - // Ingnore reponses with TTL 0, the record is no longer valid and was removed from the mDNS cache - VerifyOrReturn(aResult->mTtl > 0); - - mDnsQueryCtx * tmpContext = Platform::New(mBrowseContext->matterCtx, mBrowseContext->mDnsBrowseCallback); - VerifyOrReturn(tmpContext != nullptr); - - Platform::CopyString(tmpContext->mMdnsService.mName, sizeof(tmpContext->mMdnsService.mName), aResult->mServiceInstance); - error = FromServiceTypeToMdnsData(tmpContext->mMdnsService, aResult->mServiceType); - - if (CHIP_NO_ERROR == error) + if (ConnectivityMgr().IsWiFiStationConnected()) //|| ESP32Utils::HasIPv6LinkLocalAddress(ESP32Utils::kDefaultEthernetNetifKey)) { - DeviceLayer::PlatformMgr().ScheduleWork(DispatchBrowse, reinterpret_cast(tmpContext)); + ReturnErrorOnFailure(NxpChipDnssdBrowse(type, protocol, addressType, interface, callback, context, browseIdentifier)); } - else + else if (ConnectivityMgr().IsThreadProvisioned()) { - Platform::Delete(tmpContext); + ReturnErrorOnFailure(OpenThreadDnssdBrowse(type, protocol, addressType, interface, callback, context, browseIdentifier)); } -} - -static void OtServiceCallback(otInstance * aInstance, const otMdnsSrvResult * aResult) -{ - CHIP_ERROR error; - - // Ingnore reponses with TTL 0, the record is no longer valid and was removed from the mDNS cache - VerifyOrReturn(aResult->mTtl > 0); - VerifyOrReturn(mResolveContext != nullptr); - - error = FromServiceTypeToMdnsData(mResolveContext->mMdnsService, aResult->mServiceType); - mResolveContext->error = error; - - if (CHIP_NO_ERROR == error) - { - Platform::CopyString(mResolveContext->mMdnsService.mName, sizeof(mResolveContext->mMdnsService.mName), - aResult->mServiceInstance); - Platform::CopyString(mResolveContext->mMdnsService.mHostName, sizeof(mResolveContext->mMdnsService.mHostName), - aResult->mHostName); - - mResolveContext->mMdnsService.mPort = aResult->mPort; - mResolveContext->mMdnsService.mTtlSeconds = aResult->mTtl; - DeviceLayer::PlatformMgr().ScheduleWork(DispatchTxtResolve, reinterpret_cast(mResolveContext)); - } - else - { - HandleResolveCleanup(*mResolveContext, kResolveStepSrv); - } -} - -static void OtTxtCallback(otInstance * aInstance, const otMdnsTxtResult * aResult) -{ - bool bSendDispatch = true; - - // Ingnore reponses with TTL 0, the record is no longer valid and was removed from the mDNS cache - VerifyOrReturn(aResult->mTtl > 0); - - VerifyOrReturn(mResolveContext != nullptr); - - // Check if TXT record was included in the response. - if (aResult->mTxtDataLength != 0) - { - otDnsTxtEntryIterator iterator; - otDnsInitTxtEntryIterator(&iterator, aResult->mTxtData, aResult->mTxtDataLength); - - otDnsTxtEntry txtEntry; - chip::FixedBufferAllocator alloc(mResolveContext->mServiceTxtEntry.mBuffer); - - uint8_t entryIndex = 0; - while ((otDnsGetNextTxtEntry(&iterator, &txtEntry) == OT_ERROR_NONE) && entryIndex < 64) - { - if (txtEntry.mKey == nullptr || txtEntry.mValue == nullptr) - continue; - - mResolveContext->mServiceTxtEntry.mTxtEntries[entryIndex].mKey = alloc.Clone(txtEntry.mKey); - mResolveContext->mServiceTxtEntry.mTxtEntries[entryIndex].mData = alloc.Clone(txtEntry.mValue, txtEntry.mValueLength); - mResolveContext->mServiceTxtEntry.mTxtEntries[entryIndex].mDataSize = txtEntry.mValueLength; - entryIndex++; - } - - if (alloc.AnyAllocFailed()) - { - bSendDispatch = false; - } - else - { - mResolveContext->mMdnsService.mTextEntries = mResolveContext->mServiceTxtEntry.mTxtEntries; - mResolveContext->mMdnsService.mTextEntrySize = entryIndex; - } - } - else - { - mResolveContext->mMdnsService.mTextEntrySize = 0; - } - - if (bSendDispatch) - { - DeviceLayer::PlatformMgr().ScheduleWork(DispatchAddressResolve, reinterpret_cast(mResolveContext)); - } - else - { - HandleResolveCleanup(*mResolveContext, kResolveStepTxt); - } -} - -static void OtAddressCallback(otInstance * aInstance, const otMdnsAddressResult * aResult) -{ - // Ingnore reponses with TTL 0, the record is no longer valid and was removed from the mDNS cache - VerifyOrReturn((aResult->mAddressesLength > 0) && (aResult->mAddresses[0].mTtl > 0)); - - VerifyOrReturn(mResolveContext != nullptr); - - mResolveContext->mMdnsService.mAddressType = Inet::IPAddressType::kIPv6; - mResolveContext->mMdnsService.mAddress = std::optional(ToIPAddress(aResult->mAddresses[0].mAddress)); - - DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolve, reinterpret_cast(mResolveContext)); -} - -static void DispatchBrowseEmpty(intptr_t context) -{ - auto * browseContext = reinterpret_cast(context); - browseContext->mDnsBrowseCallback(browseContext->matterCtx, nullptr, 0, true, browseContext->error); - Platform::Delete(browseContext); - mBrowseContext = nullptr; - bBrowseInProgress = false; + return CHIP_NO_ERROR; } -static void DispatchBrowse(intptr_t context) +CHIP_ERROR ChipDnssdStopBrowse(intptr_t browseIdentifier) { - auto * browseContext = reinterpret_cast(context); - browseContext->mDnsBrowseCallback(browseContext->matterCtx, &browseContext->mMdnsService, 1, false, browseContext->error); - Platform::Delete(browseContext); + return NxpChipDnssdStopBrowse(browseIdentifier); } -static void DispatchTxtResolve(intptr_t context) +CHIP_ERROR ChipDnssdResolve(DnssdService * service, chip::Inet::InterfaceId interface, DnssdResolveCallback callback, + void * context) { - mDnsQueryCtx * resolveContext = reinterpret_cast(context); - otError error; - - // Stop SRV resolver before starting TXT one, ignore error as it will only happen if mMDS module is not initialized - otMdnsStopSrvResolver(ThreadStackMgrImpl().OTInstance(), &resolveContext->mSrvInfo); - - resolveContext->mTxtInfo.mServiceInstance = resolveContext->mMdnsService.mName; - resolveContext->mTxtInfo.mServiceType = resolveContext->mServiceType; - resolveContext->mTxtInfo.mCallback = OtTxtCallback; - resolveContext->mTxtInfo.mInfraIfIndex = mNetifIndex; - - error = otMdnsStartTxtResolver(ThreadStackMgrImpl().OTInstance(), &resolveContext->mTxtInfo); - if (error != OT_ERROR_NONE) + if (ConnectivityMgr().IsWiFiStationConnected()) //|| ESP32Utils::HasIPv6LinkLocalAddress(ESP32Utils::kDefaultEthernetNetifKey)) { - resolveContext->error = MapOpenThreadError(error); - DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolveError, reinterpret_cast(resolveContext)); + ReturnErrorOnFailure(NxpChipDnssdResolve(service, interface, callback, context)); } -} - -static void DispatchAddressResolve(intptr_t context) -{ - otError error; - mDnsQueryCtx * resolveContext = reinterpret_cast(context); - // Stop TXT resolver before starting address one, ignore error as it will only happen if mMDS module is not initialized - otMdnsStopTxtResolver(ThreadStackMgrImpl().OTInstance(), &resolveContext->mTxtInfo); - - resolveContext->mAddrInfo.mCallback = OtAddressCallback; - resolveContext->mAddrInfo.mHostName = resolveContext->mMdnsService.mHostName; - resolveContext->mAddrInfo.mInfraIfIndex = mNetifIndex; - - error = otMdnsStartIp6AddressResolver(ThreadStackMgrImpl().OTInstance(), &resolveContext->mAddrInfo); - if (error != OT_ERROR_NONE) + else if (ConnectivityMgr().IsThreadProvisioned()) { - resolveContext->error = MapOpenThreadError(error); - DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolveError, reinterpret_cast(resolveContext)); + ReturnErrorOnFailure(OpenThreadDnssdResolve(service, interface, callback, context)); } -} -static void DispatchResolve(intptr_t context) -{ - mDnsQueryCtx * resolveContext = reinterpret_cast(context); - Dnssd::DnssdService & service = resolveContext->mMdnsService; - Span ipAddrs; - - // Stop Address resolver, we have finished resolving the service - otMdnsStopIp6AddressResolver(ThreadStackMgrImpl().OTInstance(), &resolveContext->mAddrInfo); - - if (service.mAddress.has_value()) - { - ipAddrs = Span(&*service.mAddress, 1); - } - - // Signal that the context will be freed and that the resolve operation is stopped because Matter will - // try do stop it again on the mDnsResolveCallback - mResolveContext = nullptr; - - resolveContext->mDnsResolveCallback(resolveContext->matterCtx, &service, ipAddrs, resolveContext->error); - Platform::Delete(resolveContext); + return CHIP_NO_ERROR; } -static void DispatchResolveError(intptr_t context) +void ChipDnssdResolveNoLongerNeeded(const char * instanceName) { - mDnsQueryCtx * resolveContext = reinterpret_cast(context); - Span ipAddrs; - - // Signal that the context will be freed and that the resolve operation is stopped because Matter will - // try do stop it again on the mDnsResolveCallback - mResolveContext = nullptr; - - resolveContext->mDnsResolveCallback(resolveContext->matterCtx, nullptr, ipAddrs, resolveContext->error); - Platform::Delete(resolveContext); + NxpChipDnssdResolveNoLongerNeeded(instanceName); } -void HandleResolveCleanup(mDnsQueryCtx & resolveContext, ResolveStep stepType) +CHIP_ERROR ChipDnssdReconfirmRecord(const char * hostname, chip::Inet::IPAddress address, chip::Inet::InterfaceId interface) { - switch (stepType) - { - case kResolveStepSrv: - otMdnsStopSrvResolver(ThreadStackMgrImpl().OTInstance(), &resolveContext.mSrvInfo); - break; - case kResolveStepTxt: - otMdnsStopTxtResolver(ThreadStackMgrImpl().OTInstance(), &resolveContext.mTxtInfo); - break; - case kResolveStepIpAddr: - otMdnsStopIp6AddressResolver(ThreadStackMgrImpl().OTInstance(), &resolveContext.mAddrInfo); - break; - } - - DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolve, reinterpret_cast(&resolveContext)); + return CHIP_ERROR_NOT_IMPLEMENTED; } } // namespace Dnssd diff --git a/src/platform/nxp/common/DnssdImplBr.cpp b/src/platform/nxp/common/DnssdImplBr.cpp new file mode 100644 index 00000000000000..6b84f1f258d8be --- /dev/null +++ b/src/platform/nxp/common/DnssdImplBr.cpp @@ -0,0 +1,939 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * Copyright 2024 NXP + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lib/dnssd/platform/Dnssd.h" +#include +#include +#include +#include +#include + +#include + +#include +#include + +using namespace ::chip::DeviceLayer; +using namespace chip::DeviceLayer::Internal; + +namespace chip { +namespace Dnssd { + +#define USE_MDNS_NEXT_SERVICE_API 1 + +// Support both operational and commissionable discovery, so buffers sizes must be worst case. +static constexpr uint8_t kMaxMdnsServiceTxtEntriesNumber = + std::max(Dnssd::CommissionAdvertisingParameters::kTxtMaxNumber, Dnssd::OperationalAdvertisingParameters::kTxtMaxNumber); +static constexpr size_t kTotalMdnsServiceTxtValueSize = std::max(Dnssd::CommissionAdvertisingParameters::kTxtTotalValueSize, + Dnssd::OperationalAdvertisingParameters::kTxtTotalValueSize); +static constexpr size_t kTotalMdnsServiceTxtKeySize = + std::max(Dnssd::CommissionAdvertisingParameters::kTxtTotalKeySize, Dnssd::OperationalAdvertisingParameters::kTxtTotalKeySize); + +static constexpr size_t kTotalMdnsServiceTxtBufferSize = + kTotalMdnsServiceTxtKeySize + kMaxMdnsServiceTxtEntriesNumber + kTotalMdnsServiceTxtValueSize; + +// For each fabric we can register one _matter._tcp and one _matterc._udp service +static constexpr uint32_t kServiceListSize = CHIP_CONFIG_MAX_FABRICS * 2; + +static const char * GetProtocolString(DnssdServiceProtocol protocol) +{ + return protocol == DnssdServiceProtocol::kDnssdProtocolUdp ? "_udp" : "_tcp"; +} + +struct DnsServiceTxtEntries +{ + uint8_t mBuffer[kTotalMdnsServiceTxtBufferSize]; + Dnssd::TextEntry mTxtEntries[kMaxMdnsServiceTxtEntriesNumber]; +}; + +struct mDnsQueryCtx +{ + void * matterCtx; + chip::Dnssd::DnssdService mMdnsService; + DnsServiceTxtEntries mServiceTxtEntry; + char mServiceType[chip::Dnssd::kDnssdTypeAndProtocolMaxSize + 1]; + CHIP_ERROR error; + union + { + otMdnsBrowser mBrowseInfo; + otMdnsSrvResolver mSrvInfo; + otMdnsTxtResolver mTxtInfo; + otMdnsAddressResolver mAddrInfo; + }; + union + { + DnsBrowseCallback mDnsBrowseCallback; + DnsResolveCallback mDnsResolveCallback; + }; + + mDnsQueryCtx(void * context, DnsBrowseCallback aBrowseCallback) + { + matterCtx = context; + mDnsBrowseCallback = aBrowseCallback; + error = CHIP_NO_ERROR; + } + mDnsQueryCtx(void * context, DnsResolveCallback aResolveCallback) + { + matterCtx = context; + mDnsResolveCallback = aResolveCallback; + error = CHIP_NO_ERROR; + } +}; + +enum ResolveStep : uint8_t +{ + kResolveStepSrv = 0, + kResolveStepTxt, + kResolveStepIpAddr, +}; + +static const char * GetProtocolString(DnssdServiceProtocol protocol); + +static void OtBrowseCallback(otInstance * aInstance, const otMdnsBrowseResult * aResult); +static void OtServiceCallback(otInstance * aInstance, const otMdnsSrvResult * aResult); +static void OtTxtCallback(otInstance * aInstance, const otMdnsTxtResult * aResult); +static void OtAddressCallback(otInstance * aInstance, const otMdnsAddressResult * aResult); + +static void DispatchBrowseEmpty(intptr_t context); +static void DispatchBrowse(intptr_t context); + +static void DispatchTxtResolve(intptr_t context); +static void DispatchAddressResolve(intptr_t context); +static void DispatchResolve(intptr_t context); +static void DispatchResolveError(intptr_t context); + +static void HandleResolveCleanup(mDnsQueryCtx & resolveContext, ResolveStep stepType); + +static CHIP_ERROR ResolveBySrp(otInstance * thrInstancePtr, char * serviceName, mDnsQueryCtx * context, DnssdService * mdnsReq); +static CHIP_ERROR BrowseBySrp(otInstance * thrInstancePtr, char * serviceName, mDnsQueryCtx * context); +static CHIP_ERROR FromSrpCacheToMdnsData(const otSrpServerService * service, const otSrpServerHost * host, + const DnssdService * mdnsQueryReq, chip::Dnssd::DnssdService & mdnsService, + DnsServiceTxtEntries & serviceTxtEntries); + +static CHIP_ERROR FromServiceTypeToMdnsData(chip::Dnssd::DnssdService & mdnsService, const char * aServiceType); + +static bool bBrowseInProgress = false; +// ID 0 is reserved for host +static uint32_t mRegisterServiceId = 1; +static uint8_t mNetifIndex = 0; + +// Matter currently only supports one browse and resolve operation at a time so there is no need to create a list +// If the Matter implementation evolves in the future this functionality can be extended to a list. +static mDnsQueryCtx * mBrowseContext = nullptr; +static mDnsQueryCtx * mResolveContext = nullptr; + +#if USE_MDNS_NEXT_SERVICE_API +static otMdnsService * mServiceList[kServiceListSize]; +static uint32_t mServiceListFreeIndex; +#endif + +CHIP_ERROR NxpChipDnssdInit(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); + struct netif * extNetif = (ConnectivityManagerImpl().GetExternalInterface()).GetPlatformInterface(); + + // Don't try to do anything until the mDNS server is started + VerifyOrExit(otMdnsIsEnabled(thrInstancePtr), error = CHIP_ERROR_INCORRECT_STATE); + + mNetifIndex = netif_get_index(extNetif); + +exit: + initCallback(context, error); + return error; +} + +void NxpChipDnssdShutdown() +{ + otMdnsSetEnabled(ThreadStackMgrImpl().OTInstance(), false, 0); +} +#if USE_MDNS_NEXT_SERVICE_API +CHIP_ERROR NxpChipDnssdRemoveServices() +{ + otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); + otMdnsService otServiceData = { 0 }; + otMdnsIterator * iterator = nullptr; + ChipError error = CHIP_NO_ERROR; + otError otError = OT_ERROR_NONE; + otMdnsEntryState state; + + const char * hostName = ConnectivityManagerImpl().GetHostName(); + + iterator = otMdnsAllocateIterator(thrInstancePtr); + VerifyOrExit(iterator != nullptr, error = CHIP_ERROR_NO_MEMORY); + + mServiceListFreeIndex = 0; + + while (mServiceListFreeIndex <= kServiceListSize) + { + // allocate memory for new entry if the entry is not allready allocated from previous iteration + if (mServiceList[mServiceListFreeIndex] == nullptr) + { + mServiceList[mServiceListFreeIndex] = static_cast(Platform::MemoryAlloc(sizeof(otMdnsService))); + VerifyOrExit(mServiceList[mServiceListFreeIndex] != nullptr, error = CHIP_ERROR_NO_MEMORY); + } + + otError = otMdnsGetNextService(thrInstancePtr, iterator, mServiceList[mServiceListFreeIndex], &state); + if (otError == OT_ERROR_NOT_FOUND) + { + Platform::MemoryFree(mServiceList[mServiceListFreeIndex]); + mServiceList[mServiceListFreeIndex] = nullptr; + break; + } + + if ((0 == strcmp(mServiceList[mServiceListFreeIndex]->mHostName, hostName)) && + ((0 == strcmp(mServiceList[mServiceListFreeIndex]->mServiceType, "_matter._tcp")) || + (0 == strcmp(mServiceList[mServiceListFreeIndex]->mServiceType, "_matterc._udp")))) + { + mServiceListFreeIndex++; + } + } + +exit: + if (iterator != nullptr) + { + otMdnsFreeIterator(thrInstancePtr, iterator); + } + return error; +} +#else +CHIP_ERROR NxpChipDnssdRemoveServices() +{ + otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); + otMdnsService otServiceData = { 0 }; + + otServiceData.mHostName = ConnectivityManagerImpl().GetHostName(); + + otServiceData.mServiceType = "_matter._tcp"; + otMdnsUnregisterServiceType(thrInstancePtr, &otServiceData, OT_MDNS_SERVICE_MARK_FOR_UNREGISTER); + otServiceData.mServiceType = "_matterc._udp"; + otMdnsUnregisterServiceType(thrInstancePtr, &otServiceData, OT_MDNS_SERVICE_MARK_FOR_UNREGISTER); + + return CHIP_NO_ERROR; +} +#endif + +CHIP_ERROR NxpChipDnssdPublishService(const DnssdService * service, DnssdPublishCallback callback, void * context) +{ + ReturnErrorCodeIf(service == nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); + uint32_t txtBufferOffset = 0; + otError otErr = OT_ERROR_NONE; + otMdnsService otServiceData = { 0 }; + +#if USE_MDNS_NEXT_SERVICE_API + bool bRegisterService = true; +#endif + + char serviceType[chip::Dnssd::kDnssdTypeAndProtocolMaxSize + 1] = ""; + snprintf(serviceType, sizeof(serviceType), "%s.%s", service->mType, GetProtocolString(service->mProtocol)); + + // secure space for the raw TXT data in the worst-case scenario relevant for Matter: + // each entry consists of txt_entry_size (1B) + txt_entry_key + "=" + txt_entry_data + uint8_t txtBuffer[kMaxMdnsServiceTxtEntriesNumber + kTotalMdnsServiceTxtBufferSize] = { 0 }; + + // Don't try to do anything until the mDNS server is started + VerifyOrReturnValue(otMdnsIsEnabled(thrInstancePtr), CHIP_NO_ERROR); + + // Create TXT Data as one string from multiple key entries + for (uint32_t i = 0; i < service->mTextEntrySize; i++) + { + uint32_t keySize = strlen(service->mTextEntries[i].mKey); + // add TXT entry len, + 1 is for '=' + *(txtBuffer + txtBufferOffset++) = keySize + service->mTextEntries[i].mDataSize + 1; + + // add TXT entry key + memcpy(txtBuffer + txtBufferOffset, service->mTextEntries[i].mKey, keySize); + txtBufferOffset += keySize; + + // add TXT entry value if pointer is not null, if pointer is null it means we have bool value + if (service->mTextEntries[i].mData) + { + *(txtBuffer + txtBufferOffset++) = '='; + memcpy(txtBuffer + txtBufferOffset, service->mTextEntries[i].mData, service->mTextEntries[i].mDataSize); + txtBufferOffset += service->mTextEntries[i].mDataSize; + } + } + +#if USE_MDNS_NEXT_SERVICE_API + for (uint32_t i = 0; i < mServiceListFreeIndex; i++) + { + if ((0 == strcmp(mServiceList[i]->mHostName, service->mHostName)) && + (0 == strcmp(mServiceList[i]->mServiceInstance, service->mName)) && + (0 == strcmp(mServiceList[i]->mServiceType, serviceType))) + { + if ((mServiceList[i]->mTxtDataLength == txtBufferOffset) && + (0 == memcmp(txtBuffer, mServiceList[i]->mTxtData, txtBufferOffset))) + { + // In this case the service is + bRegisterService = false; + } + Platform::MemoryFree(mServiceList[i]); + if (i < --mServiceListFreeIndex) + { + // move last element in place of the removed one + mServiceList[i] = mServiceList[mServiceListFreeIndex]; + mServiceList[mServiceListFreeIndex] = nullptr; + } + else + { + mServiceList[i] = nullptr; + } + break; + } + } +#endif + if (bRegisterService) + { + if (strcmp(service->mHostName, "") != 0) + { + otServiceData.mHostName = service->mHostName; + } + + otServiceData.mServiceInstance = service->mName; + otServiceData.mServiceType = serviceType; + otServiceData.mSubTypeLabels = service->mSubTypes; + otServiceData.mSubTypeLabelsLength = service->mSubTypeSize; + otServiceData.mPort = service->mPort; + otServiceData.mTtl = service->mTtlSeconds; + otServiceData.mTxtData = txtBuffer; + otServiceData.mTxtDataLength = txtBufferOffset; + + otErr = otMdnsRegisterService(thrInstancePtr, &otServiceData, mRegisterServiceId++, NULL); + } + + return MapOpenThreadError(otErr); +} + +#if USE_MDNS_NEXT_SERVICE_API +CHIP_ERROR NxpChipDnssdFinalizeServiceUpdate() +{ + otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); + + for (uint32_t i = 0; i < mServiceListFreeIndex; i++) + { + if (mServiceList[i] != nullptr) + { + otMdnsUnregisterService(thrInstancePtr, mServiceList[i]); + Platform::MemoryFree(mServiceList[i]); + mServiceList[i] = nullptr; + } + } + + mServiceListFreeIndex = 0; + return CHIP_NO_ERROR; +} + +#else +CHIP_ERROR NxpChipDnssdFinalizeServiceUpdate() +{ + otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); + otMdnsService otServiceData = { 0 }; + + otServiceData.mHostName = ConnectivityManagerImpl().GetHostName(); + + otServiceData.mServiceType = "_matter._tcp"; + otMdnsUnregisterServiceType(thrInstancePtr, &otServiceData, OT_MDNS_SERVICE_UNREGISTER_MARKED_SERVICE); + otServiceData.mServiceType = "_matterc._udp"; + otMdnsUnregisterServiceType(thrInstancePtr, &otServiceData, OT_MDNS_SERVICE_UNREGISTER_MARKED_SERVICE); + + return CHIP_NO_ERROR; +} +#endif + +CHIP_ERROR NxpChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, Inet::IPAddressType addressType, + Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context, + intptr_t * browseIdentifier) +{ + *browseIdentifier = reinterpret_cast(nullptr); + CHIP_ERROR error = CHIP_NO_ERROR; + CHIP_ERROR srpBrowseError = CHIP_NO_ERROR; + otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); + + if (type == nullptr || callback == nullptr) + return CHIP_ERROR_INVALID_ARGUMENT; + + mBrowseContext = Platform::New(context, callback); + VerifyOrReturnError(mBrowseContext != nullptr, CHIP_ERROR_NO_MEMORY); + + // First try to browse the service in the SRP cache + snprintf(mBrowseContext->mServiceType, sizeof(mBrowseContext->mServiceType), "%s.%s", type, GetProtocolString(protocol)); + // After browsing in the SRP cache we will continue with regular mDNS browse + srpBrowseError = BrowseBySrp(thrInstancePtr, mBrowseContext->mServiceType, mBrowseContext); + + // Proceed to generate a mDNS query + mBrowseContext->mBrowseInfo.mServiceType = mBrowseContext->mServiceType; + mBrowseContext->mBrowseInfo.mSubTypeLabel = nullptr; + mBrowseContext->mBrowseInfo.mInfraIfIndex = mNetifIndex; + mBrowseContext->mBrowseInfo.mCallback = OtBrowseCallback; + + error = MapOpenThreadError(otMdnsStartBrowser(thrInstancePtr, &mBrowseContext->mBrowseInfo)); + + if (CHIP_NO_ERROR == error) + { + bBrowseInProgress = true; + *browseIdentifier = reinterpret_cast(mBrowseContext); + } + else + { + if (srpBrowseError == CHIP_NO_ERROR) + { + // In this case, we need to send a final browse indication to signal the Matter App that there are no more + // browse results coming + mBrowseContext->error = error; + DeviceLayer::PlatformMgr().ScheduleWork(DispatchBrowseEmpty, reinterpret_cast(mBrowseContext)); + } + else + { + Platform::Delete(mBrowseContext); + mBrowseContext = nullptr; + } + } + return error; +} + +CHIP_ERROR NxpChipDnssdStopBrowse(intptr_t browseIdentifier) +{ + mDnsQueryCtx * browseContext = reinterpret_cast(browseIdentifier); + otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); + otError error = OT_ERROR_INVALID_ARGS; + + // browseContext is only valid when bBrowseInProgress is true. The Matter stack can call this function even with a browseContext + // that has been freed in DispatchBrowseEmpty. + if ((true == bBrowseInProgress) && (browseContext)) + { + browseContext->error = MapOpenThreadError(otMdnsStopBrowser(thrInstancePtr, &browseContext->mBrowseInfo)); + + // browse context will be freed in DispatchBrowseEmpty + DispatchBrowseEmpty(reinterpret_cast(browseContext)); + } + return MapOpenThreadError(error); +} + +CHIP_ERROR NxpChipDnssdResolve(DnssdService * browseResult, Inet::InterfaceId interface, DnssdResolveCallback callback, + void * context) +{ + ChipError error = CHIP_ERROR_NOT_FOUND; + + if (browseResult == nullptr || callback == nullptr) + return CHIP_ERROR_INVALID_ARGUMENT; + + otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); + + mResolveContext = Platform::New(context, callback); + VerifyOrReturnError(mResolveContext != nullptr, CHIP_ERROR_NO_MEMORY); + + // First try to find the service in the SRP cache, use default.service.arpa as domain name + snprintf(mResolveContext->mServiceType, sizeof(mResolveContext->mServiceType), "%s.%s", browseResult->mType, + GetProtocolString(browseResult->mProtocol)); + + error = ResolveBySrp(thrInstancePtr, mResolveContext->mServiceType, mResolveContext, browseResult); + // If the SRP cache returns not found, proceed to generate a MDNS query + if (CHIP_ERROR_NOT_FOUND == error) + { + // The otMdnsSrvResolver structure contains only pointers to instance name and service type strings + // Use the memory from mMdnsService.mName to store the instance name string we are looking for + Platform::CopyString(mResolveContext->mMdnsService.mName, sizeof(mResolveContext->mMdnsService.mName), browseResult->mName); + + mResolveContext->mSrvInfo.mInfraIfIndex = mNetifIndex; + mResolveContext->mSrvInfo.mCallback = OtServiceCallback; + mResolveContext->mSrvInfo.mServiceInstance = mResolveContext->mMdnsService.mName; + mResolveContext->mSrvInfo.mServiceType = mResolveContext->mServiceType; + + return MapOpenThreadError(otMdnsStartSrvResolver(thrInstancePtr, &mResolveContext->mSrvInfo)); + } + else + { + return error; + } +} +void NxpChipDnssdResolveNoLongerNeeded(const char * instanceName) +{ + if (mResolveContext != nullptr) + { + if (strcmp(instanceName, mResolveContext->mMdnsService.mName) == 0) + { + otMdnsStopSrvResolver(ThreadStackMgrImpl().OTInstance(), &mResolveContext->mSrvInfo); + + Platform::Delete(mResolveContext); + mResolveContext = nullptr; + } + } +} + +CHIP_ERROR BrowseBySrp(otInstance * thrInstancePtr, char * serviceName, mDnsQueryCtx * context) +{ + const otSrpServerHost * host = nullptr; + const otSrpServerService * service = nullptr; + CHIP_ERROR error = CHIP_ERROR_NOT_FOUND; + + while ((host = otSrpServerGetNextHost(thrInstancePtr, host)) != nullptr) + { + while ((service = otSrpServerHostGetNextService(host, service)) != nullptr) + { + if ((false == otSrpServerServiceIsDeleted(service)) && + (0 == strncmp(otSrpServerServiceGetServiceName(service), serviceName, strlen(serviceName)))) + { + mDnsQueryCtx * serviceContext = Platform::New(context->matterCtx, context->mDnsBrowseCallback); + if (serviceContext != nullptr) + { + if (CHIP_NO_ERROR == + FromSrpCacheToMdnsData(service, host, nullptr, serviceContext->mMdnsService, + serviceContext->mServiceTxtEntry)) + { + // Set error to CHIP_NO_ERROR to signal that there was at least one service found in the cache + error = CHIP_NO_ERROR; + DeviceLayer::PlatformMgr().ScheduleWork(DispatchBrowse, reinterpret_cast(serviceContext)); + } + else + { + Platform::Delete(serviceContext); + } + } + } + } + } + return error; +} + +CHIP_ERROR ResolveBySrp(otInstance * thrInstancePtr, char * serviceName, mDnsQueryCtx * context, DnssdService * mdnsReq) +{ + const otSrpServerHost * host = nullptr; + const otSrpServerService * service = nullptr; + CHIP_ERROR error = CHIP_ERROR_NOT_FOUND; + + while ((host = otSrpServerGetNextHost(thrInstancePtr, host)) != nullptr) + { + while ((service = otSrpServerHostGetNextService(host, service)) != nullptr) + { + if ((false == otSrpServerServiceIsDeleted(service)) && + (0 == strncmp(otSrpServerServiceGetServiceName(service), serviceName, strlen(serviceName))) && + (0 == strncmp(otSrpServerServiceGetInstanceName(service), mdnsReq->mName, strlen(mdnsReq->mName)))) + { + error = FromSrpCacheToMdnsData(service, host, mdnsReq, context->mMdnsService, context->mServiceTxtEntry); + if (error == CHIP_NO_ERROR) + { + DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolve, reinterpret_cast(context)); + } + break; + } + } + + if (error == CHIP_NO_ERROR) + { + break; + } + } + + return error; +} + +CHIP_ERROR FromSrpCacheToMdnsData(const otSrpServerService * service, const otSrpServerHost * host, + const DnssdService * mdnsQueryReq, chip::Dnssd::DnssdService & mdnsService, + DnsServiceTxtEntries & serviceTxtEntries) +{ + const char * tmpName; + const uint8_t * txtStringPtr; + size_t substringSize; + uint8_t addrNum = 0; + uint16_t txtDataLen; + const otIp6Address * ip6AddrPtr = otSrpServerHostGetAddresses(host, &addrNum); + + if (mdnsQueryReq != nullptr) + { + Platform::CopyString(mdnsService.mName, sizeof(mdnsService.mName), mdnsQueryReq->mName); + Platform::CopyString(mdnsService.mType, sizeof(mdnsService.mType), mdnsQueryReq->mType); + mdnsService.mProtocol = mdnsQueryReq->mProtocol; + } + else + { + tmpName = otSrpServerServiceGetInstanceName(service); + // Extract from the .... the part + size_t substringSize = strchr(tmpName, '.') - tmpName; + if (substringSize >= ArraySize(mdnsService.mName)) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + Platform::CopyString(mdnsService.mName, substringSize + 1, tmpName); + + // Extract from the .... the part. + tmpName = tmpName + substringSize + 1; + substringSize = strchr(tmpName, '.') - tmpName; + if (substringSize >= ArraySize(mdnsService.mType)) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + Platform::CopyString(mdnsService.mType, substringSize + 1, tmpName); + + // Extract from the .... the part. + tmpName = tmpName + substringSize + 1; + substringSize = strchr(tmpName, '.') - tmpName; + if (substringSize >= (chip::Dnssd::kDnssdProtocolTextMaxSize + 1)) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + if (strncmp(tmpName, "_udp", substringSize) == 0) + { + mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolUdp; + } + else if (strncmp(tmpName, "_tcp", substringSize) == 0) + { + mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolTcp; + } + else + { + mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolUnknown; + } + } + + // Extract from the .. the part. + tmpName = otSrpServerHostGetFullName(host); + substringSize = strchr(tmpName, '.') - tmpName; + if (substringSize >= ArraySize(mdnsService.mHostName)) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + Platform::CopyString(mdnsService.mHostName, substringSize + 1, tmpName); + mdnsService.mPort = otSrpServerServiceGetPort(service); + + // All SRP cache hits come from the Thread Netif + mdnsService.mInterface = ConnectivityManagerImpl().GetThreadInterface(); + + mdnsService.mAddressType = Inet::IPAddressType::kIPv6; + mdnsService.mAddress = std::optional(ToIPAddress(*ip6AddrPtr)); + + // Extract TXT record SRP service + txtStringPtr = otSrpServerServiceGetTxtData(service, &txtDataLen); + if (txtDataLen != 0) + { + otDnsTxtEntryIterator iterator; + otDnsInitTxtEntryIterator(&iterator, txtStringPtr, txtDataLen); + + otDnsTxtEntry txtEntry; + chip::FixedBufferAllocator alloc(serviceTxtEntries.mBuffer); + + uint8_t entryIndex = 0; + while ((otDnsGetNextTxtEntry(&iterator, &txtEntry) == OT_ERROR_NONE) && entryIndex < 64) + { + if (txtEntry.mKey == nullptr || txtEntry.mValue == nullptr) + continue; + + serviceTxtEntries.mTxtEntries[entryIndex].mKey = alloc.Clone(txtEntry.mKey); + serviceTxtEntries.mTxtEntries[entryIndex].mData = alloc.Clone(txtEntry.mValue, txtEntry.mValueLength); + serviceTxtEntries.mTxtEntries[entryIndex].mDataSize = txtEntry.mValueLength; + entryIndex++; + } + + ReturnErrorCodeIf(alloc.AnyAllocFailed(), CHIP_ERROR_BUFFER_TOO_SMALL); + + mdnsService.mTextEntries = serviceTxtEntries.mTxtEntries; + mdnsService.mTextEntrySize = entryIndex; + } + else + { + mdnsService.mTextEntrySize = 0; + } + + mdnsService.mSubTypes = nullptr; + mdnsService.mSubTypeSize = 0; + + return CHIP_NO_ERROR; +} + +static CHIP_ERROR FromServiceTypeToMdnsData(chip::Dnssd::DnssdService & mdnsService, const char * aServiceType) +{ + char protocol[chip::Dnssd::kDnssdProtocolTextMaxSize + 1]; + const char * protocolSubstringStart; + size_t substringSize; + + // Extract from the . the part. + substringSize = strchr(aServiceType, '.') - aServiceType; + if (substringSize >= ArraySize(mdnsService.mType)) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + Platform::CopyString(mdnsService.mType, ArraySize(mdnsService.mType), aServiceType); + + // Extract from the .. the . part. + protocolSubstringStart = aServiceType + substringSize; + + // Check that the protocolSubstringStart starts wit a '.' to be sure we are in the right place + if (strchr(protocolSubstringStart, '.') == nullptr) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + + // Jump over '.' in protocolSubstringStart and substract the string terminator from the size + substringSize = strlen(++protocolSubstringStart) - 1; + if (substringSize >= ArraySize(protocol)) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + Platform::CopyString(protocol, ArraySize(protocol), protocolSubstringStart); + + if (strncmp(protocol, "_udp", chip::Dnssd::kDnssdProtocolTextMaxSize) == 0) + { + mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolUdp; + } + else if (strncmp(protocol, "_tcp", chip::Dnssd::kDnssdProtocolTextMaxSize) == 0) + { + mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolTcp; + } + else + { + mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolUnknown; + } + + // All mDNS replies come from the External Netif + mdnsService.mInterface = ConnectivityManagerImpl().GetExternalInterface(); + + return CHIP_NO_ERROR; +} + +static void OtBrowseCallback(otInstance * aInstance, const otMdnsBrowseResult * aResult) +{ + CHIP_ERROR error; + + // Ingnore reponses with TTL 0, the record is no longer valid and was removed from the mDNS cache + VerifyOrReturn(aResult->mTtl > 0); + + mDnsQueryCtx * tmpContext = Platform::New(mBrowseContext->matterCtx, mBrowseContext->mDnsBrowseCallback); + VerifyOrReturn(tmpContext != nullptr); + + Platform::CopyString(tmpContext->mMdnsService.mName, sizeof(tmpContext->mMdnsService.mName), aResult->mServiceInstance); + error = FromServiceTypeToMdnsData(tmpContext->mMdnsService, aResult->mServiceType); + + if (CHIP_NO_ERROR == error) + { + DeviceLayer::PlatformMgr().ScheduleWork(DispatchBrowse, reinterpret_cast(tmpContext)); + } + else + { + Platform::Delete(tmpContext); + } +} + +static void OtServiceCallback(otInstance * aInstance, const otMdnsSrvResult * aResult) +{ + CHIP_ERROR error; + + // Ingnore reponses with TTL 0, the record is no longer valid and was removed from the mDNS cache + VerifyOrReturn(aResult->mTtl > 0); + + VerifyOrReturn(mResolveContext != nullptr); + + error = FromServiceTypeToMdnsData(mResolveContext->mMdnsService, aResult->mServiceType); + mResolveContext->error = error; + + if (CHIP_NO_ERROR == error) + { + Platform::CopyString(mResolveContext->mMdnsService.mName, sizeof(mResolveContext->mMdnsService.mName), + aResult->mServiceInstance); + Platform::CopyString(mResolveContext->mMdnsService.mHostName, sizeof(mResolveContext->mMdnsService.mHostName), + aResult->mHostName); + + mResolveContext->mMdnsService.mPort = aResult->mPort; + mResolveContext->mMdnsService.mTtlSeconds = aResult->mTtl; + DeviceLayer::PlatformMgr().ScheduleWork(DispatchTxtResolve, reinterpret_cast(mResolveContext)); + } + else + { + HandleResolveCleanup(*mResolveContext, kResolveStepSrv); + } +} + +static void OtTxtCallback(otInstance * aInstance, const otMdnsTxtResult * aResult) +{ + bool bSendDispatch = true; + + // Ingnore reponses with TTL 0, the record is no longer valid and was removed from the mDNS cache + VerifyOrReturn(aResult->mTtl > 0); + + VerifyOrReturn(mResolveContext != nullptr); + + // Check if TXT record was included in the response. + if (aResult->mTxtDataLength != 0) + { + otDnsTxtEntryIterator iterator; + otDnsInitTxtEntryIterator(&iterator, aResult->mTxtData, aResult->mTxtDataLength); + + otDnsTxtEntry txtEntry; + chip::FixedBufferAllocator alloc(mResolveContext->mServiceTxtEntry.mBuffer); + + uint8_t entryIndex = 0; + while ((otDnsGetNextTxtEntry(&iterator, &txtEntry) == OT_ERROR_NONE) && entryIndex < 64) + { + if (txtEntry.mKey == nullptr || txtEntry.mValue == nullptr) + continue; + + mResolveContext->mServiceTxtEntry.mTxtEntries[entryIndex].mKey = alloc.Clone(txtEntry.mKey); + mResolveContext->mServiceTxtEntry.mTxtEntries[entryIndex].mData = alloc.Clone(txtEntry.mValue, txtEntry.mValueLength); + mResolveContext->mServiceTxtEntry.mTxtEntries[entryIndex].mDataSize = txtEntry.mValueLength; + entryIndex++; + } + + if (alloc.AnyAllocFailed()) + { + bSendDispatch = false; + } + else + { + mResolveContext->mMdnsService.mTextEntries = mResolveContext->mServiceTxtEntry.mTxtEntries; + mResolveContext->mMdnsService.mTextEntrySize = entryIndex; + } + } + else + { + mResolveContext->mMdnsService.mTextEntrySize = 0; + } + + if (bSendDispatch) + { + DeviceLayer::PlatformMgr().ScheduleWork(DispatchAddressResolve, reinterpret_cast(mResolveContext)); + } + else + { + HandleResolveCleanup(*mResolveContext, kResolveStepTxt); + } +} + +static void OtAddressCallback(otInstance * aInstance, const otMdnsAddressResult * aResult) +{ + // Ingnore reponses with TTL 0, the record is no longer valid and was removed from the mDNS cache + VerifyOrReturn((aResult->mAddressesLength > 0) && (aResult->mAddresses[0].mTtl > 0)); + + VerifyOrReturn(mResolveContext != nullptr); + + mResolveContext->mMdnsService.mAddressType = Inet::IPAddressType::kIPv6; + mResolveContext->mMdnsService.mAddress = std::optional(ToIPAddress(aResult->mAddresses[0].mAddress)); + + DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolve, reinterpret_cast(mResolveContext)); +} + +static void DispatchBrowseEmpty(intptr_t context) +{ + auto * browseContext = reinterpret_cast(context); + browseContext->mDnsBrowseCallback(browseContext->matterCtx, nullptr, 0, true, browseContext->error); + Platform::Delete(browseContext); + mBrowseContext = nullptr; + bBrowseInProgress = false; +} + +static void DispatchBrowse(intptr_t context) +{ + auto * browseContext = reinterpret_cast(context); + browseContext->mDnsBrowseCallback(browseContext->matterCtx, &browseContext->mMdnsService, 1, false, browseContext->error); + Platform::Delete(browseContext); +} + +static void DispatchTxtResolve(intptr_t context) +{ + mDnsQueryCtx * resolveContext = reinterpret_cast(context); + otError error; + + // Stop SRV resolver before starting TXT one, ignore error as it will only happen if mMDS module is not initialized + otMdnsStopSrvResolver(ThreadStackMgrImpl().OTInstance(), &resolveContext->mSrvInfo); + + resolveContext->mTxtInfo.mServiceInstance = resolveContext->mMdnsService.mName; + resolveContext->mTxtInfo.mServiceType = resolveContext->mServiceType; + resolveContext->mTxtInfo.mCallback = OtTxtCallback; + resolveContext->mTxtInfo.mInfraIfIndex = mNetifIndex; + + error = otMdnsStartTxtResolver(ThreadStackMgrImpl().OTInstance(), &resolveContext->mTxtInfo); + if (error != OT_ERROR_NONE) + { + resolveContext->error = MapOpenThreadError(error); + DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolveError, reinterpret_cast(resolveContext)); + } +} + +static void DispatchAddressResolve(intptr_t context) +{ + otError error; + mDnsQueryCtx * resolveContext = reinterpret_cast(context); + // Stop TXT resolver before starting address one, ignore error as it will only happen if mMDS module is not initialized + otMdnsStopTxtResolver(ThreadStackMgrImpl().OTInstance(), &resolveContext->mTxtInfo); + + resolveContext->mAddrInfo.mCallback = OtAddressCallback; + resolveContext->mAddrInfo.mHostName = resolveContext->mMdnsService.mHostName; + resolveContext->mAddrInfo.mInfraIfIndex = mNetifIndex; + + error = otMdnsStartIp6AddressResolver(ThreadStackMgrImpl().OTInstance(), &resolveContext->mAddrInfo); + if (error != OT_ERROR_NONE) + { + resolveContext->error = MapOpenThreadError(error); + DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolveError, reinterpret_cast(resolveContext)); + } +} + +static void DispatchResolve(intptr_t context) +{ + mDnsQueryCtx * resolveContext = reinterpret_cast(context); + Dnssd::DnssdService & service = resolveContext->mMdnsService; + Span ipAddrs; + + // Stop Address resolver, we have finished resolving the service + otMdnsStopIp6AddressResolver(ThreadStackMgrImpl().OTInstance(), &resolveContext->mAddrInfo); + + if (service.mAddress.has_value()) + { + ipAddrs = Span(&*service.mAddress, 1); + } + + // Signal that the context will be freed and that the resolve operation is stopped because Matter will + // try do stop it again on the mDnsResolveCallback + mResolveContext = nullptr; + + resolveContext->mDnsResolveCallback(resolveContext->matterCtx, &service, ipAddrs, resolveContext->error); + Platform::Delete(resolveContext); +} + +static void DispatchResolveError(intptr_t context) +{ + mDnsQueryCtx * resolveContext = reinterpret_cast(context); + Span ipAddrs; + + // Signal that the context will be freed and that the resolve operation is stopped because Matter will + // try do stop it again on the mDnsResolveCallback + mResolveContext = nullptr; + + resolveContext->mDnsResolveCallback(resolveContext->matterCtx, nullptr, ipAddrs, resolveContext->error); + Platform::Delete(resolveContext); +} + +void HandleResolveCleanup(mDnsQueryCtx & resolveContext, ResolveStep stepType) +{ + switch (stepType) + { + case kResolveStepSrv: + otMdnsStopSrvResolver(ThreadStackMgrImpl().OTInstance(), &resolveContext.mSrvInfo); + break; + case kResolveStepTxt: + otMdnsStopTxtResolver(ThreadStackMgrImpl().OTInstance(), &resolveContext.mTxtInfo); + break; + case kResolveStepIpAddr: + otMdnsStopIp6AddressResolver(ThreadStackMgrImpl().OTInstance(), &resolveContext.mAddrInfo); + break; + } + + DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolve, reinterpret_cast(&resolveContext)); +} + +} // namespace Dnssd +} // namespace chip diff --git a/src/platform/nxp/common/DnssdImplBr.h b/src/platform/nxp/common/DnssdImplBr.h new file mode 100644 index 00000000000000..970a2c675752b6 --- /dev/null +++ b/src/platform/nxp/common/DnssdImplBr.h @@ -0,0 +1,46 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * Copyright 2024 NXP + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 Dnssd { + +CHIP_ERROR NxpChipDnssdInit(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context); + +void NxpChipDnssdShutdown(); + +CHIP_ERROR NxpChipDnssdPublishService(const DnssdService * service, DnssdPublishCallback callback, void * context); + +CHIP_ERROR NxpChipDnssdRemoveServices(); + +CHIP_ERROR NxpChipDnssdFinalizeServiceUpdate(); + +CHIP_ERROR NxpChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, chip::Inet::IPAddressType addressType, + chip::Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context, + intptr_t * browseIdentifier); + +CHIP_ERROR NxpChipDnssdStopBrowse(intptr_t browseIdentifier); + +CHIP_ERROR NxpChipDnssdResolve(DnssdService * service, chip::Inet::InterfaceId interface, DnssdResolveCallback callback, + void * context); + +void NxpChipDnssdResolveNoLongerNeeded(const char * instanceName); + +} // namespace Dnssd +} // namespace chip diff --git a/src/platform/nxp/rt/rw61x/BUILD.gn b/src/platform/nxp/rt/rw61x/BUILD.gn index 447ef2905bb300..e80dd3cbd823f4 100644 --- a/src/platform/nxp/rt/rw61x/BUILD.gn +++ b/src/platform/nxp/rt/rw61x/BUILD.gn @@ -34,7 +34,10 @@ source_set("nxp_ota") { } config("nxp_platform_config") { - defines = [ "EXTERNAL_BLEMANAGERIMPL_HEADER=\"platform/nxp/common/ble_zephyr/BLEManagerImpl.h\"" ] + defines = [ + "EXTERNAL_BLEMANAGERIMPL_HEADER=\"platform/nxp/common/ble_zephyr/BLEManagerImpl.h\"", + "CONFIG_BOOT_REASON_SDK_SUPPORT=1", + ] include_dirs = [ ".", "../../common", @@ -63,8 +66,10 @@ config("nxp_platform_config") { defines += [ "EXTERNAL_FACTORY_DATA_PROVIDER_IMPL_HEADER=\"platform/nxp/common/factory_data/FactoryDataProviderFwkImpl.h\"" ] } } - if (chip_enable_wifi && chip_enable_openthread) { - # Disable thread nwk commissioning instance on endpoint 0, when OTBR is enabled + + # When OTBR is enabled Thread network commissioning cluster is enabled using chip_enable_secondary_nwk_if + if (chip_enable_wifi && chip_enable_openthread && + !chip_enable_secondary_nwk_if) { defines += [ "_NO_GENERIC_THREAD_NETWORK_COMMISSIONING_DRIVER_" ] } } @@ -154,17 +159,33 @@ static_library("nxp_platform") { if (chip_enable_openthread) { sources += [ + # Temporary fix, to be revert once PR #34662 is merged, build issue when using GN check argument + "${chip_root}/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h", + "../../../OpenThread/GenericThreadBorderRouterDelegate.cpp", + "../../../OpenThread/GenericThreadBorderRouterDelegate.h", "../../../OpenThread/OpenThreadUtils.cpp", "../../common/ThreadStackManagerImpl.cpp", "../../common/ThreadStackManagerImpl.h", ] - deps += [ "${chip_root}/third_party/openthread:openthread" ] - public_deps += [ "${chip_root}/third_party/openthread:openthread-platform" ] + deps += [ "${chip_root}/src/app/common:ids" ] + + if (!nxp_build_matter_standalone_lib) { + deps += [ "${chip_root}/third_party/openthread:openthread" ] + public_deps += + [ "${chip_root}/third_party/openthread:openthread-platform" ] + } if (chip_mdns == "platform") { if (chip_enable_wifi) { - sources += [ "../../common/DnssdImpl.cpp" ] + sources += [ + "../../../OpenThread/DnssdImpl.cpp", + "../../../OpenThread/OpenThreadDnssdImpl.cpp", + "../../../OpenThread/OpenThreadDnssdImpl.h", + "../../common/DnssdImpl.cpp", + "../../common/DnssdImplBr.cpp", + "../../common/DnssdImplBr.h", + ] } else { sources += [ "../../../OpenThread/DnssdImpl.cpp", diff --git a/src/platform/nxp/rt/rw61x/PlatformManagerImpl.cpp b/src/platform/nxp/rt/rw61x/PlatformManagerImpl.cpp index c17e7df36c616c..fe8c6b012b4c3f 100644 --- a/src/platform/nxp/rt/rw61x/PlatformManagerImpl.cpp +++ b/src/platform/nxp/rt/rw61x/PlatformManagerImpl.cpp @@ -204,6 +204,7 @@ CHIP_ERROR PlatformManagerImpl::_InitChipStack(void) otPlatLogInit(); otPlatRadioInit(); otPlatSetResetFunction(initiateResetInIdle); + otPlatRandomInit(); #endif #if CHIP_DEVICE_CONFIG_ENABLE_WPA diff --git a/src/platform/nxp/rt/rw61x/args.gni b/src/platform/nxp/rt/rw61x/args.gni index 5561196ea3a323..b9b34f2e7c3cbc 100644 --- a/src/platform/nxp/rt/rw61x/args.gni +++ b/src/platform/nxp/rt/rw61x/args.gni @@ -42,6 +42,8 @@ declare_args() { # if rw610_mbedtls_port_els_pkc is set to false software mbedtls is used instead rw610_mbedtls_port_els_pkc = true + + chip_enable_secondary_nwk_if = false } # TODO : Enable the OTA Requestor by default. diff --git a/third_party/openthread/ot-nxp b/third_party/openthread/ot-nxp index 0a3248f5c8ec5a..0a480829128901 160000 --- a/third_party/openthread/ot-nxp +++ b/third_party/openthread/ot-nxp @@ -1 +1 @@ -Subproject commit 0a3248f5c8ec5a9fd05541974872323f26d5182f +Subproject commit 0a4808291289019d0930a6a63afd87c2983353f5 diff --git a/third_party/openthread/platforms/nxp/rt/rw61x/BUILD.gn b/third_party/openthread/platforms/nxp/rt/rw61x/BUILD.gn index 6d4854f53a9160..86c9f2fe2d5c58 100644 --- a/third_party/openthread/platforms/nxp/rt/rw61x/BUILD.gn +++ b/third_party/openthread/platforms/nxp/rt/rw61x/BUILD.gn @@ -34,6 +34,9 @@ config("openthread_rw61x_config") { "${openthread_nxp_root}/third_party/mbedtls/configs", "${openthread_root}/third_party/mbedtls", "${openthread_root}/examples/platforms", + "${openthread_nxp_root}/examples/utils/cli_addons", + "${openthread_nxp_root}/examples/utils/cli_addons/ephemeral_key", + "${openthread_nxp_root}/examples/utils/cli_addons/lwip", ] if (spinel_interface_rpmsg) { include_dirs += [ "${openthread_nxp_root}/src/common/spinel" ] @@ -57,6 +60,14 @@ config("openthread_rw61x_config") { "OPENTHREAD_CONFIG_MULTICAST_DNS_PUBLIC_API_ENABLE=1", "OT_APP_BR_LWIP_HOOKS_EN=1", ] + + if (chip_enable_matter_cli) { + defines += [ + "OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE=1", + "OT_APP_CLI_EPHEMERAL_KEY_ADDON=1", + "OT_APP_CLI_LWIP_ADDON=1", + ] + } } # ot cli configs @@ -89,6 +100,15 @@ source_set("libopenthread-rw61x") { "${openthread_nxp_root}/src/common/br/udp_plat.c", "${openthread_nxp_root}/src/common/br/utils.c", ] + + if (chip_enable_matter_cli) { + sources += [ + "${openthread_nxp_root}/examples/utils/cli_addons/addons_cli.c", + "${openthread_nxp_root}/examples/utils/cli_addons/ephemeral_key/ephemeral_key_cli.c", + "${openthread_nxp_root}/examples/utils/cli_addons/lwip/lwip_cli.c", + ] + } + deps += [ "${nxp_sdk_build_root}:nxp_lwip" ] } if (spinel_interface_rpmsg) { diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp index 00e32012cb3be6..3029e317897ca2 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp @@ -19400,6 +19400,7 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const encoder.Encode(to_underlying(Fields::kCreatorFabricIndex), creatorFabricIndex); encoder.Encode(to_underlying(Fields::kLastModifiedFabricIndex), lastModifiedFabricIndex); encoder.Encode(to_underlying(Fields::kNextCredentialIndex), nextCredentialIndex); + encoder.Encode(to_underlying(Fields::kCredentialData), credentialData); return encoder.Finalize(); } @@ -19437,6 +19438,10 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { err = DataModel::Decode(reader, nextCredentialIndex); } + else if (__context_tag == to_underlying(Fields::kCredentialData)) + { + err = DataModel::Decode(reader, credentialData); + } else { } diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h index f8847a3f1a0b51..16042f9eeb562f 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h @@ -26208,6 +26208,7 @@ enum class Fields : uint8_t kCreatorFabricIndex = 2, kLastModifiedFabricIndex = 3, kNextCredentialIndex = 4, + kCredentialData = 5, }; struct Type @@ -26222,6 +26223,7 @@ struct Type DataModel::Nullable creatorFabricIndex; DataModel::Nullable lastModifiedFabricIndex; DataModel::Nullable nextCredentialIndex; + Optional> credentialData; CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; @@ -26241,6 +26243,7 @@ struct DecodableType DataModel::Nullable creatorFabricIndex; DataModel::Nullable lastModifiedFabricIndex; DataModel::Nullable nextCredentialIndex; + Optional> credentialData; CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace GetCredentialStatusResponse diff --git a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp index e51e3eaa80e166..05c103395826c0 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp +++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp @@ -8560,6 +8560,7 @@ CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, ReturnErrorOnFailure(DataModelLogger::LogValue("creatorFabricIndex", indent + 1, value.creatorFabricIndex)); ReturnErrorOnFailure(DataModelLogger::LogValue("lastModifiedFabricIndex", indent + 1, value.lastModifiedFabricIndex)); ReturnErrorOnFailure(DataModelLogger::LogValue("nextCredentialIndex", indent + 1, value.nextCredentialIndex)); + ReturnErrorOnFailure(DataModelLogger::LogValue("credentialData", indent + 1, value.credentialData)); DataModelLogger::LogString(indent, "}"); return CHIP_NO_ERROR; }