diff --git a/.github/workflows/check-data-model-directory-updates.yaml b/.github/workflows/check-data-model-directory-updates.yaml index 305da81d9da817..7bd20c87e0e4ec 100644 --- a/.github/workflows/check-data-model-directory-updates.yaml +++ b/.github/workflows/check-data-model-directory-updates.yaml @@ -12,20 +12,28 @@ # See the License for the specific language governing permissions and # limitations under the License. -name: Check for changes to data_model directory without a sha update +name: Data model directory checks on: pull_request: - paths: - - "data_model/**" jobs: - check-submodule-update-label: - name: Check for changes to data_model directory without a sha update + check-data_model-updates: + name: Check for updates to data model directory without SHA updates runs-on: ubuntu-latest - if: "git diff --name-only HEAD^..HEAD data_model/ | grep -q spec_sha" + container: + image: ghcr.io/project-chip/chip-build steps: - - name: Error Message - run: echo This pull request attempts to update data_model directory, but is missing updates to spec_sha file with the latest version of the sha. Files in the data_model directory are generated automatically and should not be updated manually. - - name: Fail Job - run: exit 1 + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 2 + - name: Check for changes to master data_model directory without a SHA update + run: | + python3 scripts/dm_xml_ci_change_enforcement.py data_model/master + - name: Check for changes to 1.3 data_model directory without a SHA update + run: | + python3 scripts/dm_xml_ci_change_enforcement.py data_model/1.3 + - name: Check for changes to 1.4 data_model directory without a SHA update + run: | + python3 scripts/dm_xml_ci_change_enforcement.py data_model/1.4 \ No newline at end of file diff --git a/config/zephyr/Kconfig b/config/zephyr/Kconfig index d8717a625d3dd3..7b0ee1d15062d5 100644 --- a/config/zephyr/Kconfig +++ b/config/zephyr/Kconfig @@ -582,3 +582,10 @@ config CHIP_BLE_ADVERTISING_DURATION else the maximum duration time can be extended to 2880 minutes (48h). endif + +if BT +config CHIP_CUSTOM_BLE_ADV_DATA + bool "Use custom BLE advertising data" + help + Customization of BLE advertising data at the application layer +endif diff --git a/docs/ids_and_codes/spec_clusters.md b/docs/ids_and_codes/spec_clusters.md index 43db0725793a8a..2500e7de00ee2f 100644 --- a/docs/ids_and_codes/spec_clusters.md +++ b/docs/ids_and_codes/spec_clusters.md @@ -1,5 +1,5 @@ # List of currently defined spec clusters -This file was **AUTOMATICALLY** generated by `python scripts/generate_spec_xml.py`. DO NOT EDIT BY HAND! +This file was **AUTOMATICALLY** generated. Refer to this page: [data_model](/data_model/README.md). DO NOT EDIT BY HAND! | ID (Decimal) | ID (hex) | Name | |--------------|----------|----------------------------------------------------------| diff --git a/examples/air-purifier-app/air-purifier-common/air-purifier-app.matter b/examples/air-purifier-app/air-purifier-common/air-purifier-app.matter index 8b8743c6b67330..be9b08eecf6c5d 100644 --- a/examples/air-purifier-app/air-purifier-common/air-purifier-app.matter +++ b/examples/air-purifier-app/air-purifier-common/air-purifier-app.matter @@ -1147,7 +1147,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** Commands to trigger a Node to allow a new Administrator to commission it. */ diff --git a/examples/air-quality-sensor-app/air-quality-sensor-common/air-quality-sensor-app.matter b/examples/air-quality-sensor-app/air-quality-sensor-common/air-quality-sensor-app.matter index 896a27edd0d365..3fac5bbaeac2d1 100644 --- a/examples/air-quality-sensor-app/air-quality-sensor-common/air-quality-sensor-app.matter +++ b/examples/air-quality-sensor-app/air-quality-sensor-common/air-quality-sensor-app.matter @@ -1100,7 +1100,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter index fb770209b996a3..be6f4c0622c94a 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter @@ -2050,7 +2050,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ @@ -4010,7 +4010,7 @@ provisional cluster ScenesManagement = 98 { /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */ fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6; /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */ - fabric command CopyScene(CopySceneRequest): CopySceneResponse = 64; + fabric command access(invoke: manage) CopyScene(CopySceneRequest): CopySceneResponse = 64; } /** Attributes and commands for monitoring HEPA filters in a device */ @@ -9047,7 +9047,7 @@ endpoint 1 { ram attribute occupancySensorTypeBitmap default = 1; callback attribute holdTime; callback attribute holdTimeLimits; - ram attribute PIROccupiedToUnoccupiedDelay default = 10; + callback attribute PIROccupiedToUnoccupiedDelay; callback attribute featureMap; ram attribute clusterRevision default = 5; } @@ -9505,7 +9505,7 @@ endpoint 2 { ram attribute occupancySensorTypeBitmap default = 1; callback attribute holdTime; callback attribute holdTimeLimits; - ram attribute PIROccupiedToUnoccupiedDelay default = 10; + callback attribute PIROccupiedToUnoccupiedDelay; callback attribute featureMap; ram attribute clusterRevision default = 5; } diff --git a/examples/all-clusters-app/linux/ValveControlDelegate.cpp b/examples/all-clusters-app/linux/ValveControlDelegate.cpp index f161ee65eae504..ed006eaa14baec 100644 --- a/examples/all-clusters-app/linux/ValveControlDelegate.cpp +++ b/examples/all-clusters-app/linux/ValveControlDelegate.cpp @@ -38,7 +38,6 @@ DataModel::Nullable<chip::Percent> ValveControlDelegate::HandleOpenValve(DataMod // In this demo application, the transition is considered instant, // so current level is set to the requested level and current state is set to kOpen. currentLevel = sLevel; - Attributes::CurrentState::Set(kValveEndpoint, ValveConfigurationAndControl::ValveStateEnum::kOpen); return DataModel::Nullable<chip::Percent>(currentLevel); } @@ -48,8 +47,6 @@ CHIP_ERROR ValveControlDelegate::HandleCloseValve() sLastOpenDuration = 0; sLevel = 0; ReturnErrorOnFailure(ValveConfigurationAndControl::UpdateCurrentLevel(kValveEndpoint, sLevel)); - ReturnErrorOnFailure( - ValveConfigurationAndControl::UpdateCurrentState(kValveEndpoint, ValveConfigurationAndControl::ValveStateEnum::kClosed)); ChipLogProgress(NotSpecified, "Valve closed"); return CHIP_NO_ERROR; } diff --git a/examples/all-clusters-app/nxp/common/main/AppTask.cpp b/examples/all-clusters-app/nxp/common/main/AppTask.cpp index 0b945d49561e43..702a63e89b5c8d 100644 --- a/examples/all-clusters-app/nxp/common/main/AppTask.cpp +++ b/examples/all-clusters-app/nxp/common/main/AppTask.cpp @@ -40,6 +40,9 @@ void AllClustersApp::AppTask::PostInitMatterStack() void AllClustersApp::AppTask::PostInitMatterServerInstance() { +#ifdef APP_BT_DEVICE_NAME + chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName(APP_BT_DEVICE_NAME); +#endif // Disable last fixed endpoint, which is used as a placeholder for all of the // supported clusters so that ZAP will generated the requisite code. emberAfEndpointEnableDisable(emberAfEndpointFromIndex(static_cast<uint16_t>(emberAfFixedEndpointCount() - 1)), false); diff --git a/examples/all-clusters-app/nxp/rt/rt1060/BUILD.gn b/examples/all-clusters-app/nxp/rt/rt1060/BUILD.gn index beca71ac1002d8..d5a4936a48f5a0 100644 --- a/examples/all-clusters-app/nxp/rt/rt1060/BUILD.gn +++ b/examples/all-clusters-app/nxp/rt/rt1060/BUILD.gn @@ -223,6 +223,10 @@ rt_executable("all_cluster_app") { ] } + if (chip_enable_ble) { + defines += [ "APP_BT_DEVICE_NAME=\"NXP-AllClustersApp\"" ] + } + # In case a dedicated assert function needs to be supported the flag sdk_fsl_assert_support should be set to false # The would add to the build a dedicated application assert implementation. if (!sdk_fsl_assert_support) { diff --git a/examples/all-clusters-app/nxp/rt/rt1170/BUILD.gn b/examples/all-clusters-app/nxp/rt/rt1170/BUILD.gn index 70a0a4d640738c..edbd208506b824 100644 --- a/examples/all-clusters-app/nxp/rt/rt1170/BUILD.gn +++ b/examples/all-clusters-app/nxp/rt/rt1170/BUILD.gn @@ -188,6 +188,10 @@ rt_executable("all_cluster_app") { sources += [ "${common_example_dir}/wifi_connect/source/WifiConnect.cpp" ] } + if (chip_enable_ble) { + defines += [ "APP_BT_DEVICE_NAME=\"NXP-AllClustersApp\"" ] + } + # In case a dedicated assert function needs to be supported the flag sdk_fsl_assert_support should be set to false # The would add to the build a dedicated application assert implementation. if (!sdk_fsl_assert_support) { diff --git a/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn b/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn index 5b73da4bc92080..cb4e017b9b45bf 100644 --- a/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn +++ b/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn @@ -210,6 +210,10 @@ rt_executable("all_cluster_app") { sources += [ "${common_example_dir}/wifi_connect/source/WifiConnect.cpp" ] } + if (chip_enable_ble) { + defines += [ "APP_BT_DEVICE_NAME=\"NXP-AllClustersApp\"" ] + } + # In case a dedicated assert function needs to be supported the flag sdk_fsl_assert_support should be set to false # The would add to the build a dedicated application assert implementation. if (!sdk_fsl_assert_support) { 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 ae50904721e813..e7c61c1c308a05 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 @@ -1965,7 +1965,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ @@ -2879,7 +2879,7 @@ provisional cluster ScenesManagement = 98 { /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */ fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6; /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */ - fabric command CopyScene(CopySceneRequest): CopySceneResponse = 64; + fabric command access(invoke: manage) CopyScene(CopySceneRequest): CopySceneResponse = 64; } /** An interface to a generic way to secure a door */ diff --git a/examples/bridge-app/bridge-common/bridge-app.matter b/examples/bridge-app/bridge-common/bridge-app.matter index 26a16622741c6c..a17e26628c0deb 100644 --- a/examples/bridge-app/bridge-common/bridge-app.matter +++ b/examples/bridge-app/bridge-common/bridge-app.matter @@ -1454,7 +1454,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/noip_rootnode_dimmablelight_bCwGYSDpoe.matter b/examples/chef/devices/noip_rootnode_dimmablelight_bCwGYSDpoe.matter index 9a91b17a2a718a..931784e091f027 100644 --- a/examples/chef/devices/noip_rootnode_dimmablelight_bCwGYSDpoe.matter +++ b/examples/chef/devices/noip_rootnode_dimmablelight_bCwGYSDpoe.matter @@ -1262,7 +1262,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter b/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter index dc4334462e5cd8..d3e3b7b2d5eb47 100644 --- a/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter +++ b/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter @@ -1219,7 +1219,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.matter b/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.matter index 7c5232970dfaf5..dfa25e487b78e9 100644 --- a/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.matter +++ b/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.matter @@ -1070,7 +1070,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** Commands to trigger a Node to allow a new Administrator to commission it. */ diff --git a/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.matter b/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.matter index ac2265df8d50a4..aef07a846c9fd0 100644 --- a/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.matter +++ b/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.matter @@ -1406,7 +1406,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_basicvideoplayer_0ff86e943b.matter b/examples/chef/devices/rootnode_basicvideoplayer_0ff86e943b.matter index f9b32f989dbce5..9d1c73090d23c3 100644 --- a/examples/chef/devices/rootnode_basicvideoplayer_0ff86e943b.matter +++ b/examples/chef/devices/rootnode_basicvideoplayer_0ff86e943b.matter @@ -1344,7 +1344,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_colortemperaturelight_hbUnzYVeyn.matter b/examples/chef/devices/rootnode_colortemperaturelight_hbUnzYVeyn.matter index 5f0c6496f87d65..17b103e7d38b00 100644 --- a/examples/chef/devices/rootnode_colortemperaturelight_hbUnzYVeyn.matter +++ b/examples/chef/devices/rootnode_colortemperaturelight_hbUnzYVeyn.matter @@ -1421,7 +1421,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_contactsensor_27f76aeaf5.matter b/examples/chef/devices/rootnode_contactsensor_27f76aeaf5.matter index 8c08a4e1540b5e..b28730a4017232 100644 --- a/examples/chef/devices/rootnode_contactsensor_27f76aeaf5.matter +++ b/examples/chef/devices/rootnode_contactsensor_27f76aeaf5.matter @@ -1406,7 +1406,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_contactsensor_lFAGG1bfRO.matter b/examples/chef/devices/rootnode_contactsensor_lFAGG1bfRO.matter index 1d5b5856208131..4f9bdd54889000 100644 --- a/examples/chef/devices/rootnode_contactsensor_lFAGG1bfRO.matter +++ b/examples/chef/devices/rootnode_contactsensor_lFAGG1bfRO.matter @@ -1504,7 +1504,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.matter b/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.matter index 27c88b4fb8435e..c7acde0a5c341a 100644 --- a/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.matter +++ b/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.matter @@ -1290,7 +1290,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_dimmablelight_bCwGYSDpoe.matter b/examples/chef/devices/rootnode_dimmablelight_bCwGYSDpoe.matter index 57166f3ba46159..a2b13bd5ffdb72 100644 --- a/examples/chef/devices/rootnode_dimmablelight_bCwGYSDpoe.matter +++ b/examples/chef/devices/rootnode_dimmablelight_bCwGYSDpoe.matter @@ -1442,7 +1442,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_dimmablepluginunit_f8a9a0b9d4.matter b/examples/chef/devices/rootnode_dimmablepluginunit_f8a9a0b9d4.matter index cc875bbd196bf7..b2c67e9c9a4a4b 100644 --- a/examples/chef/devices/rootnode_dimmablepluginunit_f8a9a0b9d4.matter +++ b/examples/chef/devices/rootnode_dimmablepluginunit_f8a9a0b9d4.matter @@ -1442,7 +1442,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ @@ -1908,7 +1908,7 @@ provisional cluster ScenesManagement = 98 { /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */ fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6; /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */ - fabric command CopyScene(CopySceneRequest): CopySceneResponse = 64; + fabric command access(invoke: manage) CopyScene(CopySceneRequest): CopySceneResponse = 64; } /** The server cluster provides an interface to occupancy sensing functionality based on one or more sensing modalities, including configuration and provision of notifications of occupancy status. */ diff --git a/examples/chef/devices/rootnode_dishwasher_cc105034fe.matter b/examples/chef/devices/rootnode_dishwasher_cc105034fe.matter index d730676d92ece9..9eac1825e8d0b0 100644 --- a/examples/chef/devices/rootnode_dishwasher_cc105034fe.matter +++ b/examples/chef/devices/rootnode_dishwasher_cc105034fe.matter @@ -1061,7 +1061,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** 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. */ diff --git a/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter b/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter index 6aa16252672dcd..57ebf108fce25f 100644 --- a/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter +++ b/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter @@ -1406,7 +1406,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_extendedcolorlight_8lcaaYJVAa.matter b/examples/chef/devices/rootnode_extendedcolorlight_8lcaaYJVAa.matter index 71363c84a7d8a5..11c3186dcbfc10 100644 --- a/examples/chef/devices/rootnode_extendedcolorlight_8lcaaYJVAa.matter +++ b/examples/chef/devices/rootnode_extendedcolorlight_8lcaaYJVAa.matter @@ -1442,7 +1442,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter b/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter index 1acdbca51279a4..217d06a4e7c2c7 100644 --- a/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter +++ b/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter @@ -1224,7 +1224,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_flowsensor_1zVxHedlaV.matter b/examples/chef/devices/rootnode_flowsensor_1zVxHedlaV.matter index 466dbe2c419115..7d4b787540cbe3 100644 --- a/examples/chef/devices/rootnode_flowsensor_1zVxHedlaV.matter +++ b/examples/chef/devices/rootnode_flowsensor_1zVxHedlaV.matter @@ -1245,7 +1245,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_genericswitch_2dfff6e516.matter b/examples/chef/devices/rootnode_genericswitch_2dfff6e516.matter index 0ae39923c10a27..aa8846b6c64d4f 100644 --- a/examples/chef/devices/rootnode_genericswitch_2dfff6e516.matter +++ b/examples/chef/devices/rootnode_genericswitch_2dfff6e516.matter @@ -1252,7 +1252,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** This cluster exposes interactions with a switch device, for the purpose of using those interactions by other devices. diff --git a/examples/chef/devices/rootnode_genericswitch_9866e35d0b.matter b/examples/chef/devices/rootnode_genericswitch_9866e35d0b.matter index 6a66018ef40f60..5d79f67076a948 100644 --- a/examples/chef/devices/rootnode_genericswitch_9866e35d0b.matter +++ b/examples/chef/devices/rootnode_genericswitch_9866e35d0b.matter @@ -1252,7 +1252,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** This cluster exposes interactions with a switch device, for the purpose of using those interactions by other devices. diff --git a/examples/chef/devices/rootnode_heatingcoolingunit_ncdGai1E5a.matter b/examples/chef/devices/rootnode_heatingcoolingunit_ncdGai1E5a.matter index 36a655d47df5b6..76eac769b14b2b 100644 --- a/examples/chef/devices/rootnode_heatingcoolingunit_ncdGai1E5a.matter +++ b/examples/chef/devices/rootnode_heatingcoolingunit_ncdGai1E5a.matter @@ -1442,7 +1442,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_heatpump_87ivjRAECh.matter b/examples/chef/devices/rootnode_heatpump_87ivjRAECh.matter new file mode 100644 index 00000000000000..87ff9a38821291 --- /dev/null +++ b/examples/chef/devices/rootnode_heatpump_87ivjRAECh.matter @@ -0,0 +1,2759 @@ +// 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; +} + +enum ThreeLevelAutoEnum : enum8 { + kLow = 0; + kMedium = 1; + kHigh = 2; + kAutomatic = 3; +} + +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; +} + +/** 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 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; +} + +/** 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; +} + +/** This cluster is used to describe the configuration and capabilities of a physical power source that provides power to the Node. */ +cluster PowerSource = 47 { + revision 1; // NOTE: Default/not specifically set + + enum BatApprovedChemistryEnum : enum16 { + kUnspecified = 0; + kAlkaline = 1; + kLithiumCarbonFluoride = 2; + kLithiumChromiumOxide = 3; + kLithiumCopperOxide = 4; + kLithiumIronDisulfide = 5; + kLithiumManganeseDioxide = 6; + kLithiumThionylChloride = 7; + kMagnesium = 8; + kMercuryOxide = 9; + kNickelOxyhydride = 10; + kSilverOxide = 11; + kZincAir = 12; + kZincCarbon = 13; + kZincChloride = 14; + kZincManganeseDioxide = 15; + kLeadAcid = 16; + kLithiumCobaltOxide = 17; + kLithiumIon = 18; + kLithiumIonPolymer = 19; + kLithiumIronPhosphate = 20; + kLithiumSulfur = 21; + kLithiumTitanate = 22; + kNickelCadmium = 23; + kNickelHydrogen = 24; + kNickelIron = 25; + kNickelMetalHydride = 26; + kNickelZinc = 27; + kSilverZinc = 28; + kSodiumIon = 29; + kSodiumSulfur = 30; + kZincBromide = 31; + kZincCerium = 32; + } + + enum BatChargeFaultEnum : enum8 { + kUnspecified = 0; + kAmbientTooHot = 1; + kAmbientTooCold = 2; + kBatteryTooHot = 3; + kBatteryTooCold = 4; + kBatteryAbsent = 5; + kBatteryOverVoltage = 6; + kBatteryUnderVoltage = 7; + kChargerOverVoltage = 8; + kChargerUnderVoltage = 9; + kSafetyTimeout = 10; + } + + enum BatChargeLevelEnum : enum8 { + kOK = 0; + kWarning = 1; + kCritical = 2; + } + + enum BatChargeStateEnum : enum8 { + kUnknown = 0; + kIsCharging = 1; + kIsAtFullCharge = 2; + kIsNotCharging = 3; + } + + enum BatCommonDesignationEnum : enum16 { + kUnspecified = 0; + kAAA = 1; + kAA = 2; + kC = 3; + kD = 4; + k4v5 = 5; + k6v0 = 6; + k9v0 = 7; + k12AA = 8; + kAAAA = 9; + kA = 10; + kB = 11; + kF = 12; + kN = 13; + kNo6 = 14; + kSubC = 15; + kA23 = 16; + kA27 = 17; + kBA5800 = 18; + kDuplex = 19; + k4SR44 = 20; + k523 = 21; + k531 = 22; + k15v0 = 23; + k22v5 = 24; + k30v0 = 25; + k45v0 = 26; + k67v5 = 27; + kJ = 28; + kCR123A = 29; + kCR2 = 30; + k2CR5 = 31; + kCRP2 = 32; + kCRV3 = 33; + kSR41 = 34; + kSR43 = 35; + kSR44 = 36; + kSR45 = 37; + kSR48 = 38; + kSR54 = 39; + kSR55 = 40; + kSR57 = 41; + kSR58 = 42; + kSR59 = 43; + kSR60 = 44; + kSR63 = 45; + kSR64 = 46; + kSR65 = 47; + kSR66 = 48; + kSR67 = 49; + kSR68 = 50; + kSR69 = 51; + kSR516 = 52; + kSR731 = 53; + kSR712 = 54; + kLR932 = 55; + kA5 = 56; + kA10 = 57; + kA13 = 58; + kA312 = 59; + kA675 = 60; + kAC41E = 61; + k10180 = 62; + k10280 = 63; + k10440 = 64; + k14250 = 65; + k14430 = 66; + k14500 = 67; + k14650 = 68; + k15270 = 69; + k16340 = 70; + kRCR123A = 71; + k17500 = 72; + k17670 = 73; + k18350 = 74; + k18500 = 75; + k18650 = 76; + k19670 = 77; + k25500 = 78; + k26650 = 79; + k32600 = 80; + } + + enum BatFaultEnum : enum8 { + kUnspecified = 0; + kOverTemp = 1; + kUnderTemp = 2; + } + + enum BatReplaceabilityEnum : enum8 { + kUnspecified = 0; + kNotReplaceable = 1; + kUserReplaceable = 2; + kFactoryReplaceable = 3; + } + + enum PowerSourceStatusEnum : enum8 { + kUnspecified = 0; + kActive = 1; + kStandby = 2; + kUnavailable = 3; + } + + enum WiredCurrentTypeEnum : enum8 { + kAC = 0; + kDC = 1; + } + + enum WiredFaultEnum : enum8 { + kUnspecified = 0; + kOverVoltage = 1; + kUnderVoltage = 2; + } + + bitmap Feature : bitmap32 { + kWired = 0x1; + kBattery = 0x2; + kRechargeable = 0x4; + kReplaceable = 0x8; + } + + struct BatChargeFaultChangeType { + BatChargeFaultEnum current[] = 0; + BatChargeFaultEnum previous[] = 1; + } + + struct BatFaultChangeType { + BatFaultEnum current[] = 0; + BatFaultEnum previous[] = 1; + } + + struct WiredFaultChangeType { + WiredFaultEnum current[] = 0; + WiredFaultEnum previous[] = 1; + } + + info event WiredFaultChange = 0 { + WiredFaultEnum current[] = 0; + WiredFaultEnum previous[] = 1; + } + + info event BatFaultChange = 1 { + BatFaultEnum current[] = 0; + BatFaultEnum previous[] = 1; + } + + info event BatChargeFaultChange = 2 { + BatChargeFaultEnum current[] = 0; + BatChargeFaultEnum previous[] = 1; + } + + readonly attribute PowerSourceStatusEnum status = 0; + readonly attribute int8u order = 1; + readonly attribute char_string<60> description = 2; + readonly attribute optional nullable int32u wiredAssessedInputVoltage = 3; + readonly attribute optional nullable int16u wiredAssessedInputFrequency = 4; + readonly attribute optional WiredCurrentTypeEnum wiredCurrentType = 5; + readonly attribute optional nullable int32u wiredAssessedCurrent = 6; + readonly attribute optional int32u wiredNominalVoltage = 7; + readonly attribute optional int32u wiredMaximumCurrent = 8; + readonly attribute optional boolean wiredPresent = 9; + readonly attribute optional WiredFaultEnum activeWiredFaults[] = 10; + readonly attribute optional nullable int32u batVoltage = 11; + readonly attribute optional nullable int8u batPercentRemaining = 12; + readonly attribute optional nullable int32u batTimeRemaining = 13; + readonly attribute optional BatChargeLevelEnum batChargeLevel = 14; + readonly attribute optional boolean batReplacementNeeded = 15; + readonly attribute optional BatReplaceabilityEnum batReplaceability = 16; + readonly attribute optional boolean batPresent = 17; + readonly attribute optional BatFaultEnum activeBatFaults[] = 18; + readonly attribute optional char_string<60> batReplacementDescription = 19; + readonly attribute optional BatCommonDesignationEnum batCommonDesignation = 20; + readonly attribute optional char_string<20> batANSIDesignation = 21; + readonly attribute optional char_string<20> batIECDesignation = 22; + readonly attribute optional BatApprovedChemistryEnum batApprovedChemistry = 23; + readonly attribute optional int32u batCapacity = 24; + readonly attribute optional int8u batQuantity = 25; + readonly attribute optional BatChargeStateEnum batChargeState = 26; + readonly attribute optional nullable int32u batTimeToFullCharge = 27; + readonly attribute optional boolean batFunctionalWhileCharging = 28; + readonly attribute optional nullable int32u batChargingCurrent = 29; + readonly attribute optional BatChargeFaultEnum activeBatChargeFaults[] = 30; + readonly attribute endpoint_no endpointList[] = 31; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** This cluster is used to manage global aspects of the Commissioning flow. */ +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; + provisional readonly attribute access(read: administer) optional int32u TCUpdateDeadline = 9; + 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; +} + +/** 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; +} + +/** This cluster provides a mechanism for querying data about electrical power as measured by the server. */ +cluster ElectricalPowerMeasurement = 144 { + revision 1; + + enum MeasurementTypeEnum : enum16 { + kUnspecified = 0; + kVoltage = 1; + kActiveCurrent = 2; + kReactiveCurrent = 3; + kApparentCurrent = 4; + kActivePower = 5; + kReactivePower = 6; + kApparentPower = 7; + kRMSVoltage = 8; + kRMSCurrent = 9; + kRMSPower = 10; + kFrequency = 11; + kPowerFactor = 12; + kNeutralCurrent = 13; + kElectricalEnergy = 14; + } + + enum PowerModeEnum : enum8 { + kUnknown = 0; + kDC = 1; + kAC = 2; + } + + bitmap Feature : bitmap32 { + kDirectCurrent = 0x1; + kAlternatingCurrent = 0x2; + kPolyphasePower = 0x4; + kHarmonics = 0x8; + kPowerQuality = 0x10; + } + + struct MeasurementAccuracyRangeStruct { + int64s rangeMin = 0; + int64s rangeMax = 1; + optional percent100ths percentMax = 2; + optional percent100ths percentMin = 3; + optional percent100ths percentTypical = 4; + optional int64u fixedMax = 5; + optional int64u fixedMin = 6; + optional int64u fixedTypical = 7; + } + + struct MeasurementAccuracyStruct { + MeasurementTypeEnum measurementType = 0; + boolean measured = 1; + int64s minMeasuredValue = 2; + int64s maxMeasuredValue = 3; + MeasurementAccuracyRangeStruct accuracyRanges[] = 4; + } + + struct HarmonicMeasurementStruct { + int8u order = 0; + nullable int64s measurement = 1; + } + + struct MeasurementRangeStruct { + MeasurementTypeEnum measurementType = 0; + int64s min = 1; + int64s max = 2; + optional epoch_s startTimestamp = 3; + optional epoch_s endTimestamp = 4; + optional epoch_s minTimestamp = 5; + optional epoch_s maxTimestamp = 6; + optional systime_ms startSystime = 7; + optional systime_ms endSystime = 8; + optional systime_ms minSystime = 9; + optional systime_ms maxSystime = 10; + } + + info event MeasurementPeriodRanges = 0 { + MeasurementRangeStruct ranges[] = 0; + } + + readonly attribute PowerModeEnum powerMode = 0; + readonly attribute int8u numberOfMeasurementTypes = 1; + readonly attribute MeasurementAccuracyStruct accuracy[] = 2; + readonly attribute optional MeasurementRangeStruct ranges[] = 3; + readonly attribute optional nullable voltage_mv voltage = 4; + readonly attribute optional nullable amperage_ma activeCurrent = 5; + readonly attribute optional nullable amperage_ma reactiveCurrent = 6; + readonly attribute optional nullable amperage_ma apparentCurrent = 7; + readonly attribute nullable power_mw activePower = 8; + readonly attribute optional nullable power_mw reactivePower = 9; + readonly attribute optional nullable power_mw apparentPower = 10; + readonly attribute optional nullable voltage_mv RMSVoltage = 11; + readonly attribute optional nullable amperage_ma RMSCurrent = 12; + readonly attribute optional nullable power_mw RMSPower = 13; + readonly attribute optional nullable int64s frequency = 14; + readonly attribute optional nullable HarmonicMeasurementStruct harmonicCurrents[] = 15; + readonly attribute optional nullable HarmonicMeasurementStruct harmonicPhases[] = 16; + readonly attribute optional nullable int64s powerFactor = 17; + readonly attribute optional nullable amperage_ma neutralCurrent = 18; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** This cluster provides a mechanism for querying data about the electrical energy imported or provided by the server. */ +cluster ElectricalEnergyMeasurement = 145 { + revision 1; + + enum MeasurementTypeEnum : enum16 { + kUnspecified = 0; + kVoltage = 1; + kActiveCurrent = 2; + kReactiveCurrent = 3; + kApparentCurrent = 4; + kActivePower = 5; + kReactivePower = 6; + kApparentPower = 7; + kRMSVoltage = 8; + kRMSCurrent = 9; + kRMSPower = 10; + kFrequency = 11; + kPowerFactor = 12; + kNeutralCurrent = 13; + kElectricalEnergy = 14; + } + + bitmap Feature : bitmap32 { + kImportedEnergy = 0x1; + kExportedEnergy = 0x2; + kCumulativeEnergy = 0x4; + kPeriodicEnergy = 0x8; + } + + struct MeasurementAccuracyRangeStruct { + int64s rangeMin = 0; + int64s rangeMax = 1; + optional percent100ths percentMax = 2; + optional percent100ths percentMin = 3; + optional percent100ths percentTypical = 4; + optional int64u fixedMax = 5; + optional int64u fixedMin = 6; + optional int64u fixedTypical = 7; + } + + struct MeasurementAccuracyStruct { + MeasurementTypeEnum measurementType = 0; + boolean measured = 1; + int64s minMeasuredValue = 2; + int64s maxMeasuredValue = 3; + MeasurementAccuracyRangeStruct accuracyRanges[] = 4; + } + + struct CumulativeEnergyResetStruct { + optional nullable epoch_s importedResetTimestamp = 0; + optional nullable epoch_s exportedResetTimestamp = 1; + optional nullable systime_ms importedResetSystime = 2; + optional nullable systime_ms exportedResetSystime = 3; + } + + struct EnergyMeasurementStruct { + energy_mwh energy = 0; + optional epoch_s startTimestamp = 1; + optional epoch_s endTimestamp = 2; + optional systime_ms startSystime = 3; + optional systime_ms endSystime = 4; + } + + info event CumulativeEnergyMeasured = 0 { + optional EnergyMeasurementStruct energyImported = 0; + optional EnergyMeasurementStruct energyExported = 1; + } + + info event PeriodicEnergyMeasured = 1 { + optional EnergyMeasurementStruct energyImported = 0; + optional EnergyMeasurementStruct energyExported = 1; + } + + readonly attribute MeasurementAccuracyStruct accuracy = 0; + readonly attribute optional nullable EnergyMeasurementStruct cumulativeEnergyImported = 1; + readonly attribute optional nullable EnergyMeasurementStruct cumulativeEnergyExported = 2; + readonly attribute optional nullable EnergyMeasurementStruct periodicEnergyImported = 3; + readonly attribute optional nullable EnergyMeasurementStruct periodicEnergyExported = 4; + readonly attribute optional nullable CumulativeEnergyResetStruct cumulativeEnergyReset = 5; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** This cluster allows a client to manage the power draw of a device. An example of such a client could be an Energy Management System (EMS) which controls an Energy Smart Appliance (ESA). */ +provisional cluster DeviceEnergyManagement = 152 { + revision 4; + + enum AdjustmentCauseEnum : enum8 { + kLocalOptimization = 0; + kGridOptimization = 1; + } + + enum CauseEnum : enum8 { + kNormalCompletion = 0; + kOffline = 1; + kFault = 2; + kUserOptOut = 3; + kCancelled = 4; + } + + enum CostTypeEnum : enum8 { + kFinancial = 0; + kGHGEmissions = 1; + kComfort = 2; + kTemperature = 3; + } + + enum ESAStateEnum : enum8 { + kOffline = 0; + kOnline = 1; + kFault = 2; + kPowerAdjustActive = 3; + kPaused = 4; + } + + enum ESATypeEnum : enum8 { + kEVSE = 0; + kSpaceHeating = 1; + kWaterHeating = 2; + kSpaceCooling = 3; + kSpaceHeatingCooling = 4; + kBatteryStorage = 5; + kSolarPV = 6; + kFridgeFreezer = 7; + kWashingMachine = 8; + kDishwasher = 9; + kCooking = 10; + kHomeWaterPump = 11; + kIrrigationWaterPump = 12; + kPoolPump = 13; + kOther = 255; + } + + enum ForecastUpdateReasonEnum : enum8 { + kInternalOptimization = 0; + kLocalOptimization = 1; + kGridOptimization = 2; + } + + enum OptOutStateEnum : enum8 { + kNoOptOut = 0; + kLocalOptOut = 1; + kGridOptOut = 2; + kOptOut = 3; + } + + enum PowerAdjustReasonEnum : enum8 { + kNoAdjustment = 0; + kLocalOptimizationAdjustment = 1; + kGridOptimizationAdjustment = 2; + } + + bitmap Feature : bitmap32 { + kPowerAdjustment = 0x1; + kPowerForecastReporting = 0x2; + kStateForecastReporting = 0x4; + kStartTimeAdjustment = 0x8; + kPausable = 0x10; + kForecastAdjustment = 0x20; + kConstraintBasedAdjustment = 0x40; + } + + struct CostStruct { + CostTypeEnum costType = 0; + int32s value = 1; + int8u decimalPoints = 2; + optional int16u currency = 3; + } + + struct PowerAdjustStruct { + power_mw minPower = 0; + power_mw maxPower = 1; + elapsed_s minDuration = 2; + elapsed_s maxDuration = 3; + } + + struct PowerAdjustCapabilityStruct { + nullable PowerAdjustStruct powerAdjustCapability[] = 0; + PowerAdjustReasonEnum cause = 1; + } + + struct SlotStruct { + elapsed_s minDuration = 0; + elapsed_s maxDuration = 1; + elapsed_s defaultDuration = 2; + elapsed_s elapsedSlotTime = 3; + elapsed_s remainingSlotTime = 4; + optional boolean slotIsPausable = 5; + optional elapsed_s minPauseDuration = 6; + optional elapsed_s maxPauseDuration = 7; + optional int16u manufacturerESAState = 8; + optional power_mw nominalPower = 9; + optional power_mw minPower = 10; + optional power_mw maxPower = 11; + optional energy_mwh nominalEnergy = 12; + optional CostStruct costs[] = 13; + optional power_mw minPowerAdjustment = 14; + optional power_mw maxPowerAdjustment = 15; + optional elapsed_s minDurationAdjustment = 16; + optional elapsed_s maxDurationAdjustment = 17; + } + + struct ForecastStruct { + int32u forecastID = 0; + nullable int16u activeSlotNumber = 1; + epoch_s startTime = 2; + epoch_s endTime = 3; + optional nullable epoch_s earliestStartTime = 4; + optional epoch_s latestEndTime = 5; + boolean isPausable = 6; + SlotStruct slots[] = 7; + ForecastUpdateReasonEnum forecastUpdateReason = 8; + } + + struct ConstraintsStruct { + epoch_s startTime = 0; + elapsed_s duration = 1; + optional power_mw nominalPower = 2; + optional energy_mwh maximumEnergy = 3; + optional int8s loadControl = 4; + } + + struct SlotAdjustmentStruct { + int8u slotIndex = 0; + optional power_mw nominalPower = 1; + elapsed_s duration = 2; + } + + info event PowerAdjustStart = 0 { + } + + info event PowerAdjustEnd = 1 { + CauseEnum cause = 0; + elapsed_s duration = 1; + energy_mwh energyUse = 2; + } + + info event Paused = 2 { + } + + info event Resumed = 3 { + CauseEnum cause = 0; + } + + readonly attribute ESATypeEnum ESAType = 0; + readonly attribute boolean ESACanGenerate = 1; + readonly attribute ESAStateEnum ESAState = 2; + readonly attribute power_mw absMinPower = 3; + readonly attribute power_mw absMaxPower = 4; + readonly attribute optional nullable PowerAdjustCapabilityStruct powerAdjustmentCapability = 5; + readonly attribute optional nullable ForecastStruct forecast = 6; + readonly attribute optional OptOutStateEnum optOutState = 7; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct PowerAdjustRequestRequest { + power_mw power = 0; + elapsed_s duration = 1; + AdjustmentCauseEnum cause = 2; + } + + request struct StartTimeAdjustRequestRequest { + epoch_s requestedStartTime = 0; + AdjustmentCauseEnum cause = 1; + } + + request struct PauseRequestRequest { + elapsed_s duration = 0; + AdjustmentCauseEnum cause = 1; + } + + request struct ModifyForecastRequestRequest { + int32u forecastID = 0; + SlotAdjustmentStruct slotAdjustments[] = 1; + AdjustmentCauseEnum cause = 2; + } + + request struct RequestConstraintBasedForecastRequest { + ConstraintsStruct constraints[] = 0; + AdjustmentCauseEnum cause = 1; + } + + /** Allows a client to request an adjustment in the power consumption of an ESA for a specified duration. */ + command PowerAdjustRequest(PowerAdjustRequestRequest): DefaultSuccess = 0; + /** Allows a client to cancel an ongoing PowerAdjustmentRequest operation. */ + command CancelPowerAdjustRequest(): DefaultSuccess = 1; + /** Allows a client to adjust the start time of a Forecast sequence that has not yet started operation (i.e. where the current Forecast StartTime is in the future). */ + command StartTimeAdjustRequest(StartTimeAdjustRequestRequest): DefaultSuccess = 2; + /** Allows a client to temporarily pause an operation and reduce the ESAs energy demand. */ + command PauseRequest(PauseRequestRequest): DefaultSuccess = 3; + /** Allows a client to cancel the PauseRequest command and enable earlier resumption of operation. */ + command ResumeRequest(): DefaultSuccess = 4; + /** Allows a client to modify a Forecast within the limits allowed by the ESA. */ + command ModifyForecastRequest(ModifyForecastRequestRequest): DefaultSuccess = 5; + /** Allows a client to ask the ESA to recompute its Forecast based on power and time constraints. */ + command RequestConstraintBasedForecast(RequestConstraintBasedForecastRequest): DefaultSuccess = 6; + /** Allows a client to request cancellation of a previous adjustment request in a StartTimeAdjustRequest, ModifyForecastRequest or RequestConstraintBasedForecast command. */ + command CancelRequest(): DefaultSuccess = 7; +} + +/** The Power Topology Cluster provides a mechanism for expressing how power is flowing between endpoints. */ +cluster PowerTopology = 156 { + revision 1; + + bitmap Feature : bitmap32 { + kNodeTopology = 0x1; + kTreeTopology = 0x2; + kSetTopology = 0x4; + kDynamicPowerFlow = 0x8; + } + + readonly attribute optional endpoint_no availableEndpoints[] = 0; + readonly attribute optional endpoint_no activeEndpoints[] = 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; +} + +/** Attributes and commands for selecting a mode from a list of supported options. */ +provisional cluster DeviceEnergyManagementMode = 159 { + revision 2; + + enum ModeTag : enum16 { + kAuto = 0; + kQuick = 1; + kQuiet = 2; + kLowNoise = 3; + kLowEnergy = 4; + kVacation = 5; + kMin = 6; + kMax = 7; + kNight = 8; + kDay = 9; + kNoOptimization = 16384; + kDeviceOptimization = 16385; + kLocalOptimization = 16386; + kGridOptimization = 16387; + } + + bitmap Feature : bitmap32 { + kOnOff = 0x1; + } + + struct ModeTagStruct { + optional vendor_id mfgCode = 0; + enum16 value = 1; + } + + struct ModeOptionStruct { + char_string<64> label = 0; + int8u mode = 1; + ModeTagStruct modeTags[] = 2; + } + + readonly attribute ModeOptionStruct supportedModes[] = 0; + readonly attribute int8u currentMode = 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 ChangeToModeRequest { + int8u newMode = 0; + } + + response struct ChangeToModeResponse = 1 { + enum8 status = 0; + optional char_string<64> statusText = 1; + } + + /** This command is used to change device modes. */ + command ChangeToMode(ChangeToModeRequest): ChangeToModeResponse = 0; +} + +/** 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; +} + +/** Attributes and commands for configuring the measurement of temperature, and reporting temperature measurements. */ +cluster TemperatureMeasurement = 1026 { + revision 1; // NOTE: Default/not specifically set + + readonly attribute nullable temperature measuredValue = 0; + readonly attribute nullable temperature minMeasuredValue = 1; + readonly attribute nullable temperature maxMeasuredValue = 2; + readonly attribute optional int16u tolerance = 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; +} + +endpoint 0 { + device type ma_rootdevice = 22, 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 attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster AccessControl { + callback attribute acl; + callback attribute extension; + callback attribute subjectsPerAccessControlEntry; + callback attribute targetsPerAccessControlEntry; + callback attribute accessControlEntriesPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + callback attribute clusterRevision; + } + + server cluster BasicInformation { + callback attribute dataModelRevision; + callback attribute vendorName; + callback attribute vendorID; + callback attribute productName; + callback attribute productID; + ram attribute nodeLabel; + callback attribute location; + callback attribute hardwareVersion; + callback attribute hardwareVersionString; + callback attribute softwareVersion; + callback attribute softwareVersionString; + callback attribute uniqueID; + callback attribute capabilityMinima; + callback attribute specificationVersion; + callback attribute maxPathsPerInvoke; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 3; + } + + server cluster LocalizationConfiguration { + ram attribute activeLocale; + callback attribute supportedLocales; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + 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; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + 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 interfaceEnabled; + ram attribute lastNetworkingStatus; + ram attribute lastNetworkID; + ram attribute lastConnectErrorValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster DiagnosticLogs { + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command RetrieveLogsRequest; + handle command RetrieveLogsResponse; + } + + server cluster GeneralDiagnostics { + callback attribute networkInterfaces; + callback attribute rebootCount; + callback attribute upTime; + ram attribute testEventTriggersEnabled; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + + handle command TestEventTrigger; + handle command TimeSnapshot; + handle command TimeSnapshotResponse; + } + + server cluster AdministratorCommissioning { + callback attribute windowStatus; + callback attribute adminFabricIndex; + callback attribute adminVendorId; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + 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; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + 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 generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + 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_powersource = 17, version 1; + device type ma_electricalsensor = 1296, version 1; + device type device_energy_management = 1293, version 1; + device type ma_heatpump = 777, version 1; + + binding cluster Thermostat; + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x00; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 4; + + handle command Identify; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute tagList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster PowerSource { + ram attribute status; + ram attribute order; + ram attribute description; + callback attribute endpointList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 1; + ram attribute clusterRevision default = 1; + } + + server cluster ElectricalPowerMeasurement { + callback attribute powerMode; + callback attribute numberOfMeasurementTypes; + callback attribute accuracy; + callback attribute voltage; + callback attribute activeCurrent; + callback attribute activePower; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster ElectricalEnergyMeasurement { + callback attribute accuracy; + callback attribute cumulativeEnergyImported; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster DeviceEnergyManagement { + callback attribute ESAType; + callback attribute ESACanGenerate; + callback attribute ESAState; + callback attribute absMinPower; + callback attribute absMaxPower; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 4; + } + + server cluster PowerTopology { + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster DeviceEnergyManagementMode { + callback attribute supportedModes; + callback attribute currentMode; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 2; + + handle command ChangeToMode; + handle command ChangeToModeResponse; + } +} +endpoint 2 { + device type ma_tempsensor = 770, version 1; + + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x00; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 4; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster TemperatureMeasurement { + ram attribute measuredValue default = 6000; + ram attribute minMeasuredValue default = 0; + ram attribute maxMeasuredValue default = 90; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } +} +endpoint 3 { + device type ma_tempsensor = 770, version 1; + + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x00; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 4; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster TemperatureMeasurement { + ram attribute measuredValue default = 4000; + ram attribute minMeasuredValue default = 0; + ram attribute maxMeasuredValue default = 90; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } +} + + diff --git a/examples/chef/devices/rootnode_heatpump_87ivjRAECh.zap b/examples/chef/devices/rootnode_heatpump_87ivjRAECh.zap new file mode 100644 index 00000000000000..e05f413a910b46 --- /dev/null +++ b/examples/chef/devices/rootnode_heatpump_87ivjRAECh.zap @@ -0,0 +1,4387 @@ +{ + "fileFormat": 2, + "featureLevel": 104, + "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", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 22, + "profileId": 259, + "label": "MA-rootdevice", + "name": "MA-rootdevice", + "deviceTypeOrder": 0 + } + ], + "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": 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": "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": "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": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Basic Information", + "code": 40, + "mfgCode": null, + "define": "BASIC_INFORMATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DataModelRevision", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "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": 1, + "maxInterval": 65534, + "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": 1, + "maxInterval": 65534, + "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": 1, + "maxInterval": 65534, + "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": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NodeLabel", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "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": 1, + "maxInterval": 65534, + "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": 1, + "maxInterval": 65534, + "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": 1, + "maxInterval": 65534, + "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": 1, + "maxInterval": 65534, + "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": 1, + "maxInterval": 65534, + "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": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CapabilityMinima", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "CapabilityMinimaStruct", + "included": 1, + "storageOption": "External", + "singleton": 1, + "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": "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": 1, + "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": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Localization Configuration", + "code": 43, + "mfgCode": null, + "define": "LOCALIZATION_CONFIGURATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "ActiveLocale", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "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 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": 1, + "maxInterval": 65534, + "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": 1, + "maxInterval": 65534, + "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": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 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": "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": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "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": "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": 1, + "maxInterval": 65534, + "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": 1, + "maxInterval": 65534, + "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": "TestEventTriggersEnabled", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "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": "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": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "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": 1, + "maxInterval": 65534, + "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": 1, + "maxInterval": 65534, + "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": 1, + "maxInterval": 65534, + "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": 1, + "maxInterval": 65534, + "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": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "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": 1, + "maxInterval": 65534, + "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": 1, + "maxInterval": 65534, + "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": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 2, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 777, + "profileId": 259, + "label": "MA-heatpump", + "name": "MA-heatpump", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 777, + "profileId": 259, + "label": "MA-heatpump", + "name": "MA-heatpump", + "deviceTypeOrder": 0 + }, + { + "code": 17, + "profileId": 259, + "label": "MA-powersource", + "name": "MA-powersource", + "deviceTypeOrder": 1 + }, + { + "code": 1296, + "profileId": 259, + "label": "MA-electricalsensor", + "name": "MA-electricalsensor", + "deviceTypeOrder": 2 + }, + { + "code": 1293, + "profileId": 259, + "label": "Device Energy Management", + "name": "Device Energy Management", + "deviceTypeOrder": 3 + } + ], + "deviceVersions": [ + 1, + 1, + 1, + 1 + ], + "deviceIdentifiers": [ + 777, + 17, + 1296, + 1293 + ], + "deviceTypeName": "MA-heatpump", + "deviceTypeCode": 777, + "deviceTypeProfileId": 259, + "clusters": [ + { + "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 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "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": 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": "TagList", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Power Source", + "code": 47, + "mfgCode": null, + "define": "POWER_SOURCE_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Status", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "PowerSourceStatusEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Order", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Description", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EndpointList", + "code": 31, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Electrical Power Measurement", + "code": 144, + "mfgCode": null, + "define": "ELECTRICAL_POWER_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "PowerMode", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "PowerModeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NumberOfMeasurementTypes", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Accuracy", + "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": "Voltage", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "voltage_mv", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveCurrent", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "amperage_ma", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActivePower", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "power_mw", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Electrical Energy Measurement", + "code": 145, + "mfgCode": null, + "define": "ELECTRICAL_ENERGY_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Accuracy", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "MeasurementAccuracyStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CumulativeEnergyImported", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "EnergyMeasurementStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Device Energy Management", + "code": 152, + "mfgCode": null, + "define": "DEVICE_ENERGY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "apiMaturity": "provisional", + "attributes": [ + { + "name": "ESAType", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "ESATypeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ESACanGenerate", + "code": 1, + "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": "ESAState", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "ESAStateEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AbsMinPower", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "power_mw", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AbsMaxPower", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "power_mw", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Power Topology", + "code": 156, + "mfgCode": null, + "define": "POWER_TOPOLOGY_CLUSTER", + "side": "server", + "enabled": 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": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Device Energy Management Mode", + "code": 159, + "mfgCode": null, + "define": "DEVICE_ENERGY_MANAGEMENT_MODE_CLUSTER", + "side": "server", + "enabled": 1, + "apiMaturity": "provisional", + "commands": [ + { + "name": "ChangeToMode", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ChangeToModeResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "SupportedModes", + "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": "CurrentMode", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Thermostat", + "code": 513, + "mfgCode": null, + "define": "THERMOSTAT_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "SetpointRaiseLower", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + } + ] + } + ] + }, + { + "id": 3, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 770, + "profileId": 259, + "label": "MA-tempsensor", + "name": "MA-tempsensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 770, + "profileId": 259, + "label": "MA-tempsensor", + "name": "MA-tempsensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 770 + ], + "deviceTypeName": "MA-tempsensor", + "deviceTypeCode": 770, + "deviceTypeProfileId": 259, + "clusters": [ + { + "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": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "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": 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": "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": "Temperature Measurement", + "code": 1026, + "mfgCode": null, + "define": "TEMPERATURE_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "temperature", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "6000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "temperature", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "temperature", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "90", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 4, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 770, + "profileId": 259, + "label": "MA-tempsensor", + "name": "MA-tempsensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 770, + "profileId": 259, + "label": "MA-tempsensor", + "name": "MA-tempsensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 770 + ], + "deviceTypeName": "MA-tempsensor", + "deviceTypeCode": 770, + "deviceTypeProfileId": 259, + "clusters": [ + { + "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": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "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": 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": "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": "Temperature Measurement", + "code": 1026, + "mfgCode": null, + "define": "TEMPERATURE_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "temperature", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "temperature", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "temperature", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "90", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + } + ], + "endpoints": [ + { + "endpointTypeName": "MA-rootdevice", + "endpointTypeIndex": 0, + "profileId": 259, + "endpointId": 0, + "networkId": null, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 1, + "profileId": 259, + "endpointId": 1, + "networkId": 0, + "parentEndpointIdentifier": 0 + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 2, + "profileId": 259, + "endpointId": 2, + "networkId": 0, + "parentEndpointIdentifier": 0 + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 3, + "profileId": 259, + "endpointId": 3, + "networkId": 0, + "parentEndpointIdentifier": null + } + ] +} + + diff --git a/examples/chef/devices/rootnode_humiditysensor_Xyj4gda6Hb.matter b/examples/chef/devices/rootnode_humiditysensor_Xyj4gda6Hb.matter index e633b0f2bebc4c..a401aed997c79d 100644 --- a/examples/chef/devices/rootnode_humiditysensor_Xyj4gda6Hb.matter +++ b/examples/chef/devices/rootnode_humiditysensor_Xyj4gda6Hb.matter @@ -1245,7 +1245,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_laundrydryer_01796fe396.matter b/examples/chef/devices/rootnode_laundrydryer_01796fe396.matter index bb05b243f8283d..7960936439f774 100644 --- a/examples/chef/devices/rootnode_laundrydryer_01796fe396.matter +++ b/examples/chef/devices/rootnode_laundrydryer_01796fe396.matter @@ -1061,7 +1061,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** 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. */ diff --git a/examples/chef/devices/rootnode_laundrywasher_fb10d238c8.matter b/examples/chef/devices/rootnode_laundrywasher_fb10d238c8.matter index 2e76d3f34a3a85..c92cf98aed3b59 100644 --- a/examples/chef/devices/rootnode_laundrywasher_fb10d238c8.matter +++ b/examples/chef/devices/rootnode_laundrywasher_fb10d238c8.matter @@ -994,7 +994,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** 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. */ diff --git a/examples/chef/devices/rootnode_lightsensor_lZQycTFcJK.matter b/examples/chef/devices/rootnode_lightsensor_lZQycTFcJK.matter index 32528515cf121b..167fb98e36ece9 100644 --- a/examples/chef/devices/rootnode_lightsensor_lZQycTFcJK.matter +++ b/examples/chef/devices/rootnode_lightsensor_lZQycTFcJK.matter @@ -1245,7 +1245,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_occupancysensor_iHyVgifZuo.matter b/examples/chef/devices/rootnode_occupancysensor_iHyVgifZuo.matter index 04cf5fb646d7bb..2d35dcb2f8840d 100644 --- a/examples/chef/devices/rootnode_occupancysensor_iHyVgifZuo.matter +++ b/examples/chef/devices/rootnode_occupancysensor_iHyVgifZuo.matter @@ -1245,7 +1245,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_onofflight_bbs1b7IaOV.matter b/examples/chef/devices/rootnode_onofflight_bbs1b7IaOV.matter index c4cc8357d94ef8..f91a4df653c42f 100644 --- a/examples/chef/devices/rootnode_onofflight_bbs1b7IaOV.matter +++ b/examples/chef/devices/rootnode_onofflight_bbs1b7IaOV.matter @@ -1442,7 +1442,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_onofflight_samplemei.matter b/examples/chef/devices/rootnode_onofflight_samplemei.matter index 32b351b6e81791..174f5c119469fa 100644 --- a/examples/chef/devices/rootnode_onofflight_samplemei.matter +++ b/examples/chef/devices/rootnode_onofflight_samplemei.matter @@ -1442,7 +1442,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_onofflightswitch_FsPlMr090Q.matter b/examples/chef/devices/rootnode_onofflightswitch_FsPlMr090Q.matter index 81fb81958f8f5d..190a3a4edc4e86 100644 --- a/examples/chef/devices/rootnode_onofflightswitch_FsPlMr090Q.matter +++ b/examples/chef/devices/rootnode_onofflightswitch_FsPlMr090Q.matter @@ -1317,7 +1317,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_onoffpluginunit_Wtf8ss5EBY.matter b/examples/chef/devices/rootnode_onoffpluginunit_Wtf8ss5EBY.matter index 94414ae3165662..4da57e8e1b3686 100644 --- a/examples/chef/devices/rootnode_onoffpluginunit_Wtf8ss5EBY.matter +++ b/examples/chef/devices/rootnode_onoffpluginunit_Wtf8ss5EBY.matter @@ -1317,7 +1317,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_pressuresensor_s0qC9wLH4k.matter b/examples/chef/devices/rootnode_pressuresensor_s0qC9wLH4k.matter index 1bc2e8726e1083..3d493f926633f9 100644 --- a/examples/chef/devices/rootnode_pressuresensor_s0qC9wLH4k.matter +++ b/examples/chef/devices/rootnode_pressuresensor_s0qC9wLH4k.matter @@ -1245,7 +1245,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_pump_5f904818cc.matter b/examples/chef/devices/rootnode_pump_5f904818cc.matter index 8cd43edf190fd9..741dda60e307bc 100644 --- a/examples/chef/devices/rootnode_pump_5f904818cc.matter +++ b/examples/chef/devices/rootnode_pump_5f904818cc.matter @@ -1044,7 +1044,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** Commands to trigger a Node to allow a new Administrator to commission it. */ diff --git a/examples/chef/devices/rootnode_pump_a811bb33a0.matter b/examples/chef/devices/rootnode_pump_a811bb33a0.matter index 5b2371526d9a59..50c2dd31633bd9 100644 --- a/examples/chef/devices/rootnode_pump_a811bb33a0.matter +++ b/examples/chef/devices/rootnode_pump_a811bb33a0.matter @@ -1044,7 +1044,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** Commands to trigger a Node to allow a new Administrator to commission it. */ diff --git a/examples/chef/devices/rootnode_refrigerator_temperaturecontrolledcabinet_temperaturecontrolledcabinet_ffdb696680.matter b/examples/chef/devices/rootnode_refrigerator_temperaturecontrolledcabinet_temperaturecontrolledcabinet_ffdb696680.matter index bfbd486f6e0d01..686d67e3fa49aa 100644 --- a/examples/chef/devices/rootnode_refrigerator_temperaturecontrolledcabinet_temperaturecontrolledcabinet_ffdb696680.matter +++ b/examples/chef/devices/rootnode_refrigerator_temperaturecontrolledcabinet_temperaturecontrolledcabinet_ffdb696680.matter @@ -922,7 +922,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** 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. */ diff --git a/examples/chef/devices/rootnode_roboticvacuumcleaner_1807ff0c49.matter b/examples/chef/devices/rootnode_roboticvacuumcleaner_1807ff0c49.matter index dbc56cd15e5d26..9abd9b19729f7d 100644 --- a/examples/chef/devices/rootnode_roboticvacuumcleaner_1807ff0c49.matter +++ b/examples/chef/devices/rootnode_roboticvacuumcleaner_1807ff0c49.matter @@ -1329,7 +1329,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** Commands to trigger a Node to allow a new Administrator to commission it. */ diff --git a/examples/chef/devices/rootnode_roomairconditioner_9cf3607804.matter b/examples/chef/devices/rootnode_roomairconditioner_9cf3607804.matter index 467ad0c462767d..bb4a46da845f29 100644 --- a/examples/chef/devices/rootnode_roomairconditioner_9cf3607804.matter +++ b/examples/chef/devices/rootnode_roomairconditioner_9cf3607804.matter @@ -1142,7 +1142,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** Commands to trigger a Node to allow a new Administrator to commission it. */ diff --git a/examples/chef/devices/rootnode_smokecoalarm_686fe0dcb8.matter b/examples/chef/devices/rootnode_smokecoalarm_686fe0dcb8.matter index b7e31f0bdcbf1c..f64237210be6fc 100644 --- a/examples/chef/devices/rootnode_smokecoalarm_686fe0dcb8.matter +++ b/examples/chef/devices/rootnode_smokecoalarm_686fe0dcb8.matter @@ -1329,7 +1329,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** Commands to trigger a Node to allow a new Administrator to commission it. */ diff --git a/examples/chef/devices/rootnode_speaker_RpzeXdimqA.matter b/examples/chef/devices/rootnode_speaker_RpzeXdimqA.matter index c5a1ccc522a4c3..ef250cb35245ec 100644 --- a/examples/chef/devices/rootnode_speaker_RpzeXdimqA.matter +++ b/examples/chef/devices/rootnode_speaker_RpzeXdimqA.matter @@ -1365,7 +1365,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_temperaturesensor_Qy1zkNW7c3.matter b/examples/chef/devices/rootnode_temperaturesensor_Qy1zkNW7c3.matter index 6199388887e069..e26a62dfd2f1b1 100644 --- a/examples/chef/devices/rootnode_temperaturesensor_Qy1zkNW7c3.matter +++ b/examples/chef/devices/rootnode_temperaturesensor_Qy1zkNW7c3.matter @@ -1245,7 +1245,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter b/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter index 79930324883042..549c98f930b62b 100644 --- a/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter +++ b/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter @@ -1306,7 +1306,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/devices/rootnode_waterleakdetector_0b067acfa3.matter b/examples/chef/devices/rootnode_waterleakdetector_0b067acfa3.matter index 1ea6c421aba885..67f17e7ab95b4c 100644 --- a/examples/chef/devices/rootnode_waterleakdetector_0b067acfa3.matter +++ b/examples/chef/devices/rootnode_waterleakdetector_0b067acfa3.matter @@ -1329,7 +1329,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** Commands to trigger a Node to allow a new Administrator to commission it. */ diff --git a/examples/chef/devices/rootnode_watervalve_6bb39f1f67.matter b/examples/chef/devices/rootnode_watervalve_6bb39f1f67.matter index 0e4ffe5dc8ee14..7105d9904673da 100644 --- a/examples/chef/devices/rootnode_watervalve_6bb39f1f67.matter +++ b/examples/chef/devices/rootnode_watervalve_6bb39f1f67.matter @@ -1269,7 +1269,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** Commands to trigger a Node to allow a new Administrator to commission it. */ diff --git a/examples/chef/devices/rootnode_windowcovering_RLCxaGi9Yx.matter b/examples/chef/devices/rootnode_windowcovering_RLCxaGi9Yx.matter index 0f1d25c571179f..30b58d92053827 100644 --- a/examples/chef/devices/rootnode_windowcovering_RLCxaGi9Yx.matter +++ b/examples/chef/devices/rootnode_windowcovering_RLCxaGi9Yx.matter @@ -1245,7 +1245,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/chef/sample_app_util/matter_device_types.json b/examples/chef/sample_app_util/matter_device_types.json index 3390dec8a584d7..60e307f0dcf70a 100644 --- a/examples/chef/sample_app_util/matter_device_types.json +++ b/examples/chef/sample_app_util/matter_device_types.json @@ -51,5 +51,6 @@ "Dishwasher": 117, "Smoke CO Alarm": 118, "Water Valve": 66, - "Water Leak Detector": 67 + "Water Leak Detector": 67, + "HeatPump": 777 } diff --git a/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter b/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter index 55820ca5377f4f..fed65931ab4d49 100644 --- a/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter +++ b/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter @@ -1224,7 +1224,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter index 899dc159a0baaa..f3027e97812e05 100644 --- a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter +++ b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter @@ -1147,7 +1147,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter index 3c88ebe1202775..6fd0de001695a9 100644 --- a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter +++ b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter @@ -1147,7 +1147,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/dishwasher-app/dishwasher-common/dishwasher-app.matter b/examples/dishwasher-app/dishwasher-common/dishwasher-app.matter index 6ee107a38f063e..8e3096b7a08efc 100644 --- a/examples/dishwasher-app/dishwasher-common/dishwasher-app.matter +++ b/examples/dishwasher-app/dishwasher-common/dishwasher-app.matter @@ -1070,7 +1070,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** 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. */ diff --git a/examples/dishwasher-app/silabs/data_model/dishwasher-thread-app.matter b/examples/dishwasher-app/silabs/data_model/dishwasher-thread-app.matter index 93222a8580e5ba..87d6dca00e4391 100644 --- a/examples/dishwasher-app/silabs/data_model/dishwasher-thread-app.matter +++ b/examples/dishwasher-app/silabs/data_model/dishwasher-thread-app.matter @@ -1255,7 +1255,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/dishwasher-app/silabs/data_model/dishwasher-wifi-app.matter b/examples/dishwasher-app/silabs/data_model/dishwasher-wifi-app.matter index 24abdb39862888..e2daba3687f4fa 100644 --- a/examples/dishwasher-app/silabs/data_model/dishwasher-wifi-app.matter +++ b/examples/dishwasher-app/silabs/data_model/dishwasher-wifi-app.matter @@ -1255,7 +1255,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/energy-management-app/energy-management-common/energy-management-app.matter b/examples/energy-management-app/energy-management-common/energy-management-app.matter index bdcbe117c8344b..d7db07d6c94993 100644 --- a/examples/energy-management-app/energy-management-common/energy-management-app.matter +++ b/examples/energy-management-app/energy-management-common/energy-management-app.matter @@ -1292,7 +1292,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** Commands to trigger a Node to allow a new Administrator to commission it. */ diff --git a/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.matter b/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.matter index 06e76db5ecee1a..2d1148bef83cd8 100644 --- a/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.matter +++ b/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.matter @@ -1118,7 +1118,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/fabric-sync/admin/FabricAdmin.cpp b/examples/fabric-sync/admin/FabricAdmin.cpp index 1716692691451a..3c6edadff5268e 100644 --- a/examples/fabric-sync/admin/FabricAdmin.cpp +++ b/examples/fabric-sync/admin/FabricAdmin.cpp @@ -16,8 +16,10 @@ */ #include "FabricAdmin.h" + #include <AppMain.h> #include <CommissionerMain.h> +#include <app/server/Server.h> #include <bridge/include/FabricBridge.h> #include <controller/CHIPDeviceControllerFactory.h> @@ -45,9 +47,8 @@ CHIP_ERROR FabricAdmin::Init() VerifyOrReturnError(engine != nullptr, CHIP_ERROR_INCORRECT_STATE); ReturnLogErrorOnFailure(IcdManager::Instance().Init(&sICDClientStorage, engine)); - auto exchangeMgr = Controller::DeviceControllerFactory::GetInstance().GetSystemState()->ExchangeMgr(); - VerifyOrReturnError(exchangeMgr != nullptr, CHIP_ERROR_INCORRECT_STATE); - ReturnLogErrorOnFailure(sCheckInHandler.Init(exchangeMgr, &sICDClientStorage, &IcdManager::Instance(), engine)); + ReturnLogErrorOnFailure(sCheckInHandler.Init(&chip::Server::GetInstance().GetExchangeManager(), &sICDClientStorage, + &IcdManager::Instance(), engine)); ReturnLogErrorOnFailure(PairingManager::Instance().Init(GetDeviceCommissioner())); diff --git a/examples/fabric-sync/bridge/fabric-bridge.matter b/examples/fabric-sync/bridge/fabric-bridge.matter index 06e76db5ecee1a..2d1148bef83cd8 100644 --- a/examples/fabric-sync/bridge/fabric-bridge.matter +++ b/examples/fabric-sync/bridge/fabric-bridge.matter @@ -1118,7 +1118,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter b/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter index 37b7786af95b80..678ca3b0f4082f 100644 --- a/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter +++ b/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter @@ -1360,7 +1360,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/light-switch-app/light-switch-common/icd-lit-light-switch-app.matter b/examples/light-switch-app/light-switch-common/icd-lit-light-switch-app.matter index 67ed0ab5715709..2e3827d9ae2268 100644 --- a/examples/light-switch-app/light-switch-common/icd-lit-light-switch-app.matter +++ b/examples/light-switch-app/light-switch-common/icd-lit-light-switch-app.matter @@ -1367,7 +1367,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ @@ -2438,7 +2438,7 @@ provisional cluster ScenesManagement = 98 { /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */ fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6; /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */ - fabric command CopyScene(CopySceneRequest): CopySceneResponse = 64; + fabric command access(invoke: manage) CopyScene(CopySceneRequest): CopySceneResponse = 64; } /** Attributes and commands for controlling the color properties of a color-capable light. */ diff --git a/examples/light-switch-app/light-switch-common/light-switch-app.matter b/examples/light-switch-app/light-switch-common/light-switch-app.matter index 07910e283f3a0a..b50c93ec27d357 100644 --- a/examples/light-switch-app/light-switch-common/light-switch-app.matter +++ b/examples/light-switch-app/light-switch-common/light-switch-app.matter @@ -1367,7 +1367,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ @@ -2438,7 +2438,7 @@ provisional cluster ScenesManagement = 98 { /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */ fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6; /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */ - fabric command CopyScene(CopySceneRequest): CopySceneResponse = 64; + fabric command access(invoke: manage) CopyScene(CopySceneRequest): CopySceneResponse = 64; } /** Attributes and commands for controlling the color properties of a color-capable light. */ diff --git a/examples/light-switch-app/qpg/zap/switch.matter b/examples/light-switch-app/qpg/zap/switch.matter index 03e0f51ad0830d..2eb47604f38781 100644 --- a/examples/light-switch-app/qpg/zap/switch.matter +++ b/examples/light-switch-app/qpg/zap/switch.matter @@ -1751,7 +1751,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ @@ -2555,7 +2555,7 @@ provisional cluster ScenesManagement = 98 { /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */ fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6; /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */ - fabric command CopyScene(CopySceneRequest): CopySceneResponse = 64; + fabric command access(invoke: manage) CopyScene(CopySceneRequest): CopySceneResponse = 64; } /** Attributes and commands for controlling the color properties of a color-capable light. */ diff --git a/examples/lighting-app-data-mode-no-unique-id/lighting-common/lighting-app.matter b/examples/lighting-app-data-mode-no-unique-id/lighting-common/lighting-app.matter index e8e99173b85a17..4c7e31646de0fa 100644 --- a/examples/lighting-app-data-mode-no-unique-id/lighting-common/lighting-app.matter +++ b/examples/lighting-app-data-mode-no-unique-id/lighting-common/lighting-app.matter @@ -1421,7 +1421,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ @@ -2246,7 +2246,7 @@ provisional cluster ScenesManagement = 98 { /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */ fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6; /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */ - fabric command CopyScene(CopySceneRequest): CopySceneResponse = 64; + fabric command access(invoke: manage) CopyScene(CopySceneRequest): CopySceneResponse = 64; } /** Attributes and commands for controlling the color properties of a color-capable light. */ diff --git a/examples/lighting-app/bouffalolab/data_model/lighting-app-ethernet.matter b/examples/lighting-app/bouffalolab/data_model/lighting-app-ethernet.matter index 7ce2b52c2db8a2..277e8bc07c66ea 100644 --- a/examples/lighting-app/bouffalolab/data_model/lighting-app-ethernet.matter +++ b/examples/lighting-app/bouffalolab/data_model/lighting-app-ethernet.matter @@ -1421,7 +1421,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/lighting-app/bouffalolab/data_model/lighting-app-thread.matter b/examples/lighting-app/bouffalolab/data_model/lighting-app-thread.matter index bc48c4056b2b45..e7a1fd8a68f6aa 100644 --- a/examples/lighting-app/bouffalolab/data_model/lighting-app-thread.matter +++ b/examples/lighting-app/bouffalolab/data_model/lighting-app-thread.matter @@ -1421,7 +1421,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/lighting-app/bouffalolab/data_model/lighting-app-wifi.matter b/examples/lighting-app/bouffalolab/data_model/lighting-app-wifi.matter index d896f4308f956d..94444d34e7f16b 100644 --- a/examples/lighting-app/bouffalolab/data_model/lighting-app-wifi.matter +++ b/examples/lighting-app/bouffalolab/data_model/lighting-app-wifi.matter @@ -1421,7 +1421,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/lighting-app/lighting-common/lighting-app.matter b/examples/lighting-app/lighting-common/lighting-app.matter index 769d929e580836..53f31a35e85a38 100644 --- a/examples/lighting-app/lighting-common/lighting-app.matter +++ b/examples/lighting-app/lighting-common/lighting-app.matter @@ -1421,7 +1421,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ @@ -2246,7 +2246,7 @@ provisional cluster ScenesManagement = 98 { /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */ fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6; /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */ - fabric command CopyScene(CopySceneRequest): CopySceneResponse = 64; + fabric command access(invoke: manage) CopyScene(CopySceneRequest): CopySceneResponse = 64; } /** Attributes and commands for controlling the color properties of a color-capable light. */ diff --git a/examples/lighting-app/nxp/zap/lighting-on-off.matter b/examples/lighting-app/nxp/zap/lighting-on-off.matter index c80d7cfa191a0e..a3f91b06d14683 100644 --- a/examples/lighting-app/nxp/zap/lighting-on-off.matter +++ b/examples/lighting-app/nxp/zap/lighting-on-off.matter @@ -1374,7 +1374,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/lighting-app/qpg/zap/light.matter b/examples/lighting-app/qpg/zap/light.matter index fbefaabad5bb1f..f6ac363e2f3e98 100644 --- a/examples/lighting-app/qpg/zap/light.matter +++ b/examples/lighting-app/qpg/zap/light.matter @@ -1421,7 +1421,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/lighting-app/silabs/data_model/lighting-thread-app.matter b/examples/lighting-app/silabs/data_model/lighting-thread-app.matter index 9fb02976f031d5..7a2429dad1428c 100644 --- a/examples/lighting-app/silabs/data_model/lighting-thread-app.matter +++ b/examples/lighting-app/silabs/data_model/lighting-thread-app.matter @@ -1374,7 +1374,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) 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 */ @@ -1950,7 +1950,7 @@ provisional cluster ScenesManagement = 98 { /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */ fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6; /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */ - fabric command CopyScene(CopySceneRequest): CopySceneResponse = 64; + fabric command access(invoke: manage) CopyScene(CopySceneRequest): CopySceneResponse = 64; } /** Attributes and commands for controlling the color properties of a color-capable light. */ diff --git a/examples/lighting-app/silabs/data_model/lighting-wifi-app.matter b/examples/lighting-app/silabs/data_model/lighting-wifi-app.matter index 1619fc9622caf4..83614e8cc918d7 100644 --- a/examples/lighting-app/silabs/data_model/lighting-wifi-app.matter +++ b/examples/lighting-app/silabs/data_model/lighting-wifi-app.matter @@ -1680,7 +1680,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ @@ -2241,7 +2241,7 @@ provisional cluster ScenesManagement = 98 { /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */ fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6; /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */ - fabric command CopyScene(CopySceneRequest): CopySceneResponse = 64; + fabric command access(invoke: manage) CopyScene(CopySceneRequest): CopySceneResponse = 64; } /** Attributes and commands for controlling the color properties of a color-capable light. */ diff --git a/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter b/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter index 3c51bf0b1bdf73..a54445b68294e6 100644 --- a/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter +++ b/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter @@ -1126,7 +1126,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) 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 */ diff --git a/examples/lock-app/lock-common/lock-app.matter b/examples/lock-app/lock-common/lock-app.matter index 650458149c4620..0220deb75b9797 100644 --- a/examples/lock-app/lock-common/lock-app.matter +++ b/examples/lock-app/lock-common/lock-app.matter @@ -1432,7 +1432,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/lock-app/nxp/zap/lock-app.matter b/examples/lock-app/nxp/zap/lock-app.matter index 281f19877b8eab..da021c44546d03 100644 --- a/examples/lock-app/nxp/zap/lock-app.matter +++ b/examples/lock-app/nxp/zap/lock-app.matter @@ -1164,7 +1164,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/lock-app/qpg/zap/lock.matter b/examples/lock-app/qpg/zap/lock.matter index 74ab5d744a5702..f2c759e8f7fe70 100644 --- a/examples/lock-app/qpg/zap/lock.matter +++ b/examples/lock-app/qpg/zap/lock.matter @@ -1224,7 +1224,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/lock-app/silabs/data_model/lock-app.matter b/examples/lock-app/silabs/data_model/lock-app.matter index 8a7695c75d6c87..ee3cc824b79d14 100644 --- a/examples/lock-app/silabs/data_model/lock-app.matter +++ b/examples/lock-app/silabs/data_model/lock-app.matter @@ -1432,7 +1432,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/microwave-oven-app/microwave-oven-common/microwave-oven-app.matter b/examples/microwave-oven-app/microwave-oven-common/microwave-oven-app.matter index fbc5c3625aad5f..bf5f45f4027a80 100644 --- a/examples/microwave-oven-app/microwave-oven-common/microwave-oven-app.matter +++ b/examples/microwave-oven-app/microwave-oven-common/microwave-oven-app.matter @@ -990,7 +990,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** 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. */ diff --git a/examples/network-manager-app/network-manager-common/network-manager-app.matter b/examples/network-manager-app/network-manager-common/network-manager-app.matter index 4847e0ff9e22c2..4e3c7d01aa0bc4 100644 --- a/examples/network-manager-app/network-manager-common/network-manager-app.matter +++ b/examples/network-manager-app/network-manager-common/network-manager-app.matter @@ -896,7 +896,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) 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 */ diff --git a/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter b/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter index 7538f304f356d4..9619f70767810d 100644 --- a/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter +++ b/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter @@ -1097,7 +1097,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** Commands to trigger a Node to allow a new Administrator to commission it. */ diff --git a/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter b/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter index 5269b6e7094558..2c4f638037a3f2 100644 --- a/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter +++ b/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter @@ -1249,7 +1249,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** Commands to trigger a Node to allow a new Administrator to commission it. */ diff --git a/examples/placeholder/linux/apps/app1/config.matter b/examples/placeholder/linux/apps/app1/config.matter index a6a1aa5c7f5a64..6bc47afef7015b 100644 --- a/examples/placeholder/linux/apps/app1/config.matter +++ b/examples/placeholder/linux/apps/app1/config.matter @@ -2125,7 +2125,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ @@ -3514,7 +3514,7 @@ provisional cluster ScenesManagement = 98 { /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */ fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6; /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */ - fabric command CopyScene(CopySceneRequest): CopySceneResponse = 64; + fabric command access(invoke: manage) CopyScene(CopySceneRequest): CopySceneResponse = 64; } /** An interface to a generic way to secure a door */ @@ -9645,13 +9645,13 @@ endpoint 1 { ram attribute occupancy; ram attribute occupancySensorType; ram attribute occupancySensorTypeBitmap; - ram attribute PIROccupiedToUnoccupiedDelay default = 0x00; + callback attribute PIROccupiedToUnoccupiedDelay; ram attribute PIRUnoccupiedToOccupiedDelay default = 0x00; ram attribute PIRUnoccupiedToOccupiedThreshold default = 1; - ram attribute ultrasonicOccupiedToUnoccupiedDelay default = 0x00; + callback attribute ultrasonicOccupiedToUnoccupiedDelay; ram attribute ultrasonicUnoccupiedToOccupiedDelay default = 0x00; ram attribute ultrasonicUnoccupiedToOccupiedThreshold default = 1; - ram attribute physicalContactOccupiedToUnoccupiedDelay default = 0x00; + callback attribute physicalContactOccupiedToUnoccupiedDelay; ram attribute physicalContactUnoccupiedToOccupiedDelay default = 0x00; ram attribute physicalContactUnoccupiedToOccupiedThreshold default = 1; callback attribute featureMap; diff --git a/examples/placeholder/linux/apps/app2/config.matter b/examples/placeholder/linux/apps/app2/config.matter index 0373748d9de69e..9b116eb8ba7780 100644 --- a/examples/placeholder/linux/apps/app2/config.matter +++ b/examples/placeholder/linux/apps/app2/config.matter @@ -2082,7 +2082,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ @@ -3471,7 +3471,7 @@ provisional cluster ScenesManagement = 98 { /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */ fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6; /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */ - fabric command CopyScene(CopySceneRequest): CopySceneResponse = 64; + fabric command access(invoke: manage) CopyScene(CopySceneRequest): CopySceneResponse = 64; } /** An interface to a generic way to secure a door */ @@ -9540,13 +9540,13 @@ endpoint 1 { ram attribute occupancy; ram attribute occupancySensorType; ram attribute occupancySensorTypeBitmap; - ram attribute PIROccupiedToUnoccupiedDelay default = 0x00; + callback attribute PIROccupiedToUnoccupiedDelay; ram attribute PIRUnoccupiedToOccupiedDelay default = 0x00; ram attribute PIRUnoccupiedToOccupiedThreshold default = 1; - ram attribute ultrasonicOccupiedToUnoccupiedDelay default = 0x00; + callback attribute ultrasonicOccupiedToUnoccupiedDelay; ram attribute ultrasonicUnoccupiedToOccupiedDelay default = 0x00; ram attribute ultrasonicUnoccupiedToOccupiedThreshold default = 1; - ram attribute physicalContactOccupiedToUnoccupiedDelay default = 0x00; + callback attribute physicalContactOccupiedToUnoccupiedDelay; ram attribute physicalContactUnoccupiedToOccupiedDelay default = 0x00; ram attribute physicalContactUnoccupiedToOccupiedThreshold default = 1; callback attribute featureMap; diff --git a/examples/pump-app/pump-common/pump-app.matter b/examples/pump-app/pump-common/pump-app.matter index d4ac8e35a3c9b2..a07feba84c3886 100644 --- a/examples/pump-app/pump-common/pump-app.matter +++ b/examples/pump-app/pump-common/pump-app.matter @@ -1318,7 +1318,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) 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 */ diff --git a/examples/pump-app/silabs/data_model/pump-thread-app.matter b/examples/pump-app/silabs/data_model/pump-thread-app.matter index 7d730d759c139a..c56d83fc2bc844 100644 --- a/examples/pump-app/silabs/data_model/pump-thread-app.matter +++ b/examples/pump-app/silabs/data_model/pump-thread-app.matter @@ -1318,7 +1318,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) 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 */ diff --git a/examples/pump-app/silabs/data_model/pump-wifi-app.matter b/examples/pump-app/silabs/data_model/pump-wifi-app.matter index 7d730d759c139a..c56d83fc2bc844 100644 --- a/examples/pump-app/silabs/data_model/pump-wifi-app.matter +++ b/examples/pump-app/silabs/data_model/pump-wifi-app.matter @@ -1318,7 +1318,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) 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 */ diff --git a/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter b/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter index a7c2ebcd0fbbdf..c4d91f94c05faf 100644 --- a/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter +++ b/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter @@ -1193,7 +1193,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) 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 */ diff --git a/examples/refrigerator-app/refrigerator-common/refrigerator-app.matter b/examples/refrigerator-app/refrigerator-common/refrigerator-app.matter index f3149e01afe4c9..b99237cdfd6036 100644 --- a/examples/refrigerator-app/refrigerator-common/refrigerator-app.matter +++ b/examples/refrigerator-app/refrigerator-common/refrigerator-app.matter @@ -922,7 +922,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** 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. */ diff --git a/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter b/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter index 38c88d543ec6a2..838776ac2a823b 100644 --- a/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter +++ b/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter @@ -1172,7 +1172,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) 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 */ diff --git a/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter b/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter index acb85ae85a4066..530f00d32fd7ab 100644 --- a/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter +++ b/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter @@ -1172,7 +1172,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** 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. */ diff --git a/examples/rvc-app/rvc-common/rvc-app.matter b/examples/rvc-app/rvc-common/rvc-app.matter index 0db897b3f7bd23..512f54cfd7fe52 100644 --- a/examples/rvc-app/rvc-common/rvc-app.matter +++ b/examples/rvc-app/rvc-common/rvc-app.matter @@ -993,7 +993,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** Commands to trigger a Node to allow a new Administrator to commission it. */ diff --git a/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter b/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter index d4d7f8c93ed3c9..3bd4cae0d926b7 100644 --- a/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter +++ b/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter @@ -1483,7 +1483,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/temperature-measurement-app/temperature-measurement-common/temperature-measurement.matter b/examples/temperature-measurement-app/temperature-measurement-common/temperature-measurement.matter index 17ab13992cbdc3..75105aaad3c7da 100644 --- a/examples/temperature-measurement-app/temperature-measurement-common/temperature-measurement.matter +++ b/examples/temperature-measurement-app/temperature-measurement-common/temperature-measurement.matter @@ -1123,7 +1123,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/thermostat/nxp/common/main/AppTask.cpp b/examples/thermostat/nxp/common/main/AppTask.cpp index 8e3f8f1036a2e4..583e3c3dc1bbd4 100644 --- a/examples/thermostat/nxp/common/main/AppTask.cpp +++ b/examples/thermostat/nxp/common/main/AppTask.cpp @@ -24,6 +24,10 @@ #include <app/InteractionModelEngine.h> #include <app/util/attribute-storage.h> +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include "BLEApplicationManager.h" +#endif + using namespace chip; void ThermostatApp::AppTask::PreInitMatterStack() @@ -33,6 +37,13 @@ void ThermostatApp::AppTask::PreInitMatterStack() void ThermostatApp::AppTask::PostInitMatterStack() { +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#ifdef APP_BT_DEVICE_NAME + chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName(APP_BT_DEVICE_NAME); +#endif + /* BLEApplicationManager implemented per platform or left blank */ + chip::NXP::App::BleAppMgr().Init(); +#endif chip::app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&chip::NXP::App::GetICDUtil()); } diff --git a/examples/thermostat/nxp/common/main/BleZephyrManagerApp.cpp b/examples/thermostat/nxp/common/main/BleZephyrManagerApp.cpp new file mode 100644 index 00000000000000..170ef3c4cc45ab --- /dev/null +++ b/examples/thermostat/nxp/common/main/BleZephyrManagerApp.cpp @@ -0,0 +1,100 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * Copyright 2024 NXP + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "BLEApplicationManager.h" + +#include <platform/internal/CHIPDeviceLayerInternal.h> + +#include "BLEManagerImpl.h" +#include <ble/Ble.h> +#include <platform/ConfigurationManager.h> +#include <zephyr/bluetooth/gatt.h> + +#define ADV_LEN 2 + +using namespace ::chip::DeviceLayer; +using namespace ::chip::DeviceLayer::Internal; +using namespace ::chip::NXP::App; + +BLEApplicationManager BLEApplicationManager::sInstance; + +struct ServiceData +{ + uint8_t uuid[2]; + chip::Ble::ChipBLEDeviceIdentificationInfo deviceIdInfo; +} __attribute__((packed)); + +ServiceData serviceData; +std::array<bt_data, 3> advertisingData; +std::array<bt_data, 1> scanResponseData; + +constexpr uint8_t kAdvertisingFlags = BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR; + +uint8_t manuf_data[ADV_LEN] = { + 0x25, + 0x00, +}; + +bt_uuid_16 UUID16_CHIPoBLEService = BT_UUID_INIT_16(0xFFF6); + +/** + * @brief Init BLE application manager + * + * In this example, the application manager is used to customize BLE advertising + * parameters. This example is provided for platforms with Zephyr BLE manager support. + * + * @note This example set custom Zephyr BLE manager Matter advertising parameters ( + * CONFIG_CHIP_CUSTOM_BLE_ADV_DATA for kconfig or ble_adv_data_custom for GN is set). + * To keep the advertising support for commissining, it is needed to register the whole + * adv data (adv flags + Matter adv data + custom adv data) and register scan + * response data as default adv and response data will be skipped. + * kAdvertisingFlags and manuf_data are given for examples, size of advertisingData and + * scanResponseData have to be set according to custom requirements. + * + * For custom Gatt services, APIs bt_gatt_service_register and bt_gatt_service_unregister + * could be called at application layer. It will not override Matter Gatt services but + * add new one. + * + * @note At the end of the commissioning advertising will be stopped. + * + * To start new advertising process, APIs : + * chip::DeviceLayer::BLEAdvertisingArbiter::InsertRequest + * chip::DeviceLayer::BLEAdvertisingArbiter::CancelRequest + * could be called. If InsertRequest API is called several time, only the request with the + * higher priority will be advertise. + * + */ +void BLEApplicationManager::Init(void) +{ + /* Register Matter adv data + custom adv data */ + static_assert(sizeof(serviceData) == 10, "Unexpected size of BLE advertising data!"); + const char * name = bt_get_name(); + const uint8_t nameSize = static_cast<uint8_t>(strlen(name)); + Encoding::LittleEndian::Put16(serviceData.uuid, UUID16_CHIPoBLEService.val); + chip::DeviceLayer::ConfigurationMgr().GetBLEDeviceIdentificationInfo(serviceData.deviceIdInfo); + + advertisingData[0] = BT_DATA(BT_DATA_FLAGS, &kAdvertisingFlags, sizeof(kAdvertisingFlags)); + /* Matter adv data for commissining */ + advertisingData[1] = BT_DATA(BT_DATA_SVC_DATA16, &serviceData, sizeof(serviceData)); + /* Example of custom BLE adv data */ + advertisingData[2] = BT_DATA(BT_DATA_MANUFACTURER_DATA, manuf_data, ADV_LEN); + scanResponseData[0] = BT_DATA(BT_DATA_NAME_COMPLETE, name, nameSize); + chip::DeviceLayer::Internal::BLEMgrImpl().SetCustomAdvertising(Span<bt_data>(advertisingData)); + chip::DeviceLayer::Internal::BLEMgrImpl().SetCustomScanResponse(Span<bt_data>(scanResponseData)); +} diff --git a/examples/thermostat/nxp/rt/rt1060/BUILD.gn b/examples/thermostat/nxp/rt/rt1060/BUILD.gn index e57cc01b92b47b..c365ee9d47b4ca 100644 --- a/examples/thermostat/nxp/rt/rt1060/BUILD.gn +++ b/examples/thermostat/nxp/rt/rt1060/BUILD.gn @@ -147,6 +147,22 @@ rt_executable("thermostat") { "../../common/main/main.cpp", ] + if (chip_enable_ble) { + defines += [ "APP_BT_DEVICE_NAME=\"NXP-ThermostatApp\"" ] + include_dirs += [ "${common_example_dir}/app_ble/include" ] + if (ble_adv_data_custom) { + # to customize BLE advertising data + defines += [ "CONFIG_CHIP_CUSTOM_BLE_ADV_DATA=1" ] + include_dirs += [ "${chip_root}/src/platform/nxp/common/ble_zephyr" ] + sources += [ "../../common/main/BleZephyrManagerApp.cpp" ] + } else { + # Empty implementation, default matter advertising data + sources += [ + "${common_example_dir}/app_ble/source/BLEApplicationManagerEmpty.cpp", + ] + } + } + if (chip_with_diag_logs_demo) { include_dirs += [ "${common_example_dir}/diagnostic_logs/include", diff --git a/examples/thermostat/nxp/rt/rt1060/args.gni b/examples/thermostat/nxp/rt/rt1060/args.gni index c2d91a5db7bae7..d3fc29a80c4920 100644 --- a/examples/thermostat/nxp/rt/rt1060/args.gni +++ b/examples/thermostat/nxp/rt/rt1060/args.gni @@ -14,6 +14,10 @@ import("//build_overrides/chip.gni") +# Set to true to customized BLE advertising data at application layer, +# instead of default Zephyr BLE manager implementation advertising data +ble_adv_data_custom = true + # SDK target definitions nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") nxp_sdk_driver_target = get_label_info(":sdk_driver", "label_no_toolchain") diff --git a/examples/thermostat/nxp/rt/rt1170/BUILD.gn b/examples/thermostat/nxp/rt/rt1170/BUILD.gn index abb7090f962559..3e03df43488247 100644 --- a/examples/thermostat/nxp/rt/rt1170/BUILD.gn +++ b/examples/thermostat/nxp/rt/rt1170/BUILD.gn @@ -135,6 +135,22 @@ rt_executable("thermostat") { "../../common/main/main.cpp", ] + if (chip_enable_ble) { + defines += [ "APP_BT_DEVICE_NAME=\"NXP-ThermostatApp\"" ] + include_dirs += [ "${common_example_dir}/app_ble/include" ] + if (ble_adv_data_custom) { + # to customize BLE advertising data + defines += [ "CONFIG_CHIP_CUSTOM_BLE_ADV_DATA=1" ] + include_dirs += [ "${chip_root}/src/platform/nxp/common/ble_zephyr" ] + sources += [ "../../common/main/BleZephyrManagerApp.cpp" ] + } else { + # Empty implementation, default matter advertising data + sources += [ + "${common_example_dir}/app_ble/source/BLEApplicationManagerEmpty.cpp", + ] + } + } + if (chip_with_diag_logs_demo) { include_dirs += [ "${common_example_dir}/diagnostic_logs/include", diff --git a/examples/thermostat/nxp/rt/rt1170/args.gni b/examples/thermostat/nxp/rt/rt1170/args.gni index c2d91a5db7bae7..d3fc29a80c4920 100644 --- a/examples/thermostat/nxp/rt/rt1170/args.gni +++ b/examples/thermostat/nxp/rt/rt1170/args.gni @@ -14,6 +14,10 @@ import("//build_overrides/chip.gni") +# Set to true to customized BLE advertising data at application layer, +# instead of default Zephyr BLE manager implementation advertising data +ble_adv_data_custom = true + # SDK target definitions nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") nxp_sdk_driver_target = get_label_info(":sdk_driver", "label_no_toolchain") diff --git a/examples/thermostat/nxp/rt/rw61x/BUILD.gn b/examples/thermostat/nxp/rt/rw61x/BUILD.gn index 07a58e947756c6..6dd71061c010c5 100644 --- a/examples/thermostat/nxp/rt/rw61x/BUILD.gn +++ b/examples/thermostat/nxp/rt/rw61x/BUILD.gn @@ -145,6 +145,22 @@ rt_executable("thermostat") { "../../common/main/main.cpp", ] + if (chip_enable_ble) { + defines += [ "APP_BT_DEVICE_NAME=\"NXP-ThermostatApp\"" ] + include_dirs += [ "${common_example_dir}/app_ble/include" ] + if (ble_adv_data_custom) { + # to customize BLE advertising data + defines += [ "CONFIG_CHIP_CUSTOM_BLE_ADV_DATA=1" ] + include_dirs += [ "${chip_root}/src/platform/nxp/common/ble_zephyr" ] + sources += [ "../../common/main/BleZephyrManagerApp.cpp" ] + } else { + # Empty implementation, default matter advertising data + sources += [ + "${common_example_dir}/app_ble/source/BLEApplicationManagerEmpty.cpp", + ] + } + } + if (chip_with_diag_logs_demo) { include_dirs += [ "${common_example_dir}/diagnostic_logs/include", diff --git a/examples/thermostat/nxp/rt/rw61x/args.gni b/examples/thermostat/nxp/rt/rw61x/args.gni index c2d91a5db7bae7..d3fc29a80c4920 100644 --- a/examples/thermostat/nxp/rt/rw61x/args.gni +++ b/examples/thermostat/nxp/rt/rw61x/args.gni @@ -14,6 +14,10 @@ import("//build_overrides/chip.gni") +# Set to true to customized BLE advertising data at application layer, +# instead of default Zephyr BLE manager implementation advertising data +ble_adv_data_custom = true + # SDK target definitions nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") nxp_sdk_driver_target = get_label_info(":sdk_driver", "label_no_toolchain") diff --git a/examples/thermostat/nxp/zap/thermostat_matter_br.matter b/examples/thermostat/nxp/zap/thermostat_matter_br.matter index 8a8d69fce64421..1ba87a1fbd58b5 100644 --- a/examples/thermostat/nxp/zap/thermostat_matter_br.matter +++ b/examples/thermostat/nxp/zap/thermostat_matter_br.matter @@ -1197,7 +1197,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/thermostat/nxp/zap/thermostat_matter_thread.matter b/examples/thermostat/nxp/zap/thermostat_matter_thread.matter index a2a2f2d93acd05..af687b2ba11bcb 100644 --- a/examples/thermostat/nxp/zap/thermostat_matter_thread.matter +++ b/examples/thermostat/nxp/zap/thermostat_matter_thread.matter @@ -1197,7 +1197,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter b/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter index b5b24560e31cd1..825a527c59b155 100644 --- a/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter +++ b/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter @@ -1197,7 +1197,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/thermostat/nxp/zephyr/CMakeLists.txt b/examples/thermostat/nxp/zephyr/CMakeLists.txt index b478cfff9f2566..221e66e2451162 100644 --- a/examples/thermostat/nxp/zephyr/CMakeLists.txt +++ b/examples/thermostat/nxp/zephyr/CMakeLists.txt @@ -52,6 +52,7 @@ target_include_directories(app ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/device_callbacks/include ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/factory_data/include ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/app_task/include + ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/app_ble/include ) target_sources(app @@ -73,6 +74,16 @@ target_compile_definitions(app PUBLIC "EXTERNAL_FACTORY_DATA_PROVIDER_IMPL_HEADER=\"platform/nxp/zephyr/FactoryDataProviderImpl.h\"" ) +if(CONFIG_CHIP_CUSTOM_BLE_ADV_DATA) + target_sources(app PRIVATE + ${THERMOSTAT_NXP_COMMON_DIR}/main/BleZephyrManagerApp.cpp + ) +else() + target_sources(app PRIVATE + ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/app_ble/source/BLEApplicationManagerEmpty.cpp + ) +endif() + if(CONFIG_CHIP_OTA_REQUESTOR) target_sources(app PRIVATE ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/ota_requestor/source/OTARequestorInitiatorCommon.cpp diff --git a/examples/thermostat/nxp/zephyr/prj.conf b/examples/thermostat/nxp/zephyr/prj.conf index a2fa69056d517e..6e1ad43097242d 100644 --- a/examples/thermostat/nxp/zephyr/prj.conf +++ b/examples/thermostat/nxp/zephyr/prj.conf @@ -56,3 +56,7 @@ CONFIG_CHIP_LIB_SHELL=y # enable NET commands if desired # CONFIG_NET_SHELL=y CONFIG_CHIP_STATISTICS=y + +# To customized BLE advertising data at application layer, +# instead of default Zephyr BLE manager implementation advertising data +CONFIG_CHIP_CUSTOM_BLE_ADV_DATA=y diff --git a/examples/thermostat/qpg/zap/thermostaticRadiatorValve.matter b/examples/thermostat/qpg/zap/thermostaticRadiatorValve.matter index 86383cf90492b8..96ed93bd8c07b9 100644 --- a/examples/thermostat/qpg/zap/thermostaticRadiatorValve.matter +++ b/examples/thermostat/qpg/zap/thermostaticRadiatorValve.matter @@ -1321,7 +1321,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/thermostat/thermostat-common/thermostat.matter b/examples/thermostat/thermostat-common/thermostat.matter index 1c062da0fecabc..03428f294324cf 100644 --- a/examples/thermostat/thermostat-common/thermostat.matter +++ b/examples/thermostat/thermostat-common/thermostat.matter @@ -1382,7 +1382,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/thread-br-app/thread-br-common/thread-br-app.matter b/examples/thread-br-app/thread-br-common/thread-br-app.matter index 4aa0db4a702334..b1ef02cd5aa47f 100644 --- a/examples/thread-br-app/thread-br-common/thread-br-app.matter +++ b/examples/thread-br-app/thread-br-common/thread-br-app.matter @@ -896,7 +896,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) 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 */ diff --git a/examples/tv-app/tv-common/tv-app.matter b/examples/tv-app/tv-common/tv-app.matter index 3cf472ee1de91c..1023de099d4976 100644 --- a/examples/tv-app/tv-common/tv-app.matter +++ b/examples/tv-app/tv-common/tv-app.matter @@ -1617,7 +1617,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter b/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter index b1f1cb4916fed1..d02a997c5e7487 100644 --- a/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter +++ b/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter @@ -1361,7 +1361,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ 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 b9a3224db7f109..ad1da15819866d 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 @@ -1585,7 +1585,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ @@ -2354,7 +2354,7 @@ provisional cluster ScenesManagement = 98 { /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */ fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6; /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */ - fabric command CopyScene(CopySceneRequest): CopySceneResponse = 64; + fabric command access(invoke: manage) CopyScene(CopySceneRequest): CopySceneResponse = 64; } /** An interface to a generic way to secure a door */ diff --git a/examples/water-leak-detector-app/water-leak-detector-common/water-leak-detector-app.matter b/examples/water-leak-detector-app/water-leak-detector-common/water-leak-detector-app.matter index 5d4d31b28f4e41..cb185ad5ea10a8 100644 --- a/examples/water-leak-detector-app/water-leak-detector-common/water-leak-detector-app.matter +++ b/examples/water-leak-detector-app/water-leak-detector-common/water-leak-detector-app.matter @@ -1346,7 +1346,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** Commands to trigger a Node to allow a new Administrator to commission it. */ diff --git a/examples/window-app/common/window-app.matter b/examples/window-app/common/window-app.matter index 850b8f047ef83d..c0b7cbd37dd69e 100644 --- a/examples/window-app/common/window-app.matter +++ b/examples/window-app/common/window-app.matter @@ -1462,7 +1462,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ diff --git a/integrations/appengine/README.md b/integrations/appengine/README.md index 45ecbe50d585eb..2eea9c1dc21daf 100644 --- a/integrations/appengine/README.md +++ b/integrations/appengine/README.md @@ -1,4 +1,4 @@ -## Deploy Static Website on App Engine +## Deploy Static Website on App Engine for The Matter SDK Coverage Report ### Setup google cloud integration @@ -30,7 +30,43 @@ settings of your App Engine application. Directory `out/coverage/coverage` contains the coverage report files, such as HTML, CSS, images, and JavaScript. +Deploying your generated report: + ``` cd out/coverage/coverage -gcloud app deploy ../../../integrations/appengine/webapp_config.yaml +gcloud app deploy webapp_config.yaml --project matter-build-automation +``` + +The output should look like: + +``` +Services to deploy: + +descriptor: [/usr/local/google/home/<user>/connectedhomeip/out/coverage/coverage/webapp_config.yaml] +source: [/usr/local/google/home/<user>/connectedhomeip/out/coverage/coverage] +target project: [matter-build-automation] +target service: [default] +target version: [20241212t175429] +target url: [https://matter-build-automation.ue.r.appspot.com] +target service account: [matter-build-automation@appspot.gserviceaccount.com] + + +Do you want to continue (Y/n)? Y + +Beginning deployment of service [default]... +╔════════════════════════════════════════════════════════════╗ +╠═ Uploading 0 files to Google Cloud Storage ═╣ +╚════════════════════════════════════════════════════════════╝ +File upload done. +Updating service [default]...done. +Setting traffic split for service [default]...done. +Deployed service [default] to [https://matter-build-automation.ue.r.appspot.com] + +You can stream logs from the command line by running: + $ gcloud app logs tail -s default + +To view your application in the web browser run: + $ gcloud app browse --project=matter-build-automation ``` + +If you run into permission issues, reach out to a team member from Google. diff --git a/integrations/appengine/webapp_config.yaml b/integrations/appengine/webapp_config.yaml index 839b6aa94d671b..f27ad7d68b8663 100644 --- a/integrations/appengine/webapp_config.yaml +++ b/integrations/appengine/webapp_config.yaml @@ -1,6 +1,4 @@ -runtime: python27 -api_version: 1 -threadsafe: true +runtime: python39 handlers: - url: / static_files: html/index.html diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index 0bb25ef9a06b75..d7935e95ffeaaf 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -197,6 +197,7 @@ def BuildHostTarget(): target.AppendModifier('disable-dnssd-tests', enable_dnssd_tests=False).OnlyIfRe('-tests') target.AppendModifier('chip-casting-simplified', chip_casting_simplified=True).OnlyIfRe('-tv-casting-app') target.AppendModifier('googletest', use_googletest=True).OnlyIfRe('-tests') + target.AppendModifier('terms-and-conditions', terms_and_conditions_required=True) return target diff --git a/scripts/build/builders/host.py b/scripts/build/builders/host.py index 7fe5823f37b7a8..fd84901a5adaba 100644 --- a/scripts/build/builders/host.py +++ b/scripts/build/builders/host.py @@ -336,6 +336,7 @@ def __init__(self, root, runner, app: HostApp, board=HostBoard.NATIVE, chip_casting_simplified: Optional[bool] = None, disable_shell=False, use_googletest=False, + terms_and_conditions_required: Optional[bool] = None, ): super(HostBuilder, self).__init__( root=os.path.join(root, 'examples', app.ExamplePath()), @@ -459,6 +460,12 @@ def __init__(self, root, runner, app: HostApp, board=HostBoard.NATIVE, if chip_casting_simplified is not None: self.extra_gn_options.append(f'chip_casting_simplified={str(chip_casting_simplified).lower()}') + if terms_and_conditions_required is not None: + if terms_and_conditions_required: + self.extra_gn_options.append('chip_terms_and_conditions_required=true') + else: + self.extra_gn_options.append('chip_terms_and_conditions_required=false') + if self.board == HostBoard.ARM64: if not use_clang: raise Exception("Cross compile only supported using clang") diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt index f3330ffc3fe090..05fec168c491c6 100644 --- a/scripts/build/testdata/all_targets_linux_x64.txt +++ b/scripts/build/testdata/all_targets_linux_x64.txt @@ -9,7 +9,7 @@ efr32-{brd2704b,brd4316a,brd4317a,brd4318a,brd4319a,brd4186a,brd4187a,brd2601b,b esp32-{m5stack,c3devkit,devkitc,qemu}-{all-clusters,all-clusters-minimal,energy-management,ota-provider,ota-requestor,shell,light,lock,bridge,temperature-measurement,ota-requestor,tests}[-rpc][-ipv6only][-tracing] genio-lighting-app linux-fake-tests[-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-pw-fuzztest][-coverage][-dmalloc][-clang] -linux-{x64,arm64}-{rpc-console,all-clusters,all-clusters-minimal,chip-tool,thermostat,java-matter-controller,kotlin-matter-controller,minmdns,light,light-data-model-no-unique-id,lock,shell,ota-provider,ota-requestor,simulated-app1,simulated-app2,python-bindings,tv-app,tv-casting-app,bridge,fabric-admin,fabric-bridge,fabric-sync,tests,chip-cert,address-resolve-tool,contact-sensor,dishwasher,microwave-oven,refrigerator,rvc,air-purifier,lit-icd,air-quality-sensor,network-manager,energy-management,water-leak-detector}[-nodeps][-nlfaultinject][-platform-mdns][-minmdns-verbose][-libnl][-same-event-loop][-no-interactive][-ipv6only][-no-ble][-no-wifi][-no-thread][-no-shell][-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-pw-fuzztest][-coverage][-dmalloc][-clang][-test][-rpc][-with-ui][-evse-test-event][-enable-dnssd-tests][-disable-dnssd-tests][-chip-casting-simplified][-googletest] +linux-{x64,arm64}-{rpc-console,all-clusters,all-clusters-minimal,chip-tool,thermostat,java-matter-controller,kotlin-matter-controller,minmdns,light,light-data-model-no-unique-id,lock,shell,ota-provider,ota-requestor,simulated-app1,simulated-app2,python-bindings,tv-app,tv-casting-app,bridge,fabric-admin,fabric-bridge,fabric-sync,tests,chip-cert,address-resolve-tool,contact-sensor,dishwasher,microwave-oven,refrigerator,rvc,air-purifier,lit-icd,air-quality-sensor,network-manager,energy-management,water-leak-detector}[-nodeps][-nlfaultinject][-platform-mdns][-minmdns-verbose][-libnl][-same-event-loop][-no-interactive][-ipv6only][-no-ble][-no-wifi][-no-thread][-no-shell][-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-pw-fuzztest][-coverage][-dmalloc][-clang][-test][-rpc][-with-ui][-evse-test-event][-enable-dnssd-tests][-disable-dnssd-tests][-chip-casting-simplified][-googletest][-terms-and-conditions] linux-x64-efr32-test-runner[-clang] imx-{chip-tool,lighting-app,thermostat,all-clusters-app,all-clusters-minimal-app,ota-provider-app}[-release] infineon-psoc6-{lock,light,all-clusters,all-clusters-minimal}[-ota][-updateimage][-trustm] diff --git a/scripts/build_coverage.sh b/scripts/build_coverage.sh index 1bb68a2911c525..ef6e7b97051624 100755 --- a/scripts/build_coverage.sh +++ b/scripts/build_coverage.sh @@ -179,7 +179,7 @@ mkdir -p "$COVERAGE_ROOT" lcov --initial --capture --directory "$OUTPUT_ROOT/obj/src" --exclude="$PWD"/zzz_generated/* --exclude="$PWD"/third_party/* --exclude=/usr/include/* --output-file "$COVERAGE_ROOT/lcov_base.info" lcov --capture --directory "$OUTPUT_ROOT/obj/src" --exclude="$PWD"/zzz_generated/* --exclude="$PWD"/third_party/* --exclude=/usr/include/* --output-file "$COVERAGE_ROOT/lcov_test.info" lcov --add-tracefile "$COVERAGE_ROOT/lcov_base.info" --add-tracefile "$COVERAGE_ROOT/lcov_test.info" --output-file "$COVERAGE_ROOT/lcov_final.info" -genhtml "$COVERAGE_ROOT/lcov_final.info" --output-directory "$COVERAGE_ROOT/html" +genhtml "$COVERAGE_ROOT/lcov_final.info" --output-directory "$COVERAGE_ROOT/html" --title "SHA:$(git rev-parse HEAD)" --header-title "Matter SDK Coverage Report" # Copy webapp's YAML file to the coverage output directory cp "$CHIP_ROOT/integrations/appengine/webapp_config.yaml" "$COVERAGE_ROOT/webapp_config.yaml" diff --git a/scripts/dm_xml_ci_change_enforcement.py b/scripts/dm_xml_ci_change_enforcement.py new file mode 100644 index 00000000000000..0efe40f66faa49 --- /dev/null +++ b/scripts/dm_xml_ci_change_enforcement.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import os +import subprocess +import sys + +import click + + +@click.command() +@click.argument('dir', nargs=1, type=click.Path(exists=True)) +def check_dm_directory(dir): + clusters = os.path.join(dir, 'clusters') + device_types = os.path.join(dir, 'device_types') + if not os.path.isdir(clusters) or not os.path.isdir(device_types): + print(f"Invalid data model directory {dir}") + sys.exit(1) + + # We are operating in a VM, and although there is a checkout, it is working in a scratch directory + # where the ownership is different than the runner. + # Adding an exception for this directory so that git can function properly. + subprocess.run("git config --global --add safe.directory '*'", shell=True) + + def check_dir(dir): + cmd = f'git diff HEAD^..HEAD --name-only -- {dir}' + output = subprocess.check_output(cmd, shell=True).decode().splitlines() + if output and 'spec_sha' not in output and 'scraper_version' not in output: + print(f'Data model directory {dir} had changes to the following files without a corresponding update to the spec SHA') + print(output) + print("Note that the data_model directory files are automatically updated by a spec scraper and should not be manually updated.") + return 1 + return 0 + + ret = check_dir(clusters) + check_dir(device_types) + sys.exit(ret) + + +if __name__ == '__main__': + check_dm_directory() diff --git a/scripts/helpers/bash-completion.sh b/scripts/helpers/bash-completion.sh index 6737f2149cc5f9..26239419d3e587 100644 --- a/scripts/helpers/bash-completion.sh +++ b/scripts/helpers/bash-completion.sh @@ -28,6 +28,58 @@ _chip_tool_get_options() { "$@" --help 2>&1 | awk -F'[[]|[]]' '/^[[]--/{ print $2 }' } +_chip_app() { + + local cur prev words cword split + _init_completion -s || return + + case "$prev" in + --ble-device) + readarray -t words < <(ls -I '*:*' /sys/class/bluetooth) + # Get the list of Bluetooth devices without the 'hci' prefix. + readarray -t COMPREPLY < <(compgen -W "${words[*]#hci}" -- "$cur") + return + ;; + --custom-flow) + readarray -t COMPREPLY < <(compgen -W "0 1 2" -- "$cur") + return + ;; + --capabilities) + # The capabilities option is a bit-field with 3 bits currently defined. + readarray -t COMPREPLY < <(compgen -W "001 010 011 100 101 111" -- "$cur") + return + ;; + --KVS) + _filedir + return + ;; + --PICS) + _filedir + return + ;; + --trace_file) + _filedir + return + ;; + --trace_log | --trace_decode) + readarray -t COMPREPLY < <(compgen -W "0 1" -- "$cur") + return + ;; + --trace-to) + readarray -t COMPREPLY < <(compgen -W "json perfetto" -- "$cur") + compopt -o nospace + return + ;; + esac + + case "$cur" in + -*) + readarray -t COMPREPLY < <(compgen -W "$(_parse_help "$1")" -- "$cur") + ;; + esac + +} + _chip_tool() { local cur prev words cword split @@ -36,34 +88,56 @@ _chip_tool() { # Get command line arguments up to the cursor position local args=("${COMP_WORDS[@]:0:$cword+1}") - local command=0 case "$prev" in --commissioner-name) readarray -t COMPREPLY < <(compgen -W "alpha beta gamma 4 5 6 7 8 9" -- "$cur") + return + ;; + --only-allow-trusted-cd-keys) + readarray -t COMPREPLY < <(compgen -W "0 1" -- "$cur") + return ;; - --paa-trust-store-path | --cd-trust-store-path) + --paa-trust-store-path | --cd-trust-store-path | --dac-revocation-set-path) _filedir -d + return ;; --storage-directory) _filedir -d + return ;; - *) - command=1 + --trace-to) + readarray -t COMPREPLY < <(compgen -W "json perfetto" -- "$cur") + compopt -o nospace + return ;; esac - if [ "$command" -eq 1 ]; then - case "$cur" in - -*) - words=$(_chip_tool_get_options "${args[@]}") - ;; - *) - words=$(_chip_tool_get_commands "${args[@]}") - ;; - esac - readarray -t COMPREPLY < <(compgen -W "$words" -- "$cur") - fi + case "$cur" in + -*) + words=$(_chip_tool_get_options "${args[@]}") + ;; + *) + words=$(_chip_tool_get_commands "${args[@]}") + ;; + esac + readarray -t COMPREPLY < <(compgen -W "$words" -- "$cur") } +complete -F _chip_app chip-air-purifier-app +complete -F _chip_app chip-all-clusters-app +complete -F _chip_app chip-bridge-app +complete -F _chip_app chip-dishwasher-app +complete -F _chip_app chip-energy-management-app +complete -F _chip_app chip-lighting-app +complete -F _chip_app chip-lock-app +complete -F _chip_app chip-log-source-app +complete -F _chip_app chip-microwave-oven-app +complete -F _chip_app chip-ota-provider-app +complete -F _chip_app chip-ota-requestor-app +complete -F _chip_app chip-refrigerator-app +complete -F _chip_app chip-rvc-app +complete -F _chip_app chip-tv-app +complete -F _chip_app chip-tv-casting-app + complete -F _chip_tool chip-tool diff --git a/scripts/spec_xml/paths.py b/scripts/spec_xml/paths.py index 3a5159cc514bf1..d4e269759f17f2 100644 --- a/scripts/spec_xml/paths.py +++ b/scripts/spec_xml/paths.py @@ -71,7 +71,7 @@ def get_documentation_file_path(): Returns the path to the documentation file. """ chip_root = get_chip_root() - documentation_file = os.path.join(chip_root, 'docs', 'spec_clusters.md') + documentation_file = os.path.join(chip_root, 'docs', 'ids_and_codes', 'spec_clusters.md') if not os.path.exists(documentation_file): raise FileNotFoundError(f"Documentation file does not exist: {documentation_file}") return documentation_file diff --git a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/access.h b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/access.h index 9b35ecb22d178c..8e2e0ca373a86c 100644 --- a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/access.h +++ b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/access.h @@ -373,6 +373,7 @@ 0x00000031, /* Cluster: Network Commissioning, Command: ConnectNetwork, Privilege: administer */ \ 0x00000031, /* Cluster: Network Commissioning, Command: ReorderNetwork, Privilege: administer */ \ 0x00000033, /* Cluster: General Diagnostics, Command: TestEventTrigger, Privilege: manage */ \ + 0x00000033, /* Cluster: General Diagnostics, Command: PayloadTestRequest, Privilege: manage */ \ 0x00000034, /* Cluster: Software Diagnostics, Command: ResetWatermarks, Privilege: manage */ \ 0x00000035, /* Cluster: Thread Network Diagnostics, Command: ResetCounts, Privilege: manage */ \ 0x00000037, /* Cluster: Ethernet Network Diagnostics, Command: ResetCounts, Privilege: manage */ \ @@ -400,6 +401,7 @@ 0x00000062, /* Cluster: Scenes Management, Command: RemoveScene, Privilege: manage */ \ 0x00000062, /* Cluster: Scenes Management, Command: RemoveAllScenes, Privilege: manage */ \ 0x00000062, /* Cluster: Scenes Management, Command: StoreScene, Privilege: manage */ \ + 0x00000062, /* Cluster: Scenes Management, Command: CopyScene, Privilege: manage */ \ 0x00000201, /* Cluster: Thermostat, Command: AtomicRequest, Privilege: manage */ \ 0xFFF1FC06, /* Cluster: Fault Injection, Command: FailAtFault, Privilege: manage */ \ 0xFFF1FC06, /* Cluster: Fault Injection, Command: FailRandomlyAtFault, Privilege: manage */ \ @@ -423,6 +425,7 @@ 0x00000006, /* Cluster: Network Commissioning, Command: ConnectNetwork, Privilege: administer */ \ 0x00000008, /* Cluster: Network Commissioning, Command: ReorderNetwork, Privilege: administer */ \ 0x00000000, /* Cluster: General Diagnostics, Command: TestEventTrigger, Privilege: manage */ \ + 0x00000003, /* Cluster: General Diagnostics, Command: PayloadTestRequest, Privilege: manage */ \ 0x00000000, /* Cluster: Software Diagnostics, Command: ResetWatermarks, Privilege: manage */ \ 0x00000000, /* Cluster: Thread Network Diagnostics, Command: ResetCounts, Privilege: manage */ \ 0x00000000, /* Cluster: Ethernet Network Diagnostics, Command: ResetCounts, Privilege: manage */ \ @@ -450,6 +453,7 @@ 0x00000002, /* Cluster: Scenes Management, Command: RemoveScene, Privilege: manage */ \ 0x00000003, /* Cluster: Scenes Management, Command: RemoveAllScenes, Privilege: manage */ \ 0x00000004, /* Cluster: Scenes Management, Command: StoreScene, Privilege: manage */ \ + 0x00000040, /* Cluster: Scenes Management, Command: CopyScene, Privilege: manage */ \ 0x000000FE, /* Cluster: Thermostat, Command: AtomicRequest, Privilege: manage */ \ 0x00000000, /* Cluster: Fault Injection, Command: FailAtFault, Privilege: manage */ \ 0x00000001, /* Cluster: Fault Injection, Command: FailRandomlyAtFault, Privilege: manage */ \ @@ -473,6 +477,7 @@ chip::Access::Privilege::kAdminister, /* Cluster: Network Commissioning, Command: ConnectNetwork, Privilege: administer */ \ chip::Access::Privilege::kAdminister, /* Cluster: Network Commissioning, Command: ReorderNetwork, Privilege: administer */ \ chip::Access::Privilege::kManage, /* Cluster: General Diagnostics, Command: TestEventTrigger, Privilege: manage */ \ + chip::Access::Privilege::kManage, /* Cluster: General Diagnostics, Command: PayloadTestRequest, Privilege: manage */ \ chip::Access::Privilege::kManage, /* Cluster: Software Diagnostics, Command: ResetWatermarks, Privilege: manage */ \ chip::Access::Privilege::kManage, /* Cluster: Thread Network Diagnostics, Command: ResetCounts, Privilege: manage */ \ chip::Access::Privilege::kManage, /* Cluster: Ethernet Network Diagnostics, Command: ResetCounts, Privilege: manage */ \ @@ -500,6 +505,7 @@ chip::Access::Privilege::kManage, /* Cluster: Scenes Management, Command: RemoveScene, Privilege: manage */ \ chip::Access::Privilege::kManage, /* Cluster: Scenes Management, Command: RemoveAllScenes, Privilege: manage */ \ chip::Access::Privilege::kManage, /* Cluster: Scenes Management, Command: StoreScene, Privilege: manage */ \ + chip::Access::Privilege::kManage, /* Cluster: Scenes Management, Command: CopyScene, Privilege: manage */ \ chip::Access::Privilege::kManage, /* Cluster: Thermostat, Command: AtomicRequest, Privilege: manage */ \ chip::Access::Privilege::kManage, /* Cluster: Fault Injection, Command: FailAtFault, Privilege: manage */ \ chip::Access::Privilege::kManage, /* Cluster: Fault Injection, Command: FailRandomlyAtFault, Privilege: manage */ \ diff --git a/scripts/tools/zap/tests/outputs/lighting-app/app-templates/access.h b/scripts/tools/zap/tests/outputs/lighting-app/app-templates/access.h index acef1673384c14..c062b9376f4666 100644 --- a/scripts/tools/zap/tests/outputs/lighting-app/app-templates/access.h +++ b/scripts/tools/zap/tests/outputs/lighting-app/app-templates/access.h @@ -200,6 +200,7 @@ 0x00000062, /* Cluster: Scenes Management, Command: RemoveScene, Privilege: manage */ \ 0x00000062, /* Cluster: Scenes Management, Command: RemoveAllScenes, Privilege: manage */ \ 0x00000062, /* Cluster: Scenes Management, Command: StoreScene, Privilege: manage */ \ + 0x00000062, /* Cluster: Scenes Management, Command: CopyScene, Privilege: manage */ \ } // Parallel array data (cluster, *command*, privilege) for invoke command @@ -242,6 +243,7 @@ 0x00000002, /* Cluster: Scenes Management, Command: RemoveScene, Privilege: manage */ \ 0x00000003, /* Cluster: Scenes Management, Command: RemoveAllScenes, Privilege: manage */ \ 0x00000004, /* Cluster: Scenes Management, Command: StoreScene, Privilege: manage */ \ + 0x00000040, /* Cluster: Scenes Management, Command: CopyScene, Privilege: manage */ \ } // Parallel array data (cluster, command, *privilege*) for invoke command @@ -284,6 +286,7 @@ chip::Access::Privilege::kManage, /* Cluster: Scenes Management, Command: RemoveScene, Privilege: manage */ \ chip::Access::Privilege::kManage, /* Cluster: Scenes Management, Command: RemoveAllScenes, Privilege: manage */ \ chip::Access::Privilege::kManage, /* Cluster: Scenes Management, Command: StoreScene, Privilege: manage */ \ + chip::Access::Privilege::kManage, /* Cluster: Scenes Management, Command: CopyScene, Privilege: manage */ \ } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index 14fcfc96e45543..fd286ff7c9c2d4 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -76,6 +76,7 @@ buildconfig_header("app_buildconfig") { "CHIP_DEVICE_CONFIG_DYNAMIC_SERVER=${chip_build_controller_dynamic_server}", "CHIP_CONFIG_ENABLE_BUSY_HANDLING_FOR_OPERATIONAL_SESSION_SETUP=${chip_enable_busy_handling_for_operational_session_setup}", "CHIP_CONFIG_DATA_MODEL_EXTRA_LOGGING=${chip_data_model_extra_logging}", + "CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED=${chip_terms_and_conditions_required}", ] visibility = [ ":app_config" ] diff --git a/src/app/FailSafeContext.cpp b/src/app/FailSafeContext.cpp index 95a5b267f2aa5e..372ee323930d67 100644 --- a/src/app/FailSafeContext.cpp +++ b/src/app/FailSafeContext.cpp @@ -86,9 +86,12 @@ void FailSafeContext::ScheduleFailSafeCleanup(FabricIndex fabricIndex, bool addN SetFailSafeArmed(false); ChipDeviceEvent event{ .Type = DeviceEventType::kFailSafeTimerExpired, - .FailSafeTimerExpired = { .fabricIndex = fabricIndex, - .addNocCommandHasBeenInvoked = addNocCommandInvoked, - .updateNocCommandHasBeenInvoked = updateNocCommandInvoked } }; + .FailSafeTimerExpired = { + .fabricIndex = fabricIndex, + .addNocCommandHasBeenInvoked = addNocCommandInvoked, + .updateNocCommandHasBeenInvoked = updateNocCommandInvoked, + .updateTermsAndConditionsHasBeenInvoked = mUpdateTermsAndConditionsHasBeenInvoked, + } }; CHIP_ERROR status = PlatformMgr().PostEvent(&event); if (status != CHIP_NO_ERROR) diff --git a/src/app/FailSafeContext.h b/src/app/FailSafeContext.h index 48e11e0845395b..af177bd2a8d5fc 100644 --- a/src/app/FailSafeContext.h +++ b/src/app/FailSafeContext.h @@ -56,6 +56,7 @@ class FailSafeContext void SetUpdateNocCommandInvoked() { mUpdateNocCommandHasBeenInvoked = true; } void SetAddTrustedRootCertInvoked() { mAddTrustedRootCertHasBeenInvoked = true; } void SetCsrRequestForUpdateNoc(bool isForUpdateNoc) { mIsCsrRequestForUpdateNoc = isForUpdateNoc; } + void SetUpdateTermsAndConditionsHasBeenInvoked() { mUpdateTermsAndConditionsHasBeenInvoked = true; } /** * @brief @@ -91,6 +92,7 @@ class FailSafeContext bool UpdateNocCommandHasBeenInvoked() const { return mUpdateNocCommandHasBeenInvoked; } bool AddTrustedRootCertHasBeenInvoked() const { return mAddTrustedRootCertHasBeenInvoked; } bool IsCsrRequestForUpdateNoc() const { return mIsCsrRequestForUpdateNoc; } + bool UpdateTermsAndConditionsHasBeenInvoked() { return mUpdateTermsAndConditionsHasBeenInvoked; } FabricIndex GetFabricIndex() const { @@ -109,8 +111,9 @@ class FailSafeContext bool mUpdateNocCommandHasBeenInvoked = false; bool mAddTrustedRootCertHasBeenInvoked = false; // The fact of whether a CSR occurred at all is stored elsewhere. - bool mIsCsrRequestForUpdateNoc = false; - FabricIndex mFabricIndex = kUndefinedFabricIndex; + bool mIsCsrRequestForUpdateNoc = false; + FabricIndex mFabricIndex = kUndefinedFabricIndex; + bool mUpdateTermsAndConditionsHasBeenInvoked = false; /** * @brief @@ -140,11 +143,12 @@ class FailSafeContext { SetFailSafeArmed(false); - mAddNocCommandHasBeenInvoked = false; - mUpdateNocCommandHasBeenInvoked = false; - mAddTrustedRootCertHasBeenInvoked = false; - mFailSafeBusy = false; - mIsCsrRequestForUpdateNoc = false; + mAddNocCommandHasBeenInvoked = false; + mUpdateNocCommandHasBeenInvoked = false; + mAddTrustedRootCertHasBeenInvoked = false; + mFailSafeBusy = false; + mIsCsrRequestForUpdateNoc = false; + mUpdateTermsAndConditionsHasBeenInvoked = false; } void FailSafeTimerExpired(); diff --git a/src/app/chip_data_model.cmake b/src/app/chip_data_model.cmake index 7c5ab0f82608b4..dcafc0055de3e9 100644 --- a/src/app/chip_data_model.cmake +++ b/src/app/chip_data_model.cmake @@ -81,8 +81,9 @@ function(chip_configure_data_model APP_TARGET) ${CHIP_APP_BASE_DIR}/SafeAttributePersistenceProvider.cpp ${CHIP_APP_BASE_DIR}/StorageDelegateWrapper.cpp ${CHIP_APP_BASE_DIR}/server/AclStorage.cpp - ${CHIP_APP_BASE_DIR}/server/DefaultAclStorage.cpp ${CHIP_APP_BASE_DIR}/server/CommissioningWindowManager.cpp + ${CHIP_APP_BASE_DIR}/server/DefaultAclStorage.cpp + ${CHIP_APP_BASE_DIR}/server/DefaultTermsAndConditionsProvider.cpp ${CHIP_APP_BASE_DIR}/server/Dnssd.cpp ${CHIP_APP_BASE_DIR}/server/EchoHandler.cpp ${CHIP_APP_BASE_DIR}/server/OnboardingCodesUtil.cpp diff --git a/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp b/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp index 0548c55026efc8..401179596eebef 100644 --- a/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp +++ b/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2021-2024 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,22 +21,31 @@ ******************************************************************************* ******************************************************************************/ +#include "general-commissioning-server.h" + #include <app-common/zap-generated/attributes/Accessors.h> #include <app-common/zap-generated/cluster-objects.h> +#include <app/AppConfig.h> #include <app/AttributeAccessInterfaceRegistry.h> #include <app/CommandHandler.h> #include <app/CommandHandlerInterface.h> #include <app/CommandHandlerInterfaceRegistry.h> #include <app/ConcreteCommandPath.h> +#include <app/reporting/reporting.h> #include <app/server/CommissioningWindowManager.h> #include <app/server/Server.h> -#include <app/util/attribute-storage.h> -#include <lib/support/Span.h> +#include <lib/support/CodeUtils.h> #include <lib/support/logging/CHIPLogging.h> #include <platform/CHIPDeviceConfig.h> #include <platform/ConfigurationManager.h> #include <platform/DeviceControlServer.h> #include <tracing/macros.h> +#include <transport/SecureSession.h> + +#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED +#include <app/server/TermsAndConditionsManager.h> //nogncheck +#include <app/server/TermsAndConditionsProvider.h> //nogncheck +#endif using namespace chip; using namespace chip::app; @@ -44,6 +53,7 @@ using namespace chip::app::Clusters; using namespace chip::app::Clusters::GeneralCommissioning; using namespace chip::app::Clusters::GeneralCommissioning::Attributes; using namespace chip::DeviceLayer; +using chip::app::Clusters::GeneralCommissioning::CommissioningErrorEnum; using Transport::SecureSession; using Transport::Session; @@ -80,6 +90,7 @@ class GeneralCommissioningGlobalInstance : public AttributeAccessInterface, publ void HandleArmFailSafe(HandlerContext & ctx, const Commands::ArmFailSafe::DecodableType & commandData); void HandleCommissioningComplete(HandlerContext & ctx, const Commands::CommissioningComplete::DecodableType & commandData); void HandleSetRegulatoryConfig(HandlerContext & ctx, const Commands::SetRegulatoryConfig::DecodableType & commandData); + void HandleSetTCAcknowledgements(HandlerContext & ctx, const Commands::SetTCAcknowledgements::DecodableType & commandData); }; GeneralCommissioningGlobalInstance gGeneralCommissioningInstance; @@ -106,6 +117,58 @@ CHIP_ERROR GeneralCommissioningGlobalInstance::Read(const ConcreteReadAttributeP case SupportsConcurrentConnection::Id: { return ReadSupportsConcurrentConnection(aEncoder); } +#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED + case TCAcceptedVersion::Id: { + TermsAndConditionsProvider * tcProvider = TermsAndConditionsManager::GetInstance(); + Optional<TermsAndConditions> outTermsAndConditions; + + VerifyOrReturnError(nullptr != tcProvider, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); + ReturnErrorOnFailure(tcProvider->GetAcceptance(outTermsAndConditions)); + + return aEncoder.Encode(outTermsAndConditions.ValueOr(TermsAndConditions(0, 0)).GetVersion()); + } + case TCMinRequiredVersion::Id: { + TermsAndConditionsProvider * tcProvider = TermsAndConditionsManager::GetInstance(); + Optional<TermsAndConditions> outTermsAndConditions; + + VerifyOrReturnError(nullptr != tcProvider, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); + ReturnErrorOnFailure(tcProvider->GetRequirements(outTermsAndConditions)); + + return aEncoder.Encode(outTermsAndConditions.ValueOr(TermsAndConditions(0, 0)).GetVersion()); + } + case TCAcknowledgements::Id: { + TermsAndConditionsProvider * tcProvider = TermsAndConditionsManager::GetInstance(); + Optional<TermsAndConditions> outTermsAndConditions; + + VerifyOrReturnError(nullptr != tcProvider, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); + ReturnErrorOnFailure(tcProvider->GetAcceptance(outTermsAndConditions)); + + return aEncoder.Encode(outTermsAndConditions.ValueOr(TermsAndConditions(0, 0)).GetValue()); + } + case TCAcknowledgementsRequired::Id: { + TermsAndConditionsProvider * tcProvider = TermsAndConditionsManager::GetInstance(); + bool acknowledgementsRequired; + + VerifyOrReturnError(nullptr != tcProvider, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); + ReturnErrorOnFailure(tcProvider->GetAcknowledgementsRequired(acknowledgementsRequired)); + + return aEncoder.Encode(acknowledgementsRequired); + } + case TCUpdateDeadline::Id: { + TermsAndConditionsProvider * tcProvider = TermsAndConditionsManager::GetInstance(); + Optional<uint32_t> outUpdateAcceptanceDeadline; + + VerifyOrReturnError(nullptr != tcProvider, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); + ReturnErrorOnFailure(tcProvider->GetUpdateAcceptanceDeadline(outUpdateAcceptanceDeadline)); + + if (!outUpdateAcceptanceDeadline.HasValue()) + { + return aEncoder.EncodeNull(); + } + + return aEncoder.Encode(outUpdateAcceptanceDeadline.Value()); + } +#endif // CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED default: { break; } @@ -182,9 +245,84 @@ void GeneralCommissioningGlobalInstance::InvokeCommand(HandlerContext & handlerC handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleSetRegulatoryConfig(ctx, commandData); }); break; + + case Commands::SetTCAcknowledgements::Id: + ChipLogDetail(Zcl, "GeneralCommissioningGlobalInstance: Entering SetTCAcknowledgements"); + + CommandHandlerInterface::HandleCommand<Commands::SetTCAcknowledgements::DecodableType>( + handlerContext, + [this](HandlerContext & ctx, const auto & commandData) { HandleSetTCAcknowledgements(ctx, commandData); }); + break; } } +#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED +typedef struct sTermsAndConditionsState +{ + Optional<TermsAndConditions> acceptance; + bool acknowledgementsRequired; + Optional<TermsAndConditions> requirements; + Optional<uint32_t> updateAcceptanceDeadline; +} TermsAndConditionsState; + +CHIP_ERROR GetTermsAndConditionsAttributeState(TermsAndConditionsProvider * tcProvider, + TermsAndConditionsState & outTermsAndConditionsState) +{ + TermsAndConditionsState termsAndConditionsState; + + ReturnErrorOnFailure(tcProvider->GetAcceptance(termsAndConditionsState.acceptance)); + ReturnErrorOnFailure(tcProvider->GetAcknowledgementsRequired(termsAndConditionsState.acknowledgementsRequired)); + ReturnErrorOnFailure(tcProvider->GetRequirements(termsAndConditionsState.requirements)); + ReturnErrorOnFailure(tcProvider->GetUpdateAcceptanceDeadline(termsAndConditionsState.updateAcceptanceDeadline)); + + outTermsAndConditionsState = termsAndConditionsState; + return CHIP_NO_ERROR; +} + +void NotifyTermsAndConditionsAttributeChangeIfRequired(const TermsAndConditionsState & initialState, + const TermsAndConditionsState & updatedState) +{ + // Notify on TCAcknowledgementsRequired change + if (initialState.acknowledgementsRequired != updatedState.acknowledgementsRequired) + { + MatterReportingAttributeChangeCallback(kRootEndpointId, GeneralCommissioning::Id, TCAcknowledgementsRequired::Id); + } + + // Notify on TCAcceptedVersion change + if ((initialState.acceptance.HasValue() != updatedState.acceptance.HasValue()) || + (initialState.acceptance.HasValue() && + (initialState.acceptance.Value().GetVersion() != updatedState.acceptance.Value().GetVersion()))) + { + MatterReportingAttributeChangeCallback(kRootEndpointId, GeneralCommissioning::Id, TCAcceptedVersion::Id); + } + + // Notify on TCAcknowledgements change + if ((initialState.acceptance.HasValue() != updatedState.acceptance.HasValue()) || + (initialState.acceptance.HasValue() && + (initialState.acceptance.Value().GetValue() != updatedState.acceptance.Value().GetValue()))) + { + MatterReportingAttributeChangeCallback(kRootEndpointId, GeneralCommissioning::Id, TCAcknowledgements::Id); + } + + // Notify on TCRequirements change + if ((initialState.requirements.HasValue() != updatedState.requirements.HasValue()) || + (initialState.requirements.HasValue() && + (initialState.requirements.Value().GetVersion() != updatedState.requirements.Value().GetVersion() || + initialState.requirements.Value().GetValue() != updatedState.requirements.Value().GetValue()))) + { + MatterReportingAttributeChangeCallback(kRootEndpointId, GeneralCommissioning::Id, TCMinRequiredVersion::Id); + } + + // Notify on TCUpdateDeadline change + if ((initialState.updateAcceptanceDeadline.HasValue() != updatedState.updateAcceptanceDeadline.HasValue()) || + (initialState.updateAcceptanceDeadline.HasValue() && + (initialState.updateAcceptanceDeadline.Value() != updatedState.updateAcceptanceDeadline.Value()))) + { + MatterReportingAttributeChangeCallback(kRootEndpointId, GeneralCommissioning::Id, TCUpdateDeadline::Id); + } +} +#endif // CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED + void GeneralCommissioningGlobalInstance::HandleArmFailSafe(HandlerContext & ctx, const Commands::ArmFailSafe::DecodableType & commandData) { @@ -255,55 +393,110 @@ void GeneralCommissioningGlobalInstance::HandleCommissioningComplete( ChipLogProgress(FailSafe, "GeneralCommissioning: Received CommissioningComplete"); Commands::CommissioningCompleteResponse::Type response; + + // Fail-safe must be armed if (!failSafe.IsFailSafeArmed()) { response.errorCode = CommissioningErrorEnum::kNoFailSafe; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + return; } - else + +#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED + TermsAndConditionsProvider * tcProvider = TermsAndConditionsManager::GetInstance(); + + // Ensure required terms and conditions have been accepted, then attempt to commit + if (nullptr != tcProvider) { - SessionHandle handle = ctx.mCommandHandler.GetExchangeContext()->GetSessionHandle(); - // If not a CASE session, or the fabric does not match the fail-safe, - // error out. - if (handle->GetSessionType() != Session::SessionType::kSecure || - handle->AsSecureSession()->GetSecureSessionType() != SecureSession::Type::kCASE || - !failSafe.MatchesFabricIndex(ctx.mCommandHandler.GetAccessingFabricIndex())) + Optional<TermsAndConditions> requiredTermsAndConditionsMaybe; + Optional<TermsAndConditions> acceptedTermsAndConditionsMaybe; + + CheckSuccess(tcProvider->GetRequirements(requiredTermsAndConditionsMaybe), Failure); + CheckSuccess(tcProvider->GetAcceptance(acceptedTermsAndConditionsMaybe), Failure); + + if (requiredTermsAndConditionsMaybe.HasValue() && !acceptedTermsAndConditionsMaybe.HasValue()) { - response.errorCode = CommissioningErrorEnum::kInvalidAuthentication; - ChipLogError(FailSafe, "GeneralCommissioning: Got commissioning complete in invalid security context"); + response.errorCode = CommissioningErrorEnum::kTCAcknowledgementsNotReceived; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + return; } - else + + if (requiredTermsAndConditionsMaybe.HasValue() && acceptedTermsAndConditionsMaybe.HasValue()) { - if (failSafe.NocCommandHasBeenInvoked()) + TermsAndConditions requiredTermsAndConditions = requiredTermsAndConditionsMaybe.Value(); + TermsAndConditions acceptedTermsAndConditions = acceptedTermsAndConditionsMaybe.Value(); + + if (!requiredTermsAndConditions.ValidateVersion(acceptedTermsAndConditions)) { - CHIP_ERROR err = fabricTable.CommitPendingFabricData(); - if (err != CHIP_NO_ERROR) - { - // No need to revert on error: CommitPendingFabricData always reverts if not fully successful. - ChipLogError(FailSafe, "GeneralCommissioning: Failed to commit pending fabric data: %" CHIP_ERROR_FORMAT, - err.Format()); - } - else - { - ChipLogProgress(FailSafe, "GeneralCommissioning: Successfully commited pending fabric data"); - } - CheckSuccess(err, Failure); + response.errorCode = CommissioningErrorEnum::kTCMinVersionNotMet; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + return; } - /* - * Pass fabric of commissioner to DeviceControlSvr. - * This allows device to send messages back to commissioner. - * Once bindings are implemented, this may no longer be needed. - */ - failSafe.DisarmFailSafe(); - CheckSuccess( - devCtrl->PostCommissioningCompleteEvent(handle->AsSecureSession()->GetPeerNodeId(), handle->GetFabricIndex()), - Failure); + if (!requiredTermsAndConditions.ValidateValue(acceptedTermsAndConditions)) + { + response.errorCode = CommissioningErrorEnum::kRequiredTCNotAccepted; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + return; + } + } - Breadcrumb::Set(ctx.mRequestPath.mEndpointId, 0); - response.errorCode = CommissioningErrorEnum::kOk; + if (failSafe.UpdateTermsAndConditionsHasBeenInvoked()) + { + // Commit terms and conditions acceptance on commissioning complete + err = tcProvider->CommitAcceptance(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(FailSafe, "GeneralCommissioning: Failed to commit terms and conditions: %" CHIP_ERROR_FORMAT, + err.Format()); + } + else + { + ChipLogProgress(FailSafe, "GeneralCommissioning: Successfully committed terms and conditions"); + } + CheckSuccess(err, Failure); + } + } +#endif // CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED + + SessionHandle handle = ctx.mCommandHandler.GetExchangeContext()->GetSessionHandle(); + CHIP_ERROR err = CHIP_NO_ERROR; + + // Ensure it's a valid CASE session + if ((handle->GetSessionType() != Session::SessionType::kSecure) || + (handle->AsSecureSession()->GetSecureSessionType() != SecureSession::Type::kCASE) || + (!failSafe.MatchesFabricIndex(ctx.mCommandHandler.GetAccessingFabricIndex()))) + { + response.errorCode = CommissioningErrorEnum::kInvalidAuthentication; + ChipLogError(FailSafe, "GeneralCommissioning: Got commissioning complete in invalid security context"); + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + return; + } + + // Handle NOC commands + if (failSafe.NocCommandHasBeenInvoked()) + { + err = fabricTable.CommitPendingFabricData(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(FailSafe, "GeneralCommissioning: Failed to commit pending fabric data: %" CHIP_ERROR_FORMAT, err.Format()); + // CommitPendingFabricData reverts on error, no need to revert explicitly } + else + { + ChipLogProgress(FailSafe, "GeneralCommissioning: Successfully committed pending fabric data"); + } + CheckSuccess(err, Failure); } + // Disarm the fail-safe and notify the DeviceControlServer + failSafe.DisarmFailSafe(); + err = devCtrl->PostCommissioningCompleteEvent(handle->AsSecureSession()->GetPeerNodeId(), handle->GetFabricIndex()); + CheckSuccess(err, Failure); + + Breadcrumb::Set(ctx.mRequestPath.mEndpointId, 0); + response.errorCode = CommissioningErrorEnum::kOk; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); } @@ -351,26 +544,133 @@ void GeneralCommissioningGlobalInstance::HandleSetRegulatoryConfig(HandlerContex ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); } -} // anonymous namespace +void GeneralCommissioningGlobalInstance::HandleSetTCAcknowledgements( + HandlerContext & ctx, const Commands::SetTCAcknowledgements::DecodableType & commandData) +{ + MATTER_TRACE_SCOPE("SetTCAcknowledgements", "GeneralCommissioning"); + +#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED + auto & failSafeContext = Server::GetInstance().GetFailSafeContext(); + TermsAndConditionsProvider * tcProvider = TermsAndConditionsManager::GetInstance(); + + if (nullptr == tcProvider) + { + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::Failure); + return; + } + + Optional<TermsAndConditions> requiredTermsAndConditionsMaybe; + Optional<TermsAndConditions> previousAcceptedTermsAndConditionsMaybe; + CheckSuccess(tcProvider->GetRequirements(requiredTermsAndConditionsMaybe), Failure); + CheckSuccess(tcProvider->GetAcceptance(previousAcceptedTermsAndConditionsMaybe), Failure); + TermsAndConditions acceptedTermsAndConditions = TermsAndConditions(commandData.TCUserResponse, commandData.TCVersion); + Optional<TermsAndConditions> acceptedTermsAndConditionsPresent = Optional<TermsAndConditions>(acceptedTermsAndConditions); + + Commands::SetTCAcknowledgementsResponse::Type response; + + if (requiredTermsAndConditionsMaybe.HasValue()) + { + TermsAndConditions requiredTermsAndConditions = requiredTermsAndConditionsMaybe.Value(); + + if (!requiredTermsAndConditions.ValidateVersion(acceptedTermsAndConditions)) + { + response.errorCode = CommissioningErrorEnum::kTCMinVersionNotMet; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + return; + } + + if (!requiredTermsAndConditions.ValidateValue(acceptedTermsAndConditions)) + { + response.errorCode = CommissioningErrorEnum::kRequiredTCNotAccepted; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + return; + } + } + + if (previousAcceptedTermsAndConditionsMaybe != acceptedTermsAndConditionsPresent) + { + TermsAndConditionsState initialState, updatedState; + CheckSuccess(GetTermsAndConditionsAttributeState(tcProvider, initialState), Failure); + CheckSuccess(tcProvider->SetAcceptance(acceptedTermsAndConditionsPresent), Failure); + CheckSuccess(GetTermsAndConditionsAttributeState(tcProvider, updatedState), Failure); + NotifyTermsAndConditionsAttributeChangeIfRequired(initialState, updatedState); + + // Commit or defer based on fail-safe state + if (!failSafeContext.IsFailSafeArmed()) + { + CheckSuccess(tcProvider->CommitAcceptance(), Failure); + } + else + { + failSafeContext.SetUpdateTermsAndConditionsHasBeenInvoked(); + } + } + + response.errorCode = CommissioningErrorEnum::kOk; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); +#endif // CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED +} -namespace { void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg) { if (event->Type == DeviceLayer::DeviceEventType::kFailSafeTimerExpired) { // Spec says to reset Breadcrumb attribute to 0. Breadcrumb::Set(0, 0); + + if (event->FailSafeTimerExpired.updateTermsAndConditionsHasBeenInvoked) + { +#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED + // Clear terms and conditions acceptance on failsafe timer expiration + TermsAndConditionsProvider * tcProvider = TermsAndConditionsManager::GetInstance(); + TermsAndConditionsState initialState, updatedState; + VerifyOrReturn(nullptr != tcProvider); + VerifyOrReturn(CHIP_NO_ERROR == GetTermsAndConditionsAttributeState(tcProvider, initialState)); + VerifyOrReturn(CHIP_NO_ERROR == tcProvider->RevertAcceptance()); + VerifyOrReturn(CHIP_NO_ERROR == GetTermsAndConditionsAttributeState(tcProvider, updatedState)); + NotifyTermsAndConditionsAttributeChangeIfRequired(initialState, updatedState); +#endif // CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED + } } } } // anonymous namespace +class GeneralCommissioningFabricTableDelegate : public chip::FabricTable::Delegate +{ +public: + // Gets called when a fabric is deleted + void OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) override + { + // If the FabricIndex matches the last remaining entry in the Fabrics list, then the device SHALL delete all Matter + // related data on the node which was created since it was commissioned. + if (Server::GetInstance().GetFabricTable().FabricCount() == 0) + { + ChipLogProgress(Zcl, "general-commissioning-server: Last Fabric index 0x%x was removed", + static_cast<unsigned>(fabricIndex)); + +#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED + TermsAndConditionsProvider * tcProvider = TermsAndConditionsManager::GetInstance(); + TermsAndConditionsState initialState, updatedState; + VerifyOrReturn(nullptr != tcProvider); + VerifyOrReturn(CHIP_NO_ERROR == GetTermsAndConditionsAttributeState(tcProvider, initialState)); + VerifyOrReturn(CHIP_NO_ERROR == tcProvider->ResetAcceptance()); + VerifyOrReturn(CHIP_NO_ERROR == GetTermsAndConditionsAttributeState(tcProvider, updatedState)); + NotifyTermsAndConditionsAttributeChangeIfRequired(initialState, updatedState); +#endif // CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED + } + } +}; + void MatterGeneralCommissioningPluginServerInitCallback() { Breadcrumb::Set(0, 0); AttributeAccessInterfaceRegistry::Instance().Register(&gGeneralCommissioningInstance); ReturnOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(&gGeneralCommissioningInstance)); DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler); + + static GeneralCommissioningFabricTableDelegate generalCommissioningFabricTableDelegate; + Server::GetInstance().GetFabricTable().AddFabricDelegate(&generalCommissioningFabricTableDelegate); } namespace chip { diff --git a/src/app/clusters/occupancy-sensor-server/occupancy-sensor-server.cpp b/src/app/clusters/occupancy-sensor-server/occupancy-sensor-server.cpp index cd7ba5b8f659c2..03eaaa46475d1c 100644 --- a/src/app/clusters/occupancy-sensor-server/occupancy-sensor-server.cpp +++ b/src/app/clusters/occupancy-sensor-server/occupancy-sensor-server.cpp @@ -59,8 +59,12 @@ CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValu case Attributes::FeatureMap::Id: ReturnErrorOnFailure(aEncoder.Encode(mFeature)); break; - case Attributes::HoldTime::Id: { - + case Attributes::HoldTime::Id: + case Attributes::PIROccupiedToUnoccupiedDelay::Id: + case Attributes::UltrasonicOccupiedToUnoccupiedDelay::Id: + case Attributes::PhysicalContactOccupiedToUnoccupiedDelay::Id: { + // HoldTime is equivalent to the legacy *OccupiedToUnoccupiedDelay attributes. + // The AAI will read/write these attributes at the same storage for one endpoint. uint16_t * holdTime = GetHoldTimeForEndpoint(aPath.mEndpointId); if (holdTime == nullptr) @@ -190,12 +194,6 @@ CHIP_ERROR SetHoldTime(EndpointId endpointId, uint16_t newHoldTime) MatterReportingAttributeChangeCallback(endpointId, OccupancySensing::Id, Attributes::HoldTime::Id); } - // Blindly try to write RAM-backed legacy attributes (will fail silently if absent) - // to keep them in sync. - (void) Attributes::PIROccupiedToUnoccupiedDelay::Set(endpointId, newHoldTime); - (void) Attributes::UltrasonicOccupiedToUnoccupiedDelay::Set(endpointId, newHoldTime); - (void) Attributes::PhysicalContactOccupiedToUnoccupiedDelay::Set(endpointId, newHoldTime); - return CHIP_NO_ERROR; } diff --git a/src/app/clusters/user-label-server/user-label-server.cpp b/src/app/clusters/user-label-server/user-label-server.cpp index e1ea85cf01a78a..0030f628097696 100644 --- a/src/app/clusters/user-label-server/user-label-server.cpp +++ b/src/app/clusters/user-label-server/user-label-server.cpp @@ -143,6 +143,7 @@ CHIP_ERROR UserLabelAttrAccess::WriteLabelList(const ConcreteDataAttributePath & return provider->SetUserLabelList(endpoint, labelList); } + if (aPath.mListOp == ConcreteDataAttributePath::ListOperation::AppendItem) { Structs::LabelStruct::DecodableType entry; diff --git a/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-server.cpp b/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-server.cpp index f6fa4e8fee6332..fd89ab135d384c 100644 --- a/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-server.cpp +++ b/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-server.cpp @@ -360,9 +360,9 @@ CHIP_ERROR SetValveLevel(EndpointId ep, DataModel::Nullable<Percent> level, Data if (!isDelegateNull(delegate)) { DataModel::Nullable<Percent> cLevel = delegate->HandleOpenValve(level); - if (HasFeature(ep, ValveConfigurationAndControl::Feature::kLevel)) + if (HasFeature(ep, ValveConfigurationAndControl::Feature::kLevel) && !cLevel.IsNull()) { - VerifyOrReturnError(Status::Success == CurrentLevel::Set(ep, cLevel), attribute_error); + UpdateCurrentLevel(ep, cLevel.Value()); } } // start countdown @@ -376,14 +376,28 @@ CHIP_ERROR UpdateCurrentLevel(EndpointId ep, Percent currentLevel) if (HasFeature(ep, ValveConfigurationAndControl::Feature::kLevel)) { VerifyOrReturnError(Status::Success == CurrentLevel::Set(ep, currentLevel), CHIP_IM_GLOBAL_STATUS(ConstraintError)); - return CHIP_NO_ERROR; } - return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); + DataModel::Nullable<Percent> targetLevel = DataModel::NullNullable; + TargetLevel::Get(ep, targetLevel); + if (!targetLevel.IsNull() && currentLevel == targetLevel.Value()) + { + targetLevel = DataModel::NullNullable; + TargetLevel::Set(ep, targetLevel); + UpdateCurrentState(ep, currentLevel == 0 ? ValveStateEnum::kClosed : ValveStateEnum::kOpen); + } + return CHIP_NO_ERROR; } CHIP_ERROR UpdateCurrentState(EndpointId ep, ValveConfigurationAndControl::ValveStateEnum currentState) { VerifyOrReturnError(Status::Success == CurrentState::Set(ep, currentState), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + DataModel::Nullable<ValveStateEnum> targetState = DataModel::NullNullable; + TargetState::Get(ep, targetState); + if (currentState == targetState.ValueOr(ValveStateEnum::kUnknownEnumValue)) + { + targetState = DataModel::NullNullable; + TargetState::Set(ep, targetState); + } emitValveStateChangedEvent(ep, currentState); return CHIP_NO_ERROR; } diff --git a/src/app/common_flags.gni b/src/app/common_flags.gni index 30678dfe330f2f..7fd111c371b548 100644 --- a/src/app/common_flags.gni +++ b/src/app/common_flags.gni @@ -25,6 +25,10 @@ declare_args() { # communicated to OperationalSessionSetup API consumers. chip_enable_busy_handling_for_operational_session_setup = true + # Controls whether the device commissioning process requires the user to + # acknowledge terms and conditions during commissioning. + chip_terms_and_conditions_required = false + # This controls if more logging is supposed to be enabled into the data models. # This is an optimization for small-flash size devices as extra logging requires # additional flash for messages & code for formatting. diff --git a/src/app/server/BUILD.gn b/src/app/server/BUILD.gn index fb25ae0f38bf6b..040c7b2227ff2a 100644 --- a/src/app/server/BUILD.gn +++ b/src/app/server/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Project CHIP Authors +# Copyright (c) 2020-2024 Project CHIP Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -25,6 +25,22 @@ config("server_config") { } } +source_set("terms_and_conditions") { + sources = [ + "DefaultTermsAndConditionsProvider.cpp", + "DefaultTermsAndConditionsProvider.h", + "TermsAndConditionsManager.cpp", + "TermsAndConditionsManager.h", + "TermsAndConditionsProvider.h", + ] + + public_deps = [ + "${chip_root}/src/lib/core", + "${chip_root}/src/lib/support", + "${chip_root}/src/protocols", + ] +} + static_library("server") { output_name = "libCHIPAppServer" @@ -69,6 +85,10 @@ static_library("server") { "${chip_root}/src/transport", ] + if (chip_terms_and_conditions_required) { + public_deps += [ ":terms_and_conditions" ] + } + # TODO: Server.cpp uses TestGroupData.h. Unsure why test code would be in such a central place # This dependency is split since it should probably be removed (or naming should # be updated if this is not really "testing" even though headers are Test*.h) diff --git a/src/app/server/DefaultTermsAndConditionsProvider.cpp b/src/app/server/DefaultTermsAndConditionsProvider.cpp new file mode 100644 index 00000000000000..36431aea456128 --- /dev/null +++ b/src/app/server/DefaultTermsAndConditionsProvider.cpp @@ -0,0 +1,251 @@ +/* + * 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 "DefaultTermsAndConditionsProvider.h" +#include "TermsAndConditionsProvider.h" + +#include <lib/core/CHIPError.h> +#include <lib/core/TLV.h> +#include <lib/core/TLVTypes.h> +#include <lib/support/CodeUtils.h> +#include <lib/support/DefaultStorageKeyAllocator.h> +#include <lib/support/SafeInt.h> +#include <protocols/Protocols.h> +#include <protocols/interaction_model/StatusCode.h> + +namespace { +constexpr chip::TLV::Tag kSerializationVersionTag = chip::TLV::ContextTag(1); +constexpr chip::TLV::Tag kAcceptedAcknowledgementsTag = chip::TLV::ContextTag(2); +constexpr chip::TLV::Tag kAcceptedAcknowledgementsVersionTag = chip::TLV::ContextTag(3); +constexpr uint8_t kSerializationSchemaMinimumVersion = 1; +constexpr uint8_t kSerializationSchemaCurrentVersion = 1; + +constexpr size_t kEstimatedTlvBufferSize = chip::TLV::EstimateStructOverhead(sizeof(uint8_t), // SerializationVersion + sizeof(uint16_t), // AcceptedAcknowledgements + sizeof(uint16_t) // AcceptedAcknowledgementsVersion + ) * + 4; // Extra space for rollback compatibility +} // namespace + +CHIP_ERROR chip::app::DefaultTermsAndConditionsStorageDelegate::Init(PersistentStorageDelegate * inPersistentStorageDelegate) +{ + VerifyOrReturnValue(nullptr != inPersistentStorageDelegate, CHIP_ERROR_INVALID_ARGUMENT); + + mStorageDelegate = inPersistentStorageDelegate; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultTermsAndConditionsStorageDelegate::Delete() +{ + VerifyOrReturnValue(nullptr != mStorageDelegate, CHIP_ERROR_UNINITIALIZED); + + const chip::StorageKeyName kStorageKey = chip::DefaultStorageKeyAllocator::TermsAndConditionsAcceptance(); + ReturnErrorOnFailure(mStorageDelegate->SyncDeleteKeyValue(kStorageKey.KeyName())); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultTermsAndConditionsStorageDelegate::Get(Optional<TermsAndConditions> & outTermsAndConditions) +{ + VerifyOrReturnValue(nullptr != mStorageDelegate, CHIP_ERROR_UNINITIALIZED); + + uint8_t serializationVersion = 0; + uint16_t acknowledgements = 0; + uint16_t acknowledgementsVersion = 0; + + chip::TLV::TLVReader tlvReader; + chip::TLV::TLVType tlvContainer; + + uint8_t buffer[kEstimatedTlvBufferSize] = { 0 }; + uint16_t bufferSize = sizeof(buffer); + + const chip::StorageKeyName kStorageKey = chip::DefaultStorageKeyAllocator::TermsAndConditionsAcceptance(); + + CHIP_ERROR err = mStorageDelegate->SyncGetKeyValue(kStorageKey.KeyName(), &buffer, bufferSize); + VerifyOrReturnValue(CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND == err || CHIP_NO_ERROR == err, err); + + if (CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND == err) + { + outTermsAndConditions.ClearValue(); + return CHIP_NO_ERROR; + } + + tlvReader.Init(buffer, bufferSize); + ReturnErrorOnFailure(tlvReader.Next(chip::TLV::kTLVType_Structure, chip::TLV::AnonymousTag())); + ReturnErrorOnFailure(tlvReader.EnterContainer(tlvContainer)); + ReturnErrorOnFailure(tlvReader.Next(kSerializationVersionTag)); + ReturnErrorOnFailure(tlvReader.Get(serializationVersion)); + + if (serializationVersion < kSerializationSchemaMinimumVersion) + { + ChipLogError(AppServer, "The terms and conditions datastore schema (%hhu) is newer than oldest compatible schema (%hhu)", + serializationVersion, kSerializationSchemaMinimumVersion); + return CHIP_IM_GLOBAL_STATUS(ConstraintError); + } + + if (serializationVersion != kSerializationSchemaCurrentVersion) + { + ChipLogDetail(AppServer, "The terms and conditions datastore schema (%hhu) differs from current schema (%hhu)", + serializationVersion, kSerializationSchemaCurrentVersion); + } + + ReturnErrorOnFailure(tlvReader.Next(kAcceptedAcknowledgementsTag)); + ReturnErrorOnFailure(tlvReader.Get(acknowledgements)); + ReturnErrorOnFailure(tlvReader.Next(kAcceptedAcknowledgementsVersionTag)); + ReturnErrorOnFailure(tlvReader.Get(acknowledgementsVersion)); + ReturnErrorOnFailure(tlvReader.ExitContainer(tlvContainer)); + + outTermsAndConditions = Optional<TermsAndConditions>(TermsAndConditions(acknowledgements, acknowledgementsVersion)); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultTermsAndConditionsStorageDelegate::Set(const TermsAndConditions & inTermsAndConditions) +{ + uint8_t buffer[kEstimatedTlvBufferSize] = { 0 }; + chip::TLV::TLVWriter tlvWriter; + chip::TLV::TLVType tlvContainer; + + VerifyOrReturnValue(nullptr != mStorageDelegate, CHIP_ERROR_UNINITIALIZED); + + tlvWriter.Init(buffer); + ReturnErrorOnFailure(tlvWriter.StartContainer(chip::TLV::AnonymousTag(), chip::TLV::kTLVType_Structure, tlvContainer)); + ReturnErrorOnFailure(tlvWriter.Put(kSerializationVersionTag, kSerializationSchemaCurrentVersion)); + ReturnErrorOnFailure(tlvWriter.Put(kAcceptedAcknowledgementsTag, inTermsAndConditions.GetValue())); + ReturnErrorOnFailure(tlvWriter.Put(kAcceptedAcknowledgementsVersionTag, inTermsAndConditions.GetVersion())); + ReturnErrorOnFailure(tlvWriter.EndContainer(tlvContainer)); + ReturnErrorOnFailure(tlvWriter.Finalize()); + + const chip::StorageKeyName kStorageKey = chip::DefaultStorageKeyAllocator::TermsAndConditionsAcceptance(); + ReturnErrorOnFailure( + mStorageDelegate->SyncSetKeyValue(kStorageKey.KeyName(), buffer, static_cast<uint16_t>(tlvWriter.GetLengthWritten()))); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::Init( + TermsAndConditionsStorageDelegate * inStorageDelegate, + const chip::Optional<chip::app::TermsAndConditions> & inRequiredTermsAndConditions) +{ + VerifyOrReturnValue(nullptr != inStorageDelegate, CHIP_ERROR_INVALID_ARGUMENT); + + mTermsAndConditionsStorageDelegate = inStorageDelegate; + mRequiredAcknowledgements = inRequiredTermsAndConditions; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::CommitAcceptance() +{ + VerifyOrReturnValue(nullptr != mTermsAndConditionsStorageDelegate, CHIP_ERROR_UNINITIALIZED); + + // No terms and conditions to commit + VerifyOrReturnValue(mTemporalAcceptance.HasValue(), CHIP_NO_ERROR); + + ReturnErrorOnFailure(mTermsAndConditionsStorageDelegate->Set(mTemporalAcceptance.Value())); + ChipLogProgress(AppServer, "Terms and conditions have been committed"); + mTemporalAcceptance.ClearValue(); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::GetAcceptance(Optional<TermsAndConditions> & outTermsAndConditions) const +{ + VerifyOrReturnValue(nullptr != mTermsAndConditionsStorageDelegate, CHIP_ERROR_UNINITIALIZED); + + // Return the in-memory acceptance state + if (mTemporalAcceptance.HasValue()) + { + outTermsAndConditions = mTemporalAcceptance; + return CHIP_NO_ERROR; + } + + // Otherwise, try to get the persisted acceptance state + CHIP_ERROR err = mTermsAndConditionsStorageDelegate->Get(outTermsAndConditions); + VerifyOrReturnValue(CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND == err || CHIP_NO_ERROR == err, err); + + if (CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND == err) + { + ChipLogError(AppServer, "No terms and conditions have been accepted"); + outTermsAndConditions.ClearValue(); + return CHIP_NO_ERROR; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::GetAcknowledgementsRequired(bool & outAcknowledgementsRequired) const +{ + Optional<TermsAndConditions> requiredTermsAndConditionsMaybe; + ReturnErrorOnFailure(GetRequirements(requiredTermsAndConditionsMaybe)); + + if (!requiredTermsAndConditionsMaybe.HasValue()) + { + outAcknowledgementsRequired = false; + return CHIP_NO_ERROR; + } + + Optional<TermsAndConditions> acceptedTermsAndConditionsMaybe; + ReturnErrorOnFailure(GetAcceptance(acceptedTermsAndConditionsMaybe)); + + if (!acceptedTermsAndConditionsMaybe.HasValue()) + { + outAcknowledgementsRequired = true; + return CHIP_NO_ERROR; + } + + TermsAndConditions requiredTermsAndConditions = requiredTermsAndConditionsMaybe.Value(); + TermsAndConditions acceptedTermsAndConditions = acceptedTermsAndConditionsMaybe.Value(); + outAcknowledgementsRequired = requiredTermsAndConditions.Validate(acceptedTermsAndConditions); + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::GetRequirements(Optional<TermsAndConditions> & outTermsAndConditions) const +{ + outTermsAndConditions = mRequiredAcknowledgements; + return CHIP_NO_ERROR; +} + +CHIP_ERROR +chip::app::DefaultTermsAndConditionsProvider::GetUpdateAcceptanceDeadline(Optional<uint32_t> & outUpdateAcceptanceDeadline) const +{ + // No-op stub implementation. This feature is not implemented in this default implementation. + outUpdateAcceptanceDeadline = Optional<uint32_t>(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::ResetAcceptance() +{ + VerifyOrReturnValue(nullptr != mTermsAndConditionsStorageDelegate, CHIP_ERROR_UNINITIALIZED); + + (void) mTermsAndConditionsStorageDelegate->Delete(); + ReturnErrorOnFailure(RevertAcceptance()); + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::RevertAcceptance() +{ + mTemporalAcceptance.ClearValue(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::SetAcceptance(const Optional<TermsAndConditions> & inTermsAndConditions) +{ + mTemporalAcceptance = inTermsAndConditions; + return CHIP_NO_ERROR; +} diff --git a/src/app/server/DefaultTermsAndConditionsProvider.h b/src/app/server/DefaultTermsAndConditionsProvider.h new file mode 100644 index 00000000000000..8bc3d0761b3e21 --- /dev/null +++ b/src/app/server/DefaultTermsAndConditionsProvider.h @@ -0,0 +1,152 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "TermsAndConditionsProvider.h" + +#include <stdint.h> + +#include <lib/core/CHIPError.h> +#include <lib/core/CHIPPersistentStorageDelegate.h> +#include <lib/core/Optional.h> + +namespace chip { +namespace app { + +/** + * @brief Abstract interface for storing and retrieving terms and conditions acceptance status. + * + * This class defines the methods required to interact with the underlying storage system + * for saving, retrieving, and deleting the user's acceptance of terms and conditions. + */ +class TermsAndConditionsStorageDelegate +{ +public: + virtual ~TermsAndConditionsStorageDelegate() = default; + + /** + * @brief Deletes the persisted terms and conditions acceptance status from storage. + * + * This method deletes the stored record of the user's acceptance of the terms and conditions, + * effectively resetting their acceptance status in the persistent storage. + * + * @retval CHIP_NO_ERROR if the record was successfully deleted. + * @retval CHIP_ERROR_UNINITIALIZED if the storage delegate is not properly initialized. + * @retval CHIP_ERROR_* for other errors. + */ + virtual CHIP_ERROR Delete() = 0; + + /** + * @brief Retrieves the persisted terms and conditions acceptance status from storage. + * + * This method attempts to retrieve the previously accepted terms and conditions from + * persistent storage. If no such record exists, it returns an empty `Optional`. + * + * @param[out] outTermsAndConditions The retrieved terms and conditions, if any exist. + * + * @retval CHIP_NO_ERROR if the terms were successfully retrieved. + * @retval CHIP_ERROR_UNINITIALIZED if the storage delegate is not properly initialized. + * @retval CHIP_ERROR_* for other errors. + */ + virtual CHIP_ERROR Get(Optional<TermsAndConditions> & outTermsAndConditions) = 0; + + /** + * @brief Persists the user's acceptance of the terms and conditions. + * + * This method stores the provided terms and conditions acceptance status in persistent + * storage, allowing the user's acceptance to be retrieved later. + * + * @param[in] inTermsAndConditions The terms and conditions to be saved. + * + * @retval CHIP_NO_ERROR if the terms were successfully stored. + * @retval CHIP_ERROR_UNINITIALIZED if the storage delegate is not properly initialized. + * @retval CHIP_ERROR_* for other errors. + */ + virtual CHIP_ERROR Set(const TermsAndConditions & inTermsAndConditions) = 0; +}; + +/** + * @brief Default implementation of the TermsAndConditionsStorageDelegate using a persistent storage backend. + * + * This class provides an implementation of the TermsAndConditionsStorageDelegate interface, storing + * and retrieving the user's terms and conditions acceptance from persistent storage. It requires a + * PersistentStorageDelegate to interface with the storage system. + */ +class DefaultTermsAndConditionsStorageDelegate : public TermsAndConditionsStorageDelegate +{ +public: + /** + * @brief Initializes the storage delegate with a persistent storage backend. + * + * This method initializes the storage delegate with the provided persistent storage delegate. + * The storage delegate must be initialized before performing any operations. + * + * @param[in] inPersistentStorageDelegate The storage backend used for saving and retrieving data. + * + * @retval CHIP_NO_ERROR if the storage delegate was successfully initialized. + * @retval CHIP_ERROR_INVALID_ARGUMENT if the provided storage delegate is null. + */ + CHIP_ERROR Init(PersistentStorageDelegate * inPersistentStorageDelegate); + + CHIP_ERROR Delete() override; + + CHIP_ERROR Get(Optional<TermsAndConditions> & inTermsAndConditions) override; + + CHIP_ERROR Set(const TermsAndConditions & inTermsAndConditions) override; + +private: + PersistentStorageDelegate * mStorageDelegate = nullptr; +}; + +class DefaultTermsAndConditionsProvider : public TermsAndConditionsProvider +{ +public: + /** + * @brief Initializes the TermsAndConditionsProvider. + * + * @param[in] inStorageDelegate Storage delegate dependency. + * @param[in] inRequiredTermsAndConditions The required terms and conditions that must be met. + */ + CHIP_ERROR Init(TermsAndConditionsStorageDelegate * inStorageDelegate, + const Optional<TermsAndConditions> & inRequiredTermsAndConditions); + + CHIP_ERROR CommitAcceptance() override; + + CHIP_ERROR GetAcceptance(Optional<TermsAndConditions> & outTermsAndConditions) const override; + + CHIP_ERROR GetAcknowledgementsRequired(bool & outAcknowledgementsRequired) const override; + + CHIP_ERROR GetRequirements(Optional<TermsAndConditions> & outTermsAndConditions) const override; + + CHIP_ERROR GetUpdateAcceptanceDeadline(Optional<uint32_t> & outUpdateAcceptanceDeadline) const override; + + CHIP_ERROR ResetAcceptance() override; + + CHIP_ERROR RevertAcceptance() override; + + CHIP_ERROR SetAcceptance(const Optional<TermsAndConditions> & inTermsAndConditions) override; + +private: + TermsAndConditionsStorageDelegate * mTermsAndConditionsStorageDelegate; + Optional<TermsAndConditions> mTemporalAcceptance; + Optional<TermsAndConditions> mRequiredAcknowledgements; +}; + +} // namespace app +} // namespace chip diff --git a/src/app/server/TermsAndConditionsManager.cpp b/src/app/server/TermsAndConditionsManager.cpp new file mode 100644 index 00000000000000..4946bf37d2611f --- /dev/null +++ b/src/app/server/TermsAndConditionsManager.cpp @@ -0,0 +1,80 @@ +/* + * + * 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 "TermsAndConditionsManager.h" + +#include "DefaultTermsAndConditionsProvider.h" + +static chip::app::TermsAndConditionsManager sTermsAndConditionsManager; +static chip::app::DefaultTermsAndConditionsProvider sTermsAndConditionsProviderInstance; +static chip::app::DefaultTermsAndConditionsStorageDelegate sTermsAndConditionsStorageDelegateInstance; + +chip::app::TermsAndConditionsManager * chip::app::TermsAndConditionsManager::GetInstance() +{ + return &sTermsAndConditionsManager; +} + +CHIP_ERROR chip::app::TermsAndConditionsManager::Init(chip::PersistentStorageDelegate * inPersistentStorageDelegate, + const Optional<TermsAndConditions> & inRequiredTermsAndConditions) +{ + ReturnErrorOnFailure(sTermsAndConditionsStorageDelegateInstance.Init(inPersistentStorageDelegate)); + ReturnErrorOnFailure( + sTermsAndConditionsProviderInstance.Init(&sTermsAndConditionsStorageDelegateInstance, inRequiredTermsAndConditions)); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::TermsAndConditionsManager::CommitAcceptance() +{ + return sTermsAndConditionsProviderInstance.CommitAcceptance(); +} + +CHIP_ERROR chip::app::TermsAndConditionsManager::GetAcceptance(Optional<TermsAndConditions> & outTermsAndConditions) const +{ + return sTermsAndConditionsProviderInstance.GetAcceptance(outTermsAndConditions); +} + +CHIP_ERROR chip::app::TermsAndConditionsManager::GetAcknowledgementsRequired(bool & outAcknowledgementsRequired) const +{ + return sTermsAndConditionsProviderInstance.GetAcknowledgementsRequired(outAcknowledgementsRequired); +} + +CHIP_ERROR chip::app::TermsAndConditionsManager::GetRequirements(Optional<TermsAndConditions> & outTermsAndConditions) const +{ + return sTermsAndConditionsProviderInstance.GetRequirements(outTermsAndConditions); +} + +CHIP_ERROR chip::app::TermsAndConditionsManager::GetUpdateAcceptanceDeadline(Optional<uint32_t> & outUpdateAcceptanceDeadline) const +{ + return sTermsAndConditionsProviderInstance.GetUpdateAcceptanceDeadline(outUpdateAcceptanceDeadline); +} + +CHIP_ERROR chip::app::TermsAndConditionsManager::ResetAcceptance() +{ + return sTermsAndConditionsProviderInstance.ResetAcceptance(); +} + +CHIP_ERROR chip::app::TermsAndConditionsManager::RevertAcceptance() +{ + return sTermsAndConditionsProviderInstance.RevertAcceptance(); +} + +CHIP_ERROR chip::app::TermsAndConditionsManager::SetAcceptance(const Optional<TermsAndConditions> & inTermsAndConditions) +{ + return sTermsAndConditionsProviderInstance.SetAcceptance(inTermsAndConditions); +} diff --git a/src/app/server/TermsAndConditionsManager.h b/src/app/server/TermsAndConditionsManager.h new file mode 100644 index 00000000000000..02101bbec46425 --- /dev/null +++ b/src/app/server/TermsAndConditionsManager.h @@ -0,0 +1,45 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <lib/core/CHIPPersistentStorageDelegate.h> + +#include "TermsAndConditionsProvider.h" + +namespace chip { +namespace app { + +class TermsAndConditionsManager : public TermsAndConditionsProvider +{ +public: + static TermsAndConditionsManager * GetInstance(); + CHIP_ERROR Init(PersistentStorageDelegate * inPersistentStorageDelegate, + const Optional<TermsAndConditions> & inRequiredTermsAndConditions); + CHIP_ERROR CommitAcceptance(); + CHIP_ERROR GetAcceptance(Optional<TermsAndConditions> & outTermsAndConditions) const; + CHIP_ERROR GetAcknowledgementsRequired(bool & outAcknowledgementsRequired) const; + CHIP_ERROR GetRequirements(Optional<TermsAndConditions> & outTermsAndConditions) const; + CHIP_ERROR GetUpdateAcceptanceDeadline(Optional<uint32_t> & outUpdateAcceptanceDeadline) const; + CHIP_ERROR ResetAcceptance(); + CHIP_ERROR RevertAcceptance(); + CHIP_ERROR SetAcceptance(const Optional<TermsAndConditions> & inTermsAndConditions); +}; + +} // namespace app +} // namespace chip diff --git a/src/app/server/TermsAndConditionsProvider.h b/src/app/server/TermsAndConditionsProvider.h new file mode 100644 index 00000000000000..cb0b6f0b8f088a --- /dev/null +++ b/src/app/server/TermsAndConditionsProvider.h @@ -0,0 +1,224 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <stdint.h> + +#include <lib/core/CHIPError.h> +#include <lib/core/Optional.h> + +namespace chip { +namespace app { + +/** + * @brief Represents a pair of terms and conditions value and version. + * + * This class encapsulates terms and conditions with methods to validate a user's accepted value and version against required + * criteria. + */ +class TermsAndConditions +{ +public: + TermsAndConditions(uint16_t inValue, uint16_t inVersion) : value(inValue), version(inVersion) {} + + bool operator==(const TermsAndConditions & other) const { return value == other.value && version == other.version; } + bool operator!=(const TermsAndConditions & other) const { return !(*this == other); } + + /** + * @brief Retrieves the terms and conditions value (accepted bits). + * + * @return The value of the terms and conditions. + */ + uint16_t GetValue() const { return value; } + + /** + * @brief Retrieves the terms and conditions version. + * + * @return The version of the terms and conditions. + */ + uint16_t GetVersion() const { return version; } + + /** + * @brief Validates the terms and conditions value. + * + * Checks whether all required bits are set in the accepted terms and conditions. + * + * @param acceptedTermsAndConditions The user's accepted terms and conditions. + * @return True if all required bits are set, false otherwise. + */ + bool ValidateValue(const TermsAndConditions & acceptedTermsAndConditions) const + { + // Check if all required bits are set in the user-accepted value. + return ((value & acceptedTermsAndConditions.GetValue()) == value); + } + + /** + * @brief Validates the terms and conditions version. + * + * Checks whether the accepted version is greater than or equal to the required version. + * + * @param acceptedTermsAndConditions The user's accepted terms and conditions. + * @return True if the accepted version is valid, false otherwise. + */ + bool ValidateVersion(const TermsAndConditions & acceptedTermsAndConditions) const + { + // Check if the version is below the minimum required version. + return (acceptedTermsAndConditions.GetVersion() >= version); + } + + /** + * @brief Validates the terms and conditions. + * + * Combines validation of both value and version to ensure compliance with requirements. + * + * @param acceptedTermsAndConditions The user's accepted terms and conditions. + * @return True if both value and version validations pass, false otherwise. + */ + bool Validate(const TermsAndConditions & acceptedTermsAndConditions) const + { + return ValidateVersion(acceptedTermsAndConditions) && ValidateValue(acceptedTermsAndConditions); + } + +private: + const uint16_t value; + const uint16_t version; +}; + +/** + * @brief Data access layer for handling the required terms and conditions and managing user acceptance status. + * + * This class provides methods to manage the acceptance of terms and conditions, including storing, retrieving, + * and verifying the acceptance status. It also supports temporary in-memory storage and persistent storage for + * accepted terms and conditions. + */ +class TermsAndConditionsProvider +{ +public: + virtual ~TermsAndConditionsProvider() = default; + + /** + * @brief Persists the acceptance of the terms and conditions. + * + * This method commits the in-memory acceptance status to persistent storage. It stores the acceptance + * status in a permanent location and clears the temporary in-memory acceptance state after committing. + * + * @retval CHIP_NO_ERROR if the terms were successfully persisted. + * @retval CHIP_ERROR_UNINITIALIZED if the module has not been initialized. + * @retval CHIP_ERROR_* for other errors. + */ + virtual CHIP_ERROR CommitAcceptance() = 0; + + /** + * @brief Retrieves the current acceptance status of the terms and conditions. + * + * This method checks the temporary in-memory acceptance state first. If no in-memory state is found, + * it attempts to retrieve the acceptance status from persistent storage. If no terms have been accepted, + * it returns an empty `Optional`. + * + * @param[out] outTermsAndConditions The current accepted terms and conditions, if any. + * + * @retval CHIP_NO_ERROR if the terms were successfully retrieved or no terms were found. + * @retval CHIP_ERROR_UNINITIALIZED if the module has not been initialized. + * @retval CHIP_ERROR_* for other errors. + */ + virtual CHIP_ERROR GetAcceptance(Optional<TermsAndConditions> & outTermsAndConditions) const = 0; + + /** + * @brief Determines if acknowledgments are required. + * + * @param[out] outAcknowledgementsRequired True if acknowledgments are required, false otherwise. + * + * @retval CHIP_NO_ERROR if successful. + * @retval CHIP_ERROR_UNINITIALIZED if the module has not been initialized. + * @retval CHIP_ERROR_* for other errors. + */ + virtual CHIP_ERROR GetAcknowledgementsRequired(bool & outAcknowledgementsRequired) const = 0; + + /** + * @brief Retrieves the requirements for the terms and conditions. + * + * This method retrieves the required terms and conditions that must be accepted by the user. These + * requirements are set by the provider and used to validate the acceptance. + * + * @param[out] outTermsAndConditions The required terms and conditions. + * + * @retval CHIP_NO_ERROR if the required terms were successfully retrieved. + * @retval CHIP_ERROR_UNINITIALIZED if the module has not been initialized. + * @retval CHIP_ERROR_* for other errors. + */ + virtual CHIP_ERROR GetRequirements(Optional<TermsAndConditions> & outTermsAndConditions) const = 0; + + /** + * @brief Retrieves the deadline for accepting updated terms and conditions. + * + * This method retrieves the deadline by which the user must accept updated terms and conditions. + * If no deadline is set, it returns an empty `Optional`. + * + * @param[out] outUpdateAcceptanceDeadline The deadline (in seconds) by which updated terms must be accepted. + * Returns empty Optional if no deadline is set. + * + * @retval CHIP_NO_ERROR if the deadline was successfully retrieved or no deadline was found. + * @retval CHIP_ERROR_UNINITIALIZED if the module has not been initialized. + * @retval CHIP_ERROR_* for other errors. + */ + virtual CHIP_ERROR GetUpdateAcceptanceDeadline(Optional<uint32_t> & outUpdateAcceptanceDeadline) const = 0; + + /** + * @brief Resets the persisted acceptance status. + * + * This method deletes the persisted acceptance of the terms and conditions from storage, effectively + * resetting the stored acceptance status. Any in-memory temporary acceptance will also be cleared + * through this method. + * + * @retval CHIP_NO_ERROR if the terms were successfully reset. + * @retval CHIP_ERROR_UNINITIALIZED if the module has not been initialized. + * @retval CHIP_ERROR_* for other errors. + */ + virtual CHIP_ERROR ResetAcceptance() = 0; + + /** + * @brief Clears the in-memory temporary acceptance status. + * + * This method clears any temporary acceptance of the terms and conditions that is held in-memory. It does + * not affect the persisted state stored in storage. + * + * @retval CHIP_NO_ERROR if the in-memory acceptance state was successfully cleared. + * @retval CHIP_ERROR_UNINITIALIZED if the module has not been initialized. + * @retval CHIP_ERROR_* for other errors. + */ + virtual CHIP_ERROR RevertAcceptance() = 0; + + /** + * @brief Sets the temporary in-memory acceptance status of the terms and conditions. + * + * This method stores the provided terms and conditions acceptance status in-memory. It does not persist + * the acceptance status to storage. To persist the acceptance, call `CommitAcceptance()` after this method. + * + * @param[in] inTermsAndConditions The terms and conditions to be accepted temporarily. + * + * @retval CHIP_NO_ERROR if the terms were successfully stored in-memory. + * @retval CHIP_ERROR_INVALID_ARGUMENT if the provided terms and conditions are invalid. + * @retval CHIP_ERROR_UNINITIALIZED if the module has not been initialized. + * @retval CHIP_ERROR_* for other errors. + */ + virtual CHIP_ERROR SetAcceptance(const Optional<TermsAndConditions> & inTermsAndConditions) = 0; +}; + +} // namespace app +} // namespace chip diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index 912c1e32a0ef5a..1923573765101a 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Project CHIP Authors +# Copyright (c) 2020-2024 Project CHIP Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -211,6 +211,7 @@ chip_test_suite("tests") { "TestDataModelSerialization.cpp", "TestDefaultOTARequestorStorage.cpp", "TestDefaultSafeAttributePersistenceProvider.cpp", + "TestDefaultTermsAndConditionsProvider.cpp", "TestDefaultThreadNetworkDirectoryStorage.cpp", "TestEcosystemInformationCluster.cpp", "TestEventLoggingNoUTCTime.cpp", @@ -252,6 +253,8 @@ chip_test_suite("tests") { "${chip_root}/src/app/data-model-provider/tests:encode-decode", "${chip_root}/src/app/icd/client:handler", "${chip_root}/src/app/icd/client:manager", + "${chip_root}/src/app/server", + "${chip_root}/src/app/server:terms_and_conditions", "${chip_root}/src/app/tests:helpers", "${chip_root}/src/app/util/mock:mock_codegen_data_model", "${chip_root}/src/app/util/mock:mock_ember", diff --git a/src/app/tests/TestDefaultTermsAndConditionsProvider.cpp b/src/app/tests/TestDefaultTermsAndConditionsProvider.cpp new file mode 100644 index 00000000000000..dc2a66278aa5d2 --- /dev/null +++ b/src/app/tests/TestDefaultTermsAndConditionsProvider.cpp @@ -0,0 +1,435 @@ +/* + * + * 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 "app/server/DefaultTermsAndConditionsProvider.h" +#include "app/server/TermsAndConditionsProvider.h" +#include "pw_unit_test/framework.h" + +#include <lib/core/CHIPError.h> +#include <lib/core/StringBuilderAdapters.h> +#include <lib/support/TestPersistentStorageDelegate.h> +#include <pw_unit_test/framework.h> + +class TestTermsAndConditionsStorageDelegate : public chip::app::TermsAndConditionsStorageDelegate +{ +public: + TestTermsAndConditionsStorageDelegate(chip::Optional<chip::app::TermsAndConditions> & initialTermsAndConditions) : + mTermsAndConditions(initialTermsAndConditions) + {} + + CHIP_ERROR Delete() + { + mTermsAndConditions.ClearValue(); + return CHIP_NO_ERROR; + } + + CHIP_ERROR Get(chip::Optional<chip::app::TermsAndConditions> & outTermsAndConditions) + { + outTermsAndConditions = mTermsAndConditions; + return CHIP_NO_ERROR; + } + + CHIP_ERROR Set(const chip::app::TermsAndConditions & inTermsAndConditions) + { + mTermsAndConditions = chip::Optional<chip::app::TermsAndConditions>(inTermsAndConditions); + return CHIP_NO_ERROR; + } + +private: + chip::Optional<chip::app::TermsAndConditions> & mTermsAndConditions; +}; + +TEST(DefaultTermsAndConditionsProvider, TestInitSuccess) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate testPersistentStorageDelegate; + chip::app::DefaultTermsAndConditionsStorageDelegate defaultTermsAndConditionsStorageDelegate; + err = defaultTermsAndConditionsStorageDelegate.Init(&testPersistentStorageDelegate); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::app::DefaultTermsAndConditionsProvider defaultTermsAndConditionsProvider; + chip::Optional<chip::app::TermsAndConditions> requiredTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(1, 1)); + err = defaultTermsAndConditionsProvider.Init(&defaultTermsAndConditionsStorageDelegate, requiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); +} + +TEST(DefaultTermsAndConditionsProvider, TestNoRequirementsGetRequirementsSuccess) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate testPersistentStorageDelegate; + chip::app::DefaultTermsAndConditionsStorageDelegate defaultTermsAndConditionsStorageDelegate; + err = defaultTermsAndConditionsStorageDelegate.Init(&testPersistentStorageDelegate); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::app::DefaultTermsAndConditionsProvider defaultTermsAndConditionsProvider; + chip::Optional<chip::app::TermsAndConditions> requiredTermsAndConditions = chip::Optional<chip::app::TermsAndConditions>(); + err = defaultTermsAndConditionsProvider.Init(&defaultTermsAndConditionsStorageDelegate, requiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::Optional<chip::app::TermsAndConditions> outTermsAndConditions; + err = defaultTermsAndConditionsProvider.GetAcceptance(outTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_FALSE(outTermsAndConditions.HasValue()); +} + +TEST(DefaultTermsAndConditionsProvider, TestNeverAcceptanceGetAcceptanceSuccess) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate testPersistentStorageDelegate; + chip::app::DefaultTermsAndConditionsStorageDelegate defaultTermsAndConditionsStorageDelegate; + err = defaultTermsAndConditionsStorageDelegate.Init(&testPersistentStorageDelegate); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::app::DefaultTermsAndConditionsProvider defaultTermsAndConditionsProvider; + chip::Optional<chip::app::TermsAndConditions> requiredTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(0b1111'1111'1111'1111, 1)); + err = defaultTermsAndConditionsProvider.Init(&defaultTermsAndConditionsStorageDelegate, requiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::Optional<chip::app::TermsAndConditions> outTermsAndConditions; + err = defaultTermsAndConditionsProvider.GetAcceptance(outTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_FALSE(outTermsAndConditions.HasValue()); +} + +TEST(DefaultTermsAndConditionsProvider, TestTermsAcceptedPersistsSuccess) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate testPersistentStorageDelegate; + chip::app::DefaultTermsAndConditionsStorageDelegate defaultTermsAndConditionsStorageDelegate; + err = defaultTermsAndConditionsStorageDelegate.Init(&testPersistentStorageDelegate); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::app::DefaultTermsAndConditionsProvider defaultTermsAndConditionsProvider; + chip::Optional<chip::app::TermsAndConditions> requiredTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(1, 1)); + err = defaultTermsAndConditionsProvider.Init(&defaultTermsAndConditionsStorageDelegate, requiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::Optional<chip::app::TermsAndConditions> newTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(1, 1)); + + err = defaultTermsAndConditionsProvider.SetAcceptance(newTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::Optional<chip::app::TermsAndConditions> outTermsAndConditions; + err = defaultTermsAndConditionsProvider.GetAcceptance(outTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outTermsAndConditions.Value().GetValue()); + EXPECT_EQ(1, outTermsAndConditions.Value().GetVersion()); + + err = defaultTermsAndConditionsProvider.CommitAcceptance(); + err = defaultTermsAndConditionsProvider.GetAcceptance(outTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outTermsAndConditions.Value().GetValue()); + EXPECT_EQ(1, outTermsAndConditions.Value().GetVersion()); + + chip::app::DefaultTermsAndConditionsProvider anotherTncProvider; + err = anotherTncProvider.Init(&defaultTermsAndConditionsStorageDelegate, requiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + err = anotherTncProvider.GetAcceptance(outTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outTermsAndConditions.Value().GetValue()); + EXPECT_EQ(1, outTermsAndConditions.Value().GetVersion()); +} + +TEST(DefaultTermsAndConditionsProvider, TestTermsRequiredGetRequirementsSuccess) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate testPersistentStorageDelegate; + chip::app::DefaultTermsAndConditionsStorageDelegate defaultTermsAndConditionsStorageDelegate; + err = defaultTermsAndConditionsStorageDelegate.Init(&testPersistentStorageDelegate); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::app::DefaultTermsAndConditionsProvider defaultTermsAndConditionsProvider; + chip::Optional<chip::app::TermsAndConditions> requiredTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(1, 1)); + err = defaultTermsAndConditionsProvider.Init(&defaultTermsAndConditionsStorageDelegate, requiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::Optional<chip::app::TermsAndConditions> outTermsAndConditions; + err = defaultTermsAndConditionsProvider.GetRequirements(outTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outTermsAndConditions.Value().GetValue()); + EXPECT_EQ(1, outTermsAndConditions.Value().GetVersion()); +} + +TEST(DefaultTermsAndConditionsProvider, TestSetAcceptanceGetAcceptanceSuccess) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate testPersistentStorageDelegate; + chip::app::DefaultTermsAndConditionsStorageDelegate defaultTermsAndConditionsStorageDelegate; + err = defaultTermsAndConditionsStorageDelegate.Init(&testPersistentStorageDelegate); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::app::DefaultTermsAndConditionsProvider defaultTermsAndConditionsProvider; + chip::Optional<chip::app::TermsAndConditions> requiredTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(1, 1)); + err = defaultTermsAndConditionsProvider.Init(&defaultTermsAndConditionsStorageDelegate, requiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::Optional<chip::app::TermsAndConditions> acceptedTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(1, 1)); + err = defaultTermsAndConditionsProvider.SetAcceptance(acceptedTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::Optional<chip::app::TermsAndConditions> outTermsAndConditions; + err = defaultTermsAndConditionsProvider.GetRequirements(outTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outTermsAndConditions.Value().GetValue()); + EXPECT_EQ(1, outTermsAndConditions.Value().GetVersion()); +} + +TEST(DefaultTermsAndConditionsProvider, TestRevertAcceptanceGetAcceptanceSuccess) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate testPersistentStorageDelegate; + chip::app::DefaultTermsAndConditionsStorageDelegate defaultTermsAndConditionsStorageDelegate; + err = defaultTermsAndConditionsStorageDelegate.Init(&testPersistentStorageDelegate); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::app::DefaultTermsAndConditionsProvider defaultTermsAndConditionsProvider; + chip::Optional<chip::app::TermsAndConditions> requiredTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(1, 1)); + err = defaultTermsAndConditionsProvider.Init(&defaultTermsAndConditionsStorageDelegate, requiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::Optional<chip::app::TermsAndConditions> acceptedTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(1, 1)); + err = defaultTermsAndConditionsProvider.SetAcceptance(acceptedTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::Optional<chip::app::TermsAndConditions> outTermsAndConditions; + err = defaultTermsAndConditionsProvider.GetRequirements(outTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outTermsAndConditions.Value().GetValue()); + EXPECT_EQ(1, outTermsAndConditions.Value().GetVersion()); + + err = defaultTermsAndConditionsProvider.RevertAcceptance(); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::Optional<chip::app::TermsAndConditions> outAcceptance2; + err = defaultTermsAndConditionsProvider.GetAcceptance(outAcceptance2); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_FALSE(outAcceptance2.HasValue()); +} + +TEST(DefaultTermsAndConditionsProvider, TestAcceptanceRequiredTermsMissingFailure) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate testPersistentStorageDelegate; + chip::app::DefaultTermsAndConditionsStorageDelegate defaultTermsAndConditionsStorageDelegate; + err = defaultTermsAndConditionsStorageDelegate.Init(&testPersistentStorageDelegate); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::app::DefaultTermsAndConditionsProvider defaultTermsAndConditionsProvider; + chip::Optional<chip::app::TermsAndConditions> requiredTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(1, 1)); + err = defaultTermsAndConditionsProvider.Init(&defaultTermsAndConditionsStorageDelegate, requiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::Optional<chip::app::TermsAndConditions> acceptedTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(1, 1)); + err = defaultTermsAndConditionsProvider.SetAcceptance(acceptedTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::Optional<chip::app::TermsAndConditions> outAcknowledgementTermsAndConditions; + err = defaultTermsAndConditionsProvider.GetAcceptance(outAcknowledgementTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outAcknowledgementTermsAndConditions.Value().GetValue()); + EXPECT_EQ(1, outAcknowledgementTermsAndConditions.Value().GetVersion()); + + err = defaultTermsAndConditionsProvider.RevertAcceptance(); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::Optional<chip::app::TermsAndConditions> outRequiredTermsAndConditions; + err = defaultTermsAndConditionsProvider.GetRequirements(outRequiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outRequiredTermsAndConditions.Value().GetValue()); + EXPECT_EQ(1, outRequiredTermsAndConditions.Value().GetVersion()); +} + +TEST(DefaultTermsAndConditionsProvider, TestAcceptanceCommitCheckSetRevertCheckExpectCommitValue) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate testPersistentStorageDelegate; + chip::app::DefaultTermsAndConditionsStorageDelegate defaultTermsAndConditionsStorageDelegate; + err = defaultTermsAndConditionsStorageDelegate.Init(&testPersistentStorageDelegate); + EXPECT_EQ(CHIP_NO_ERROR, err); + + // Initialize unit under test + chip::app::DefaultTermsAndConditionsProvider defaultTermsAndConditionsProvider; + chip::Optional<chip::app::TermsAndConditions> requiredTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(1, 1)); + err = defaultTermsAndConditionsProvider.Init(&defaultTermsAndConditionsStorageDelegate, requiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + // Set acceptance + chip::Optional<chip::app::TermsAndConditions> acceptedTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(0b1, 1)); + err = defaultTermsAndConditionsProvider.SetAcceptance(acceptedTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + // Commit value + err = defaultTermsAndConditionsProvider.CommitAcceptance(); + EXPECT_EQ(CHIP_NO_ERROR, err); + + // Check commit value + chip::Optional<chip::app::TermsAndConditions> outTermsAndConditions; + err = defaultTermsAndConditionsProvider.GetAcceptance(outTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_TRUE(outTermsAndConditions.HasValue()); + EXPECT_EQ(outTermsAndConditions.Value().GetValue(), acceptedTermsAndConditions.Value().GetValue()); + EXPECT_EQ(outTermsAndConditions.Value().GetVersion(), acceptedTermsAndConditions.Value().GetVersion()); + + // Set updated value + chip::Optional<chip::app::TermsAndConditions> updatedTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(0b11, 2)); + err = defaultTermsAndConditionsProvider.SetAcceptance(updatedTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + // Check updated value + err = defaultTermsAndConditionsProvider.GetAcceptance(outTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_TRUE(outTermsAndConditions.HasValue()); + EXPECT_EQ(outTermsAndConditions.Value().GetValue(), updatedTermsAndConditions.Value().GetValue()); + EXPECT_EQ(outTermsAndConditions.Value().GetVersion(), updatedTermsAndConditions.Value().GetVersion()); + + // Revert updated value + err = defaultTermsAndConditionsProvider.RevertAcceptance(); + EXPECT_EQ(CHIP_NO_ERROR, err); + + // Check committed value + err = defaultTermsAndConditionsProvider.GetAcceptance(outTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_TRUE(outTermsAndConditions.HasValue()); + EXPECT_EQ(outTermsAndConditions.Value().GetValue(), acceptedTermsAndConditions.Value().GetValue()); + EXPECT_EQ(outTermsAndConditions.Value().GetVersion(), acceptedTermsAndConditions.Value().GetVersion()); +} + +TEST(DefaultTermsAndConditionsProvider, TestRevertAcceptanceWhileMissing) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate testPersistentStorageDelegate; + chip::app::DefaultTermsAndConditionsStorageDelegate defaultTermsAndConditionsStorageDelegate; + chip::app::DefaultTermsAndConditionsProvider defaultTermsAndConditionsProvider; + + chip::Optional<chip::app::TermsAndConditions> requiredTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(1, 1)); + + chip::Optional<chip::app::TermsAndConditions> outTermsAndConditions; + + err = defaultTermsAndConditionsStorageDelegate.Init(&testPersistentStorageDelegate); + EXPECT_EQ(CHIP_NO_ERROR, err); + + // Initialize unit under test [No conditions previously accepted] + err = defaultTermsAndConditionsProvider.Init(&defaultTermsAndConditionsStorageDelegate, requiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + // [Fail-safe started] No conditions set during the fail-safe. No commit. + err = defaultTermsAndConditionsProvider.GetAcceptance(outTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_FALSE(outTermsAndConditions.HasValue()); + + // [Fail-safe expires] Revert is called. + err = defaultTermsAndConditionsProvider.RevertAcceptance(); + EXPECT_EQ(CHIP_NO_ERROR, err); + + // [New fail safe started (to retry the commissioning operations)] Confirm acceptance returns previous values (empty) + err = defaultTermsAndConditionsProvider.GetAcceptance(outTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_FALSE(outTermsAndConditions.HasValue()); +} + +TEST(DefaultTermsAndConditionsProvider, TestRevertAcceptanceWhenPreviouslyAccepted) +{ + CHIP_ERROR err; + + // Initialize unit under test [Conditions previously accepted] + chip::Optional<chip::app::TermsAndConditions> initialTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(1, 1)); + chip::Optional<chip::app::TermsAndConditions> requiredTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(0b11, 2)); + TestTermsAndConditionsStorageDelegate testTermsAndConditionsStorageDelegate(initialTermsAndConditions); + chip::app::DefaultTermsAndConditionsProvider defaultTermsAndConditionsProvider; + err = defaultTermsAndConditionsProvider.Init(&testTermsAndConditionsStorageDelegate, requiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + // [Fail-safe started] No conditions set during the fail-safe. No commit. + + // [Fail-safe expires] Revert is called. + err = defaultTermsAndConditionsProvider.RevertAcceptance(); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::Optional<chip::app::TermsAndConditions> outTermsAndConditions; + + // [New fail safe started (to retry the commissioning operations)] Confirm acceptance returns previous values (accepted) + err = defaultTermsAndConditionsProvider.GetAcceptance(outTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_TRUE(outTermsAndConditions.HasValue()); + EXPECT_EQ(outTermsAndConditions.Value().GetValue(), 1); + EXPECT_EQ(outTermsAndConditions.Value().GetVersion(), 1); +} + +TEST(DefaultTermsAndConditionsProvider, TestRevertAcceptanceWhenPreviouslyAcceptedThenUpdatedUnderFailsafe) +{ + CHIP_ERROR err; + + // Initialize unit under test dependency + chip::Optional<chip::app::TermsAndConditions> initiallyAcceptedTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(1, 1)); + TestTermsAndConditionsStorageDelegate testTermsAndConditionsStorageDelegate(initiallyAcceptedTermsAndConditions); + + // Initialize unit under test [Conditions previously accepted] + chip::Optional<chip::app::TermsAndConditions> requiredTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(0b11, 2)); + chip::app::DefaultTermsAndConditionsProvider defaultTermsAndConditionsProvider; + err = defaultTermsAndConditionsProvider.Init(&testTermsAndConditionsStorageDelegate, requiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + // [Fail-safe started] Acceptance updated. + chip::Optional<chip::app::TermsAndConditions> updatedAcceptedTermsAndConditions = + chip::Optional<chip::app::TermsAndConditions>(chip::app::TermsAndConditions(0b111, 3)); + err = defaultTermsAndConditionsProvider.SetAcceptance(updatedAcceptedTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + + // [Fail-safe expires] Revert is called. + err = defaultTermsAndConditionsProvider.RevertAcceptance(); + EXPECT_EQ(CHIP_NO_ERROR, err); + + chip::Optional<chip::app::TermsAndConditions> outTermsAndConditions; + + // [New fail safe started (to retry the commissioning operations)] Confirm acceptance returns previous values (accepted) + err = defaultTermsAndConditionsProvider.GetAcceptance(outTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_TRUE(outTermsAndConditions.HasValue()); + EXPECT_EQ(outTermsAndConditions.Value().GetValue(), initiallyAcceptedTermsAndConditions.Value().GetValue()); + EXPECT_EQ(outTermsAndConditions.Value().GetVersion(), initiallyAcceptedTermsAndConditions.Value().GetVersion()); +} diff --git a/src/app/tests/suites/TestUserLabelClusterConstraints.yaml b/src/app/tests/suites/TestUserLabelClusterConstraints.yaml index 4074def78d82d1..935fe88c2b662c 100644 --- a/src/app/tests/suites/TestUserLabelClusterConstraints.yaml +++ b/src/app/tests/suites/TestUserLabelClusterConstraints.yaml @@ -55,3 +55,35 @@ tests: ] response: error: CONSTRAINT_ERROR + + - label: "Attempt to write a large label list" + command: "writeAttribute" + attribute: "LabelList" + arguments: + value: [ + # Example repeated user labels to blow up the maximum allowed + { Label: "roomName", Value: "master bedroom 1" }, + { Label: "orientation", Value: "east" }, + { Label: "floor", Value: "2" }, + { Label: "roomType", Value: "bedroom" }, + { Label: "someKey5", Value: "someVal5" }, + { Label: "someKey6", Value: "someVal6" }, + { Label: "someKey7", Value: "someVal7" }, + { Label: "someKey8", Value: "someVal8" }, + { Label: "someKey9", Value: "someVal9" }, + { Label: "someKey10", Value: "someVal10" }, + { Label: "someKey11", Value: "someVal11" }, + { Label: "someKey12", Value: "someVal12" }, + { Label: "someKey13", Value: "someVal13" }, + { Label: "someKey14", Value: "someVal14" }, + { Label: "someKey15", Value: "someVal15" }, + { Label: "someKey16", Value: "someVal16" }, + { Label: "someKey17", Value: "someVal17" }, + { Label: "someKey18", Value: "someVal18" }, + { Label: "someKey19", Value: "someVal19" }, + { Label: "someKey20", Value: "someVal20" }, + ] + response: + # When the cluster runs out of capacity to store these entries, + # we expect a FAILURE get returned. + error: FAILURE diff --git a/src/app/zap-templates/zcl/data-model/chip/general-diagnostics-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/general-diagnostics-cluster.xml index c3bae609c66a21..ac628ffcede887 100644 --- a/src/app/zap-templates/zcl/data-model/chip/general-diagnostics-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/general-diagnostics-cluster.xml @@ -151,7 +151,7 @@ limitations under the License. <mandatoryConform/> </command> - <command source="client" code="0x03" name="PayloadTestRequest" response="PayloadTestResponse" optional="true" apiMaturity="provisional"> + <command source="client" code="0x03" name="PayloadTestRequest" response="PayloadTestResponse" optional="true"> <description>Request a variable length payload response.</description> <arg name="EnableKey" type="octet_string" length="16"/> <arg name="Value" type="int8u"/> @@ -159,9 +159,10 @@ limitations under the License. <mandatoryConform> <feature name="DMTEST"/> </mandatoryConform> + <access op="invoke" role="manage"/> </command> - <command source="server" code="0x04" name="PayloadTestResponse" optional="true" apiMaturity="provisional"> + <command source="server" code="0x04" name="PayloadTestResponse" optional="true"> <description>Response for the PayloadTestRequest command.</description> <arg name="Payload" type="octet_string" max="2048" optional="false"/> <mandatoryConform> diff --git a/src/app/zap-templates/zcl/data-model/chip/scene.xml b/src/app/zap-templates/zcl/data-model/chip/scene.xml index ceea35e3759e69..fdd4a65c9cb29c 100644 --- a/src/app/zap-templates/zcl/data-model/chip/scene.xml +++ b/src/app/zap-templates/zcl/data-model/chip/scene.xml @@ -169,6 +169,7 @@ limitations under the License. <arg name="GroupIdentifierTo" type="group_id"/> <arg name="SceneIdentifierTo" type="int8u"/> <optionalConform/> + <access op="invoke" role="manage"/> </command> <command source="server" code="0x00" name="AddSceneResponse" optional="false" disableDefaultResponse="true"> diff --git a/src/app/zap-templates/zcl/zcl-with-test-extensions.json b/src/app/zap-templates/zcl/zcl-with-test-extensions.json index 0912be1df2db37..14179bb5566bfc 100644 --- a/src/app/zap-templates/zcl/zcl-with-test-extensions.json +++ b/src/app/zap-templates/zcl/zcl-with-test-extensions.json @@ -294,7 +294,14 @@ "ClientsSupportedPerFabric", "MaximumCheckInBackOff" ], - "Occupancy Sensing": ["HoldTimeLimits", "HoldTime", "FeatureMap"], + "Occupancy Sensing": [ + "HoldTimeLimits", + "HoldTime", + "PIROccupiedToUnoccupiedDelay", + "UltrasonicOccupiedToUnoccupiedDelay", + "PhysicalContactOccupiedToUnoccupiedDelay", + "FeatureMap" + ], "Operational Credentials": [ "SupportedFabrics", "CommissionedFabrics", diff --git a/src/app/zap-templates/zcl/zcl.json b/src/app/zap-templates/zcl/zcl.json index 3a62c4c84ca6eb..728d3acdad1f06 100644 --- a/src/app/zap-templates/zcl/zcl.json +++ b/src/app/zap-templates/zcl/zcl.json @@ -288,7 +288,14 @@ "ClientsSupportedPerFabric", "MaximumCheckInBackOff" ], - "Occupancy Sensing": ["HoldTimeLimits", "HoldTime", "FeatureMap"], + "Occupancy Sensing": [ + "HoldTimeLimits", + "HoldTime", + "PIROccupiedToUnoccupiedDelay", + "UltrasonicOccupiedToUnoccupiedDelay", + "PhysicalContactOccupiedToUnoccupiedDelay", + "FeatureMap" + ], "Operational Credentials": [ "SupportedFabrics", "CommissionedFabrics", diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index 31da395b05cd31..aa2707931f36d6 100644 --- a/src/controller/data_model/controller-clusters.matter +++ b/src/controller/data_model/controller-clusters.matter @@ -1990,7 +1990,7 @@ cluster GeneralDiagnostics = 51 { /** Take a snapshot of system time and epoch time. */ command TimeSnapshot(): TimeSnapshotResponse = 1; /** Request a variable length payload response. */ - command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; + command access(invoke: manage) PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } /** The Software 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. */ @@ -4272,7 +4272,7 @@ provisional cluster ScenesManagement = 98 { /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */ fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6; /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */ - fabric command CopyScene(CopySceneRequest): CopySceneResponse = 64; + fabric command access(invoke: manage) CopyScene(CopySceneRequest): CopySceneResponse = 64; } /** Attributes and commands for monitoring HEPA filters in a device */ diff --git a/src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.cpp b/src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.cpp index 15804a61a3ead2..7b3f0094c7249e 100644 --- a/src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.cpp +++ b/src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.cpp @@ -50,12 +50,23 @@ CHIP_ERROR TestDACRevocationDelegateImpl::SetDeviceAttestationRevocationSetPath( return CHIP_NO_ERROR; } +CHIP_ERROR TestDACRevocationDelegateImpl::SetDeviceAttestationRevocationData(const std::string & jsonData) +{ + mRevocationData = jsonData; + return CHIP_NO_ERROR; +} + void TestDACRevocationDelegateImpl::ClearDeviceAttestationRevocationSetPath() { // clear the string_view mDeviceAttestationRevocationSetPath = mDeviceAttestationRevocationSetPath.substr(0, 0); } +void TestDACRevocationDelegateImpl::ClearDeviceAttestationRevocationData() +{ + mRevocationData.clear(); +} + // Check if issuer and AKID matches with the crl signer OR crl signer delegator's subject and SKID bool TestDACRevocationDelegateImpl::CrossValidateCert(const Json::Value & revokedSet, const std::string & akidHexStr, const std::string & issuerNameBase64Str) @@ -115,26 +126,42 @@ bool TestDACRevocationDelegateImpl::CrossValidateCert(const Json::Value & revoke bool TestDACRevocationDelegateImpl::IsEntryInRevocationSet(const std::string & akidHexStr, const std::string & issuerNameBase64Str, const std::string & serialNumberHexStr) { - std::ifstream file(mDeviceAttestationRevocationSetPath.c_str()); - if (!file.is_open()) - { - ChipLogError(NotSpecified, "Failed to open file: %s", mDeviceAttestationRevocationSetPath.c_str()); - return false; - } - - // Parse the JSON data incrementally - Json::CharReaderBuilder readerBuilder; Json::Value jsonData; - std::string errs; - bool parsingSuccessful = Json::parseFromStream(readerBuilder, file, &jsonData, &errs); + // Try direct data first, then fall back to file + if (!mRevocationData.empty()) + { + std::string errs; + std::istringstream jsonStream(!mRevocationData.empty() ? mRevocationData : "[]"); + if (!Json::parseFromStream(Json::CharReaderBuilder(), jsonStream, &jsonData, &errs)) + { + ChipLogError(NotSpecified, "Failed to parse JSON data: %s", errs.c_str()); + return false; + } + } + else if (!mDeviceAttestationRevocationSetPath.empty()) + { + std::string errs; + std::ifstream file(mDeviceAttestationRevocationSetPath.c_str()); + if (!file.is_open()) + { + ChipLogError(NotSpecified, "Failed to open file: %s", mDeviceAttestationRevocationSetPath.c_str()); + return false; + } - // Close the file as it's no longer needed - file.close(); + bool parsingSuccessful = Json::parseFromStream(Json::CharReaderBuilder(), file, &jsonData, &errs); + file.close(); - if (!parsingSuccessful) + if (!parsingSuccessful) + { + ChipLogError(NotSpecified, "Failed to parse JSON from file: %s", errs.c_str()); + return false; + } + } + else { - ChipLogError(NotSpecified, "Failed to parse JSON: %s", errs.c_str()); + ChipLogDetail(NotSpecified, "No revocation data available"); + // No revocation data available return false; } @@ -278,7 +305,7 @@ void TestDACRevocationDelegateImpl::CheckForRevokedDACChain( { AttestationVerificationResult attestationError = AttestationVerificationResult::kSuccess; - if (mDeviceAttestationRevocationSetPath.empty()) + if (mDeviceAttestationRevocationSetPath.empty() && mRevocationData.empty()) { onCompletion->mCall(onCompletion->mContext, info, attestationError); return; diff --git a/src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.h b/src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.h index cea143603c341d..fc93ce4487e83a 100644 --- a/src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.h +++ b/src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.h @@ -52,6 +52,10 @@ class TestDACRevocationDelegateImpl : public DeviceAttestationRevocationDelegate // This can be used to skip the revocation check void ClearDeviceAttestationRevocationSetPath(); + // Set JSON data directly for unit test purposes. + CHIP_ERROR SetDeviceAttestationRevocationData(const std::string & jsonData); + void ClearDeviceAttestationRevocationData(); + private: enum class KeyIdType : uint8_t { @@ -83,6 +87,7 @@ class TestDACRevocationDelegateImpl : public DeviceAttestationRevocationDelegate bool IsCertificateRevoked(const ByteSpan & certDer); std::string mDeviceAttestationRevocationSetPath; + std::string mRevocationData; // Stores direct JSON data }; } // namespace Credentials diff --git a/src/credentials/tests/TestDeviceAttestationCredentials.cpp b/src/credentials/tests/TestDeviceAttestationCredentials.cpp index 8480fff4daaae4..f5bee29df50533 100644 --- a/src/credentials/tests/TestDeviceAttestationCredentials.cpp +++ b/src/credentials/tests/TestDeviceAttestationCredentials.cpp @@ -417,17 +417,6 @@ TEST_F(TestDeviceAttestationCredentials, TestAttestationTrustStore) } } -static void WriteTestRevokedData(const char * jsonData, const char * fileName) -{ - // TODO: Add option to load test data from the test without using file. #34588 - - // write data to /tmp/sample_revoked_set.json using fstream APIs - std::ofstream file; - file.open(fileName, std::ofstream::out | std::ofstream::trunc); - file << jsonData; - file.close(); -} - TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) { uint8_t attestationElementsTestVector[] = { 0 }; @@ -456,16 +445,14 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) TestDACRevocationDelegateImpl revocationDelegateImpl; - // Test without revocation set + // Test without revocation data revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); - const char * tmpJsonFile = "/tmp/sample_revoked_set.json"; - revocationDelegateImpl.SetDeviceAttestationRevocationSetPath(tmpJsonFile); - // Test empty json - WriteTestRevokedData("", tmpJsonFile); + revocationDelegateImpl.SetDeviceAttestationRevocationData(""); revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); + revocationDelegateImpl.ClearDeviceAttestationRevocationData(); EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); // Test DAC is revoked, crl signer is PAI itself @@ -478,8 +465,9 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) "revoked_serial_numbers": ["0C694F7F866067B2"] }] )"; - WriteTestRevokedData(jsonData, tmpJsonFile); + revocationDelegateImpl.SetDeviceAttestationRevocationData(jsonData); revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); + revocationDelegateImpl.ClearDeviceAttestationRevocationData(); EXPECT_EQ(attestationResult, AttestationVerificationResult::kDacRevoked); // Test PAI is revoked, crl signer is PAA itself @@ -492,8 +480,9 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) "revoked_serial_numbers": ["3E6CE6509AD840CD"] }] )"; - WriteTestRevokedData(jsonData, tmpJsonFile); + revocationDelegateImpl.SetDeviceAttestationRevocationData(jsonData); revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); + revocationDelegateImpl.ClearDeviceAttestationRevocationData(); EXPECT_EQ(attestationResult, AttestationVerificationResult::kPaiRevoked); // Test DAC and PAI both revoked, crl signers are PAI and PAA respectively @@ -513,7 +502,7 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) "revoked_serial_numbers": ["3E6CE6509AD840CD"] }] )"; - WriteTestRevokedData(jsonData, tmpJsonFile); + revocationDelegateImpl.SetDeviceAttestationRevocationData(jsonData); revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); EXPECT_EQ(attestationResult, AttestationVerificationResult::kPaiAndDacRevoked); @@ -523,6 +512,7 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) TestCerts::sTestCert_PAI_FFF2_8001_Cert, TestCerts::sTestCert_DAC_FFF2_8001_0008_Cert, ByteSpan(attestationNonceTestVector), static_cast<VendorId>(0xFFF2), 0x8001); revocationDelegateImpl.CheckForRevokedDACChain(FFF2_8001_info, &attestationInformationVerificationCallback); + revocationDelegateImpl.ClearDeviceAttestationRevocationData(); EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); // Test issuer does not match @@ -536,8 +526,9 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) "revoked_serial_numbers": ["0C694F7F866067B2"] }] )"; - WriteTestRevokedData(jsonData, tmpJsonFile); + revocationDelegateImpl.SetDeviceAttestationRevocationData(jsonData); revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); + revocationDelegateImpl.ClearDeviceAttestationRevocationData(); EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); // Test subject key ID does not match @@ -551,8 +542,9 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) "revoked_serial_numbers": ["0C694F7F866067B2"] }] )"; - WriteTestRevokedData(jsonData, tmpJsonFile); + revocationDelegateImpl.SetDeviceAttestationRevocationData(jsonData); revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); + revocationDelegateImpl.ClearDeviceAttestationRevocationData(); EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); // Test serial number does not match @@ -566,8 +558,9 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) "revoked_serial_numbers": ["3E6CE6509AD840CD1", "BC694F7F866067B1"] }] )"; - WriteTestRevokedData(jsonData, tmpJsonFile); + revocationDelegateImpl.SetDeviceAttestationRevocationData(jsonData); revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); + revocationDelegateImpl.ClearDeviceAttestationRevocationData(); EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); // Test starting serial number bytes match but not all, @@ -581,8 +574,9 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) "revoked_serial_numbers": ["0C694F7F866067B21234"] }] )"; - WriteTestRevokedData(jsonData, tmpJsonFile); + revocationDelegateImpl.SetDeviceAttestationRevocationData(jsonData); revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); + revocationDelegateImpl.ClearDeviceAttestationRevocationData(); EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); // Test DAC is revoked, and crl signer delegator is present @@ -597,8 +591,9 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) "revoked_serial_numbers": ["0C694F7F866067B2"] }] )"; - WriteTestRevokedData(jsonData, tmpJsonFile); + revocationDelegateImpl.SetDeviceAttestationRevocationData(jsonData); revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); + revocationDelegateImpl.ClearDeviceAttestationRevocationData(); EXPECT_EQ(attestationResult, AttestationVerificationResult::kDacRevoked); // Test with invalid crl signer cert missing begin and end cert markers @@ -612,8 +607,9 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) }] )"; - WriteTestRevokedData(jsonData, tmpJsonFile); + revocationDelegateImpl.SetDeviceAttestationRevocationData(jsonData); revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); + revocationDelegateImpl.ClearDeviceAttestationRevocationData(); EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); // test with malformed crl signer certificate @@ -627,7 +623,8 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) }] )"; - WriteTestRevokedData(jsonData, tmpJsonFile); + revocationDelegateImpl.SetDeviceAttestationRevocationData(jsonData); revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); + revocationDelegateImpl.ClearDeviceAttestationRevocationData(); EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); } diff --git a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm index 996e41ff12cf2d..264a268e253163 100644 --- a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm +++ b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm @@ -871,13 +871,7 @@ - (void)invalidate // tear down the subscription. We will get no more callbacks from // the subscription after this point. std::lock_guard lock(self->_lock); - self->_currentReadClient = nullptr; - if (self->_currentSubscriptionCallback) { - delete self->_currentSubscriptionCallback; - } - self->_currentSubscriptionCallback = nullptr; - - [self _changeInternalState:MTRInternalDeviceStateUnsubscribed]; + [self _resetSubscription]; } errorHandler:nil]; @@ -938,8 +932,8 @@ - (void)_triggerResubscribeWithReason:(NSString *)reason nodeLikelyReachable:(BO } readClientToResubscribe->TriggerResubscribeIfScheduled(reason.UTF8String); } else if (_internalDeviceState == MTRInternalDeviceStateSubscribing && nodeLikelyReachable) { - // If we have reason to suspect that the node is now reachable and we haven’t established a - // CASE session yet, let’s consider it to be stalled and invalidate the pairing session. + // If we have reason to suspect that the node is now reachable and we haven't established a + // CASE session yet, let's consider it to be stalled and invalidate the pairing session. [self._concreteController asyncGetCommissionerOnMatterQueue:^(Controller::DeviceCommissioner * commissioner) { auto caseSessionMgr = commissioner->CASESessionMgr(); VerifyOrDie(caseSessionMgr != nullptr); @@ -1164,7 +1158,7 @@ - (void)_handleSubscriptionError:(NSError *)error [self _doHandleSubscriptionError:error]; } -- (void)_doHandleSubscriptionError:(NSError *)error +- (void)_doHandleSubscriptionError:(nullable NSError *)error { assertChipStackLockedByCurrentThread(); @@ -1305,7 +1299,13 @@ - (void)_handleResubscriptionNeededWithDelay:(NSNumber *)resubscriptionDelayMs // Change our state before going async. [self _changeState:MTRDeviceStateUnknown]; - [self _changeInternalState:MTRInternalDeviceStateResubscribing]; + + // If we have never had a subscription established, stay in the Subscribing + // state; don't transition to Resubscribing just because our attempt at + // subscribing failed. + if (HadSubscriptionEstablishedOnce(self->_internalDeviceState)) { + [self _changeInternalState:MTRInternalDeviceStateResubscribing]; + } dispatch_async(self.queue, ^{ [self _handleResubscriptionNeededWithDelayOnDeviceQueue:resubscriptionDelayMs]; @@ -2444,19 +2444,29 @@ - (void)_resetSubscriptionWithReasonString:(NSString *)reasonString MTR_LOG("%@ subscription reset disconnecting ReadClient and SubscriptionCallback", self); std::lock_guard lock(self->_lock); - self->_currentReadClient = nullptr; - if (self->_currentSubscriptionCallback) { - delete self->_currentSubscriptionCallback; - } - self->_currentSubscriptionCallback = nullptr; - [self _doHandleSubscriptionError:nil]; + [self _resetSubscription]; + // Use nil reset delay so that this keeps existing backoff timing [self _doHandleSubscriptionReset:nil]; } errorHandler:nil]; } +- (void)_resetSubscription +{ + assertChipStackLockedByCurrentThread(); + os_unfair_lock_assert_owner(&_lock); + + _currentReadClient = nullptr; + if (_currentSubscriptionCallback) { + delete _currentSubscriptionCallback; + _currentSubscriptionCallback = nullptr; + } + + [self _doHandleSubscriptionError:nil]; +} + #ifdef DEBUG - (void)unitTestResetSubscription { @@ -4322,11 +4332,31 @@ - (BOOL)_deviceHasActiveSubscription - (void)_deviceMayBeReachable { - MTR_LOG("%@ _deviceMayBeReachable called", self); + MTR_LOG("%@ _deviceMayBeReachable called, resetting subscription", self); // TODO: This should only be allowed for thread devices - [_deviceController asyncDispatchToMatterQueue:^{ - [self _triggerResubscribeWithReason:@"SPI client indicated the device may now be reachable" - nodeLikelyReachable:YES]; + [self._concreteController asyncGetCommissionerOnMatterQueue:^(Controller::DeviceCommissioner * commissioner) { + // Reset all of our subscription/session state and re-establish it all + // from the start. Reset our subscription first, before tearing + // down the session, so we don't have to worry about the + // notifications from the latter coming through async and + // complicating the situation. Unfortunately, we do not want to + // hold the lock when destroying the session, just in case it still + // ends up calling into us somehow, so we have to break the work up + // into two separate locked sections... + { + std::lock_guard lock(self->_lock); + [self _clearSubscriptionPoolWork]; + [self _resetSubscription]; + } + + auto caseSessionMgr = commissioner->CASESessionMgr(); + VerifyOrDie(caseSessionMgr != nullptr); + caseSessionMgr->ReleaseSession(commissioner->GetPeerScopedId(self->_nodeID.unsignedLongLongValue)); + + std::lock_guard lock(self->_lock); + // Use _ensureSubscriptionForExistingDelegates so that the subscriptions + // will go through the pool as needed, not necessarily happen immediately. + [self _ensureSubscriptionForExistingDelegates:@"SPI client indicated the device may now be reachable"]; } errorHandler:nil]; } diff --git a/src/darwin/Framework/CHIP/MTRError.h b/src/darwin/Framework/CHIP/MTRError.h index 428464dab983ef..cf359fac960979 100644 --- a/src/darwin/Framework/CHIP/MTRError.h +++ b/src/darwin/Framework/CHIP/MTRError.h @@ -35,7 +35,6 @@ MTR_EXTERN NSErrorDomain const MTRInteractionErrorDomain MTR_AVAILABLE(ios(16.1) * Errors reported by the server side of a Matter interaction via the normal * Matter error-reporting mechanisms use MTRInteractionErrorDomain instead. */ -// clang-format off typedef NS_ERROR_ENUM(MTRErrorDomain, MTRErrorCode){ /** * MTRErrorCodeGeneralError represents a generic Matter error with no @@ -61,7 +60,7 @@ typedef NS_ERROR_ENUM(MTRErrorDomain, MTRErrorCode){ * MTRErrorCodeFabricExists is returned when trying to commission a device * into a fabric when it's already part of that fabric. */ - MTRErrorCodeFabricExists = 11, + MTRErrorCodeFabricExists = 11, /** * MTRErrorCodeUnknownSchema means the schema for the given cluster/attribute, @@ -95,9 +94,25 @@ typedef NS_ERROR_ENUM(MTRErrorDomain, MTRErrorCode){ /** * The operation was cancelled. */ - MTRErrorCodeCancelled MTR_AVAILABLE(ios(17.6), macos(14.6), watchos(10.6), tvos(17.6))= 16, + MTRErrorCodeCancelled MTR_AVAILABLE(ios(17.6), macos(14.6), watchos(10.6), tvos(17.6)) = 16, + + /** + * Access to some resource was denied. + */ + MTRErrorCodeAccessDenied MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 17, + + /** + * A request was made to some entity, and that entity cannot handle the + * request right now, but might be able to at a different point in time. + */ + MTRErrorCodeBusy MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 18, + + /** + * Something was requested that could not be located. + */ + MTRErrorCodeNotFound MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 19, }; -// clang-format on +#define MTRMaxErrorCode MTRErrorCodeNotFound /** * MTRInteractionErrorDomain contains errors that represent a Matter @@ -109,38 +124,36 @@ typedef NS_ERROR_ENUM(MTRErrorDomain, MTRErrorCode){ * was reported. This key will be absent if there was no cluster-specific * status. */ -// clang-format off typedef NS_ERROR_ENUM(MTRInteractionErrorDomain, MTRInteractionErrorCode){ // These values come from the general status code table in the Matter // Interaction Model specification. - MTRInteractionErrorCodeFailure = 0x01, - MTRInteractionErrorCodeInvalidSubscription = 0x7d, - MTRInteractionErrorCodeUnsupportedAccess = 0x7e, - MTRInteractionErrorCodeUnsupportedEndpoint = 0x7f, - MTRInteractionErrorCodeInvalidAction = 0x80, - MTRInteractionErrorCodeUnsupportedCommand = 0x81, - MTRInteractionErrorCodeInvalidCommand = 0x85, - MTRInteractionErrorCodeUnsupportedAttribute = 0x86, - MTRInteractionErrorCodeConstraintError = 0x87, - MTRInteractionErrorCodeUnsupportedWrite = 0x88, - MTRInteractionErrorCodeResourceExhausted = 0x89, - MTRInteractionErrorCodeNotFound = 0x8b, - MTRInteractionErrorCodeUnreportableAttribute = 0x8c, - MTRInteractionErrorCodeInvalidDataType = 0x8d, - MTRInteractionErrorCodeUnsupportedRead = 0x8f, - MTRInteractionErrorCodeDataVersionMismatch = 0x92, - MTRInteractionErrorCodeTimeout = 0x94, - MTRInteractionErrorCodeBusy = 0x9c, - MTRInteractionErrorCodeUnsupportedCluster = 0xc3, - MTRInteractionErrorCodeNoUpstreamSubscription = 0xc5, - MTRInteractionErrorCodeNeedsTimedInteraction = 0xc6, - MTRInteractionErrorCodeUnsupportedEvent = 0xc7, - MTRInteractionErrorCodePathsExhausted = 0xc8, - MTRInteractionErrorCodeTimedRequestMismatch = 0xc9, - MTRInteractionErrorCodeFailsafeRequired = 0xca, - MTRInteractionErrorCodeInvalidInState MTR_AVAILABLE(ios(17.6), macos(14.6), watchos(10.6), tvos(17.6))= 0xcb, - MTRInteractionErrorCodeNoCommandResponse MTR_AVAILABLE(ios(17.6), macos(14.6), watchos(10.6), tvos(17.6))= 0xcc, + MTRInteractionErrorCodeFailure = 0x01, + MTRInteractionErrorCodeInvalidSubscription = 0x7d, + MTRInteractionErrorCodeUnsupportedAccess = 0x7e, + MTRInteractionErrorCodeUnsupportedEndpoint = 0x7f, + MTRInteractionErrorCodeInvalidAction = 0x80, + MTRInteractionErrorCodeUnsupportedCommand = 0x81, + MTRInteractionErrorCodeInvalidCommand = 0x85, + MTRInteractionErrorCodeUnsupportedAttribute = 0x86, + MTRInteractionErrorCodeConstraintError = 0x87, + MTRInteractionErrorCodeUnsupportedWrite = 0x88, + MTRInteractionErrorCodeResourceExhausted = 0x89, + MTRInteractionErrorCodeNotFound = 0x8b, + MTRInteractionErrorCodeUnreportableAttribute = 0x8c, + MTRInteractionErrorCodeInvalidDataType = 0x8d, + MTRInteractionErrorCodeUnsupportedRead = 0x8f, + MTRInteractionErrorCodeDataVersionMismatch = 0x92, + MTRInteractionErrorCodeTimeout = 0x94, + MTRInteractionErrorCodeBusy = 0x9c, + MTRInteractionErrorCodeUnsupportedCluster = 0xc3, + MTRInteractionErrorCodeNoUpstreamSubscription = 0xc5, + MTRInteractionErrorCodeNeedsTimedInteraction = 0xc6, + MTRInteractionErrorCodeUnsupportedEvent = 0xc7, + MTRInteractionErrorCodePathsExhausted = 0xc8, + MTRInteractionErrorCodeTimedRequestMismatch = 0xc9, + MTRInteractionErrorCodeFailsafeRequired = 0xca, + MTRInteractionErrorCodeInvalidInState MTR_AVAILABLE(ios(17.6), macos(14.6), watchos(10.6), tvos(17.6)) = 0xcb, + MTRInteractionErrorCodeNoCommandResponse MTR_AVAILABLE(ios(17.6), macos(14.6), watchos(10.6), tvos(17.6)) = 0xcc, }; -// clang-format on NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRError.mm b/src/darwin/Framework/CHIP/MTRError.mm index e268ab49e32cc9..e7f3acb90ad5ba 100644 --- a/src/darwin/Framework/CHIP/MTRError.mm +++ b/src/darwin/Framework/CHIP/MTRError.mm @@ -107,6 +107,10 @@ + (NSError *)errorForCHIPErrorCode:(CHIP_ERROR)errorCode logContext:(id)contextT code = MTRErrorCodeFabricExists; description = NSLocalizedString(@"The device is already a member of this fabric.", nil); break; + case CHIP_ERROR_SCHEMA_MISMATCH.AsInteger(): + code = MTRErrorCodeSchemaMismatch; + description = NSLocalizedString(@"Data does not match expected schema.", nil); + break; case CHIP_ERROR_DECODE_FAILED.AsInteger(): code = MTRErrorCodeTLVDecodeFailed; description = NSLocalizedString(@"TLV decoding failed.", nil); @@ -122,6 +126,18 @@ + (NSError *)errorForCHIPErrorCode:(CHIP_ERROR)errorCode logContext:(id)contextT code = MTRErrorCodeCancelled; description = NSLocalizedString(@"The operation was cancelled.", nil); break; + case CHIP_ERROR_ACCESS_DENIED.AsInteger(): + code = MTRErrorCodeAccessDenied; + description = NSLocalizedString(@"Access denied.", nil); + break; + case CHIP_ERROR_BUSY.AsInteger(): + code = MTRErrorCodeBusy; + description = NSLocalizedString(@"Operation cannot be completed at this time: resource busy.", nil); + break; + case CHIP_ERROR_NOT_FOUND.AsInteger(): + code = MTRErrorCodeNotFound; + description = NSLocalizedString(@"Requested resource was not found.", nil); + break; default: code = MTRErrorCodeGeneralError; description = [NSString stringWithFormat:NSLocalizedString(@"General error: %u", nil), errorCode.AsInteger()]; @@ -141,6 +157,11 @@ + (NSError *)errorForCHIPErrorCode:(CHIP_ERROR)errorCode logContext:(id)contextT return error; } ++ (NSError *)errorForCHIPIntegerCode:(uint32_t)errorCode +{ + return [MTRError errorForCHIPErrorCode:chip::ChipError(errorCode)]; +} + + (NSError *)errorForIMStatus:(const chip::app::StatusIB &)status { if (status.IsSuccess()) { @@ -303,6 +324,9 @@ + (CHIP_ERROR)errorToCHIPErrorCode:(NSError * _Nullable)error case MTRErrorCodeFabricExists: code = CHIP_ERROR_FABRIC_EXISTS.AsInteger(); break; + case MTRErrorCodeSchemaMismatch: + code = CHIP_ERROR_SCHEMA_MISMATCH.AsInteger(); + break; case MTRErrorCodeTLVDecodeFailed: code = CHIP_ERROR_DECODE_FAILED.AsInteger(); break; @@ -312,6 +336,15 @@ + (CHIP_ERROR)errorToCHIPErrorCode:(NSError * _Nullable)error case MTRErrorCodeCancelled: code = CHIP_ERROR_CANCELLED.AsInteger(); break; + case MTRErrorCodeAccessDenied: + code = CHIP_ERROR_ACCESS_DENIED.AsInteger(); + break; + case MTRErrorCodeBusy: + code = CHIP_ERROR_BUSY.AsInteger(); + break; + case MTRErrorCodeNotFound: + code = CHIP_ERROR_NOT_FOUND.AsInteger(); + break; case MTRErrorCodeGeneralError: { id userInfoErrorCode = error.userInfo[@"errorCode"]; if ([userInfoErrorCode isKindOfClass:NSNumber.class]) { @@ -328,6 +361,11 @@ + (CHIP_ERROR)errorToCHIPErrorCode:(NSError * _Nullable)error return chip::ChipError(code); } ++ (uint32_t)errorToCHIPIntegerCode:(NSError * _Nullable)error +{ + return [self errorToCHIPErrorCode:error].AsInteger(); +} + @end @implementation MTRErrorHolder diff --git a/src/darwin/Framework/CHIP/MTRError_Internal.h b/src/darwin/Framework/CHIP/MTRError_Internal.h index c79cc17d95f198..5bb61116430958 100644 --- a/src/darwin/Framework/CHIP/MTRError_Internal.h +++ b/src/darwin/Framework/CHIP/MTRError_Internal.h @@ -16,9 +16,9 @@ */ #import <Foundation/Foundation.h> -#import <Matter/MTRError.h> #import "MTRDefines_Internal.h" +#import "MTRError_Testable.h" #include <app/MessageDef/StatusIB.h> #include <lib/core/CHIPError.h> @@ -27,8 +27,7 @@ NS_ASSUME_NONNULL_BEGIN MTR_DIRECT_MEMBERS -@interface MTRError : NSObject -+ (NSError *)errorWithCode:(MTRErrorCode)code; +@interface MTRError () + (NSError * _Nullable)errorForCHIPErrorCode:(CHIP_ERROR)errorCode; + (NSError * _Nullable)errorForCHIPErrorCode:(CHIP_ERROR)errorCode logContext:(id _Nullable)contextToLog; + (NSError * _Nullable)errorForIMStatus:(const chip::app::StatusIB &)status; diff --git a/src/darwin/Framework/CHIP/MTRError_Testable.h b/src/darwin/Framework/CHIP/MTRError_Testable.h new file mode 100644 index 00000000000000..a4456c6097ee01 --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRError_Testable.h @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> +#import <Matter/MTRError.h> + +#import "MTRDefines_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +MTR_TESTABLE +@interface MTRError : NSObject + ++ (NSError *)errorWithCode:(MTRErrorCode)code; + +// For tests only, since we can't use CHIP_ERROR from there. The "code"s used +// here are integer representations of CHIP_ERROR. Otherwise these functions +// are just like errorForCHIPErrorCode and errorToCHIPErrorCode. ++ (NSError *)errorForCHIPIntegerCode:(uint32_t)code; ++ (uint32_t)errorToCHIPIntegerCode:(NSError * _Nullable)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/templates/availability.yaml b/src/darwin/Framework/CHIP/templates/availability.yaml index 3885ae5d988a1d..5267131218300a 100644 --- a/src/darwin/Framework/CHIP/templates/availability.yaml +++ b/src/darwin/Framework/CHIP/templates/availability.yaml @@ -9874,44 +9874,6 @@ - RequiredTCNotAccepted - TCAcknowledgementsNotReceived - TCMinVersionNotMet - RVCCleanMode: - # Not clear whether these will stay in the XML - ModeTag: - - Auto - - Quick - - Quiet - - LowNoise - - LowEnergy - - Min - - Max - - Night - - Day - - Vacation - RVCOperationalState: - # Not clear whether these will stay in the XML - ErrorStateEnum: - - NoError - - UnableToStartOrResume - - UnableToCompleteOperation - - CommandInvalidInState - OperationalStateEnum: - - Stopped - - Running - - Paused - - Error - RVCRunMode: - # Not clear whether these will stay in the XML - ModeTag: - - Auto - - Quick - - Quiet - - LowNoise - - LowEnergy - - Vacation - - Min - - Max - - Night - - Day bitmaps: AccessControl: # Targeting 1.4 @@ -10370,11 +10332,24 @@ - NumberOfRinsesEnum LaundryWasherMode: - ModeTag + OvenCavityOperationalState: + - ErrorStateEnum + - OperationalStateEnum RefrigeratorAndTemperatureControlledCabinetMode: - ModeTag enum values: DishwasherMode: ModeTag: + - Auto + - Quick + - Quiet + - LowNoise + - LowEnergy + - Vacation + - Min + - Max + - Night + - Day - Normal - Heavy - Light @@ -10400,16 +10375,57 @@ - Max LaundryWasherMode: ModeTag: + - Auto + - Quick + - Quiet + - LowNoise + - LowEnergy + - Vacation + - Min + - Max + - Night + - Day - Normal - Delicate - Heavy - Whites MicrowaveOvenMode: ModeTag: + - Auto + - Quick + - Quiet + - LowNoise + - LowEnergy + - Vacation + - Min + - Max + - Night + - Day - Normal - Defrost + OvenCavityOperationalState: + ErrorStateEnum: + - NoError + - UnableToStartOrResume + - UnableToCompleteOperation + - CommandInvalidInState + OperationalStateEnum: + - Stopped + - Running + - Paused + - Error OvenMode: ModeTag: + - Auto + - Quick + - Quiet + - LowNoise + - LowEnergy + - Vacation + - Min + - Max + - Night + - Day - Bake - Convection - Grill @@ -10422,10 +10438,53 @@ - Steam RefrigeratorAndTemperatureControlledCabinetMode: ModeTag: + - Auto + - Quick + - Quiet + - LowNoise + - LowEnergy + - Vacation + - Min + - Max + - Night + - Day - RapidCool - RapidFreeze + RVCCleanMode: + ModeTag: + - Auto + - Quick + - Quiet + - LowNoise + - LowEnergy + - Min + - Max + - Night + - Day + - Vacation + RVCOperationalState: + ErrorStateEnum: + - NoError + - UnableToStartOrResume + - UnableToCompleteOperation + - CommandInvalidInState + OperationalStateEnum: + - Stopped + - Running + - Paused + - Error RVCRunMode: ModeTag: + - Auto + - Quick + - Quiet + - LowNoise + - LowEnergy + - Vacation + - Min + - Max + - Night + - Day - Mapping bitmaps: DishwasherAlarm: @@ -10503,77 +10562,6 @@ SetCookingParameters: # wattSettingIndex is provisional because WATTS is provisional in Matter 1.4 - wattSettingIndex - enums: - OvenCavityOperationalState: - # Not clear whether these will stay in the XML - - ErrorStateEnum - - OperationalStateEnum - enum values: - DishwasherMode: - # Not clear whether these will stay in the XML - ModeTag: - - Auto - - Quick - - Quiet - - LowNoise - - LowEnergy - - Vacation - - Min - - Max - - Night - - Day - LaundryWasherMode: - # Not clear whether these will stay in the XML - ModeTag: - - Auto - - Quick - - Quiet - - LowNoise - - LowEnergy - - Vacation - - Min - - Max - - Night - - Day - MicrowaveOvenMode: - # Not clear whether these will stay in the XML - ModeTag: - - Auto - - Quick - - Quiet - - LowNoise - - LowEnergy - - Vacation - - Min - - Max - - Night - - Day - OvenMode: - # Not clear whether these will stay in the XML - ModeTag: - - Auto - - Quick - - Quiet - - LowNoise - - LowEnergy - - Vacation - - Min - - Max - - Night - - Day - RefrigeratorAndTemperatureControlledCabinetMode: - # Not clear whether these will stay in the XML - ModeTag: - - Auto - - Quick - - Quiet - - LowNoise - - LowEnergy - - Vacation - - Min - - Max - - Night - - Day bitmap values: DishwasherAlarm: AlarmBitmap: diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h index cf7924b9b5d70d..3b73ca8805a296 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h @@ -17238,30 +17238,30 @@ typedef NS_OPTIONS(uint32_t, MTRTimerFeature) { } MTR_PROVISIONALLY_AVAILABLE; typedef NS_ENUM(uint8_t, MTROvenCavityOperationalStateErrorState) { - MTROvenCavityOperationalStateErrorStateNoError MTR_PROVISIONALLY_AVAILABLE = 0x00, - MTROvenCavityOperationalStateErrorStateUnableToStartOrResume MTR_PROVISIONALLY_AVAILABLE = 0x01, - MTROvenCavityOperationalStateErrorStateUnableToCompleteOperation MTR_PROVISIONALLY_AVAILABLE = 0x02, - MTROvenCavityOperationalStateErrorStateCommandInvalidInState MTR_PROVISIONALLY_AVAILABLE = 0x03, -} MTR_PROVISIONALLY_AVAILABLE; + MTROvenCavityOperationalStateErrorStateNoError MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x00, + MTROvenCavityOperationalStateErrorStateUnableToStartOrResume MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x01, + MTROvenCavityOperationalStateErrorStateUnableToCompleteOperation MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x02, + MTROvenCavityOperationalStateErrorStateCommandInvalidInState MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x03, +} MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)); typedef NS_ENUM(uint8_t, MTROvenCavityOperationalStateOperationalState) { - MTROvenCavityOperationalStateOperationalStateStopped MTR_PROVISIONALLY_AVAILABLE = 0x00, - MTROvenCavityOperationalStateOperationalStateRunning MTR_PROVISIONALLY_AVAILABLE = 0x01, - MTROvenCavityOperationalStateOperationalStatePaused MTR_PROVISIONALLY_AVAILABLE = 0x02, - MTROvenCavityOperationalStateOperationalStateError MTR_PROVISIONALLY_AVAILABLE = 0x03, -} MTR_PROVISIONALLY_AVAILABLE; + MTROvenCavityOperationalStateOperationalStateStopped MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x00, + MTROvenCavityOperationalStateOperationalStateRunning MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x01, + MTROvenCavityOperationalStateOperationalStatePaused MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x02, + MTROvenCavityOperationalStateOperationalStateError MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x03, +} MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)); typedef NS_ENUM(uint16_t, MTROvenModeModeTag) { - MTROvenModeModeTagAuto MTR_PROVISIONALLY_AVAILABLE = 0x00, - MTROvenModeModeTagQuick MTR_PROVISIONALLY_AVAILABLE = 0x01, - MTROvenModeModeTagQuiet MTR_PROVISIONALLY_AVAILABLE = 0x02, - MTROvenModeModeTagLowNoise MTR_PROVISIONALLY_AVAILABLE = 0x03, - MTROvenModeModeTagLowEnergy MTR_PROVISIONALLY_AVAILABLE = 0x04, - MTROvenModeModeTagVacation MTR_PROVISIONALLY_AVAILABLE = 0x05, - MTROvenModeModeTagMin MTR_PROVISIONALLY_AVAILABLE = 0x06, - MTROvenModeModeTagMax MTR_PROVISIONALLY_AVAILABLE = 0x07, - MTROvenModeModeTagNight MTR_PROVISIONALLY_AVAILABLE = 0x08, - MTROvenModeModeTagDay MTR_PROVISIONALLY_AVAILABLE = 0x09, + MTROvenModeModeTagAuto MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x00, + MTROvenModeModeTagQuick MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x01, + MTROvenModeModeTagQuiet MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x02, + MTROvenModeModeTagLowNoise MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x03, + MTROvenModeModeTagLowEnergy MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x04, + MTROvenModeModeTagVacation MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x05, + MTROvenModeModeTagMin MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x06, + MTROvenModeModeTagMax MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x07, + MTROvenModeModeTagNight MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x08, + MTROvenModeModeTagDay MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x09, MTROvenModeModeTagBake MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x4000, MTROvenModeModeTagConvection MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x4001, MTROvenModeModeTagGrill MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x4002, @@ -17286,16 +17286,16 @@ typedef NS_OPTIONS(uint32_t, MTRModeSelectFeature) { } MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)); typedef NS_ENUM(uint16_t, MTRLaundryWasherModeModeTag) { - MTRLaundryWasherModeModeTagAuto MTR_PROVISIONALLY_AVAILABLE = 0x00, - MTRLaundryWasherModeModeTagQuick MTR_PROVISIONALLY_AVAILABLE = 0x01, - MTRLaundryWasherModeModeTagQuiet MTR_PROVISIONALLY_AVAILABLE = 0x02, - MTRLaundryWasherModeModeTagLowNoise MTR_PROVISIONALLY_AVAILABLE = 0x03, - MTRLaundryWasherModeModeTagLowEnergy MTR_PROVISIONALLY_AVAILABLE = 0x04, - MTRLaundryWasherModeModeTagVacation MTR_PROVISIONALLY_AVAILABLE = 0x05, - MTRLaundryWasherModeModeTagMin MTR_PROVISIONALLY_AVAILABLE = 0x06, - MTRLaundryWasherModeModeTagMax MTR_PROVISIONALLY_AVAILABLE = 0x07, - MTRLaundryWasherModeModeTagNight MTR_PROVISIONALLY_AVAILABLE = 0x08, - MTRLaundryWasherModeModeTagDay MTR_PROVISIONALLY_AVAILABLE = 0x09, + MTRLaundryWasherModeModeTagAuto MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x00, + MTRLaundryWasherModeModeTagQuick MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x01, + MTRLaundryWasherModeModeTagQuiet MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x02, + MTRLaundryWasherModeModeTagLowNoise MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x03, + MTRLaundryWasherModeModeTagLowEnergy MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x04, + MTRLaundryWasherModeModeTagVacation MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x05, + MTRLaundryWasherModeModeTagMin MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x06, + MTRLaundryWasherModeModeTagMax MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x07, + MTRLaundryWasherModeModeTagNight MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x08, + MTRLaundryWasherModeModeTagDay MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x09, MTRLaundryWasherModeModeTagNormal MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x4000, MTRLaundryWasherModeModeTagDelicate MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x4001, MTRLaundryWasherModeModeTagHeavy MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x4002, @@ -17303,16 +17303,16 @@ typedef NS_ENUM(uint16_t, MTRLaundryWasherModeModeTag) { } MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)); typedef NS_ENUM(uint16_t, MTRRefrigeratorAndTemperatureControlledCabinetModeModeTag) { - MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagAuto MTR_PROVISIONALLY_AVAILABLE = 0x00, - MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagQuick MTR_PROVISIONALLY_AVAILABLE = 0x01, - MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagQuiet MTR_PROVISIONALLY_AVAILABLE = 0x02, - MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagLowNoise MTR_PROVISIONALLY_AVAILABLE = 0x03, - MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagLowEnergy MTR_PROVISIONALLY_AVAILABLE = 0x04, - MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagVacation MTR_PROVISIONALLY_AVAILABLE = 0x05, - MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagMin MTR_PROVISIONALLY_AVAILABLE = 0x06, - MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagMax MTR_PROVISIONALLY_AVAILABLE = 0x07, - MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagNight MTR_PROVISIONALLY_AVAILABLE = 0x08, - MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagDay MTR_PROVISIONALLY_AVAILABLE = 0x09, + MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagAuto MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x00, + MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagQuick MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x01, + MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagQuiet MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x02, + MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagLowNoise MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x03, + MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagLowEnergy MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x04, + MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagVacation MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x05, + MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagMin MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x06, + MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagMax MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x07, + MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagNight MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x08, + MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagDay MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x09, MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagRapidCool MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x4000, MTRRefrigeratorAndTemperatureControlledCabinetModeModeTagRapidFreeze MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x4001, } MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)); @@ -17330,16 +17330,16 @@ typedef NS_OPTIONS(uint32_t, MTRLaundryWasherControlsFeature) { } MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)); typedef NS_ENUM(uint16_t, MTRRVCRunModeModeTag) { - MTRRVCRunModeModeTagAuto MTR_PROVISIONALLY_AVAILABLE = 0x00, - MTRRVCRunModeModeTagQuick MTR_PROVISIONALLY_AVAILABLE = 0x01, - MTRRVCRunModeModeTagQuiet MTR_PROVISIONALLY_AVAILABLE = 0x02, - MTRRVCRunModeModeTagLowNoise MTR_PROVISIONALLY_AVAILABLE = 0x03, - MTRRVCRunModeModeTagLowEnergy MTR_PROVISIONALLY_AVAILABLE = 0x04, - MTRRVCRunModeModeTagVacation MTR_PROVISIONALLY_AVAILABLE = 0x05, - MTRRVCRunModeModeTagMin MTR_PROVISIONALLY_AVAILABLE = 0x06, - MTRRVCRunModeModeTagMax MTR_PROVISIONALLY_AVAILABLE = 0x07, - MTRRVCRunModeModeTagNight MTR_PROVISIONALLY_AVAILABLE = 0x08, - MTRRVCRunModeModeTagDay MTR_PROVISIONALLY_AVAILABLE = 0x09, + MTRRVCRunModeModeTagAuto MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x00, + MTRRVCRunModeModeTagQuick MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x01, + MTRRVCRunModeModeTagQuiet MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x02, + MTRRVCRunModeModeTagLowNoise MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x03, + MTRRVCRunModeModeTagLowEnergy MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x04, + MTRRVCRunModeModeTagVacation MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x05, + MTRRVCRunModeModeTagMin MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x06, + MTRRVCRunModeModeTagMax MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x07, + MTRRVCRunModeModeTagNight MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x08, + MTRRVCRunModeModeTagDay MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x09, MTRRVCRunModeModeTagIdle MTR_AVAILABLE(ios(17.4), macos(14.4), watchos(10.4), tvos(17.4)) = 0x4000, MTRRVCRunModeModeTagCleaning MTR_AVAILABLE(ios(17.4), macos(14.4), watchos(10.4), tvos(17.4)) = 0x4001, MTRRVCRunModeModeTagMapping MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x4002, @@ -17361,16 +17361,16 @@ typedef NS_OPTIONS(uint32_t, MTRRVCRunModeFeature) { } MTR_AVAILABLE(ios(17.4), macos(14.4), watchos(10.4), tvos(17.4)); typedef NS_ENUM(uint16_t, MTRRVCCleanModeModeTag) { - MTRRVCCleanModeModeTagAuto MTR_PROVISIONALLY_AVAILABLE = 0x00, - MTRRVCCleanModeModeTagQuick MTR_PROVISIONALLY_AVAILABLE = 0x01, - MTRRVCCleanModeModeTagQuiet MTR_PROVISIONALLY_AVAILABLE = 0x02, - MTRRVCCleanModeModeTagLowNoise MTR_PROVISIONALLY_AVAILABLE = 0x03, - MTRRVCCleanModeModeTagLowEnergy MTR_PROVISIONALLY_AVAILABLE = 0x04, - MTRRVCCleanModeModeTagVacation MTR_PROVISIONALLY_AVAILABLE = 0x05, - MTRRVCCleanModeModeTagMin MTR_PROVISIONALLY_AVAILABLE = 0x06, - MTRRVCCleanModeModeTagMax MTR_PROVISIONALLY_AVAILABLE = 0x07, - MTRRVCCleanModeModeTagNight MTR_PROVISIONALLY_AVAILABLE = 0x08, - MTRRVCCleanModeModeTagDay MTR_PROVISIONALLY_AVAILABLE = 0x09, + MTRRVCCleanModeModeTagAuto MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x00, + MTRRVCCleanModeModeTagQuick MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x01, + MTRRVCCleanModeModeTagQuiet MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x02, + MTRRVCCleanModeModeTagLowNoise MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x03, + MTRRVCCleanModeModeTagLowEnergy MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x04, + MTRRVCCleanModeModeTagVacation MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x05, + MTRRVCCleanModeModeTagMin MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x06, + MTRRVCCleanModeModeTagMax MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x07, + MTRRVCCleanModeModeTagNight MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x08, + MTRRVCCleanModeModeTagDay MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x09, MTRRVCCleanModeModeTagDeepClean MTR_AVAILABLE(ios(17.4), macos(14.4), watchos(10.4), tvos(17.4)) = 0x4000, MTRRVCCleanModeModeTagVacuum MTR_AVAILABLE(ios(17.4), macos(14.4), watchos(10.4), tvos(17.4)) = 0x4001, MTRRVCCleanModeModeTagMop MTR_AVAILABLE(ios(17.4), macos(14.4), watchos(10.4), tvos(17.4)) = 0x4002, @@ -17395,16 +17395,16 @@ typedef NS_OPTIONS(uint32_t, MTRRefrigeratorAlarmAlarmBitmap) { } MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)); typedef NS_ENUM(uint16_t, MTRDishwasherModeModeTag) { - MTRDishwasherModeModeTagAuto MTR_PROVISIONALLY_AVAILABLE = 0x00, - MTRDishwasherModeModeTagQuick MTR_PROVISIONALLY_AVAILABLE = 0x01, - MTRDishwasherModeModeTagQuiet MTR_PROVISIONALLY_AVAILABLE = 0x02, - MTRDishwasherModeModeTagLowNoise MTR_PROVISIONALLY_AVAILABLE = 0x03, - MTRDishwasherModeModeTagLowEnergy MTR_PROVISIONALLY_AVAILABLE = 0x04, - MTRDishwasherModeModeTagVacation MTR_PROVISIONALLY_AVAILABLE = 0x05, - MTRDishwasherModeModeTagMin MTR_PROVISIONALLY_AVAILABLE = 0x06, - MTRDishwasherModeModeTagMax MTR_PROVISIONALLY_AVAILABLE = 0x07, - MTRDishwasherModeModeTagNight MTR_PROVISIONALLY_AVAILABLE = 0x08, - MTRDishwasherModeModeTagDay MTR_PROVISIONALLY_AVAILABLE = 0x09, + MTRDishwasherModeModeTagAuto MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x00, + MTRDishwasherModeModeTagQuick MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x01, + MTRDishwasherModeModeTagQuiet MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x02, + MTRDishwasherModeModeTagLowNoise MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x03, + MTRDishwasherModeModeTagLowEnergy MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x04, + MTRDishwasherModeModeTagVacation MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x05, + MTRDishwasherModeModeTagMin MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x06, + MTRDishwasherModeModeTagMax MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x07, + MTRDishwasherModeModeTagNight MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x08, + MTRDishwasherModeModeTagDay MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x09, MTRDishwasherModeModeTagNormal MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x4000, MTRDishwasherModeModeTagHeavy MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x4001, MTRDishwasherModeModeTagLight MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x4002, @@ -17487,16 +17487,16 @@ typedef NS_OPTIONS(uint32_t, MTRDishwasherAlarmFeature) { } MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)); typedef NS_ENUM(uint16_t, MTRMicrowaveOvenModeModeTag) { - MTRMicrowaveOvenModeModeTagAuto MTR_PROVISIONALLY_AVAILABLE = 0x00, - MTRMicrowaveOvenModeModeTagQuick MTR_PROVISIONALLY_AVAILABLE = 0x01, - MTRMicrowaveOvenModeModeTagQuiet MTR_PROVISIONALLY_AVAILABLE = 0x02, - MTRMicrowaveOvenModeModeTagLowNoise MTR_PROVISIONALLY_AVAILABLE = 0x03, - MTRMicrowaveOvenModeModeTagLowEnergy MTR_PROVISIONALLY_AVAILABLE = 0x04, - MTRMicrowaveOvenModeModeTagVacation MTR_PROVISIONALLY_AVAILABLE = 0x05, - MTRMicrowaveOvenModeModeTagMin MTR_PROVISIONALLY_AVAILABLE = 0x06, - MTRMicrowaveOvenModeModeTagMax MTR_PROVISIONALLY_AVAILABLE = 0x07, - MTRMicrowaveOvenModeModeTagNight MTR_PROVISIONALLY_AVAILABLE = 0x08, - MTRMicrowaveOvenModeModeTagDay MTR_PROVISIONALLY_AVAILABLE = 0x09, + MTRMicrowaveOvenModeModeTagAuto MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x00, + MTRMicrowaveOvenModeModeTagQuick MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x01, + MTRMicrowaveOvenModeModeTagQuiet MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x02, + MTRMicrowaveOvenModeModeTagLowNoise MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x03, + MTRMicrowaveOvenModeModeTagLowEnergy MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x04, + MTRMicrowaveOvenModeModeTagVacation MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x05, + MTRMicrowaveOvenModeModeTagMin MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x06, + MTRMicrowaveOvenModeModeTagMax MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x07, + MTRMicrowaveOvenModeModeTagNight MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x08, + MTRMicrowaveOvenModeModeTagDay MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x09, MTRMicrowaveOvenModeModeTagNormal MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x4000, MTRMicrowaveOvenModeModeTagDefrost MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x4001, } MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)); @@ -17522,10 +17522,10 @@ typedef NS_ENUM(uint8_t, MTROperationalState) { } MTR_AVAILABLE(ios(17.4), macos(14.4), watchos(10.4), tvos(17.4)); typedef NS_ENUM(uint8_t, MTRRVCOperationalStateErrorState) { - MTRRVCOperationalStateErrorStateNoError MTR_PROVISIONALLY_AVAILABLE = 0x00, - MTRRVCOperationalStateErrorStateUnableToStartOrResume MTR_PROVISIONALLY_AVAILABLE = 0x01, - MTRRVCOperationalStateErrorStateUnableToCompleteOperation MTR_PROVISIONALLY_AVAILABLE = 0x02, - MTRRVCOperationalStateErrorStateCommandInvalidInState MTR_PROVISIONALLY_AVAILABLE = 0x03, + MTRRVCOperationalStateErrorStateNoError MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x00, + MTRRVCOperationalStateErrorStateUnableToStartOrResume MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x01, + MTRRVCOperationalStateErrorStateUnableToCompleteOperation MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x02, + MTRRVCOperationalStateErrorStateCommandInvalidInState MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x03, MTRRVCOperationalStateErrorStateFailedToFindChargingDock MTR_AVAILABLE(ios(17.4), macos(14.4), watchos(10.4), tvos(17.4)) = 0x40, MTRRVCOperationalStateErrorStateStuck MTR_AVAILABLE(ios(17.4), macos(14.4), watchos(10.4), tvos(17.4)) = 0x41, MTRRVCOperationalStateErrorStateDustBinMissing MTR_AVAILABLE(ios(17.4), macos(14.4), watchos(10.4), tvos(17.4)) = 0x42, @@ -17537,10 +17537,10 @@ typedef NS_ENUM(uint8_t, MTRRVCOperationalStateErrorState) { } MTR_AVAILABLE(ios(17.4), macos(14.4), watchos(10.4), tvos(17.4)); typedef NS_ENUM(uint8_t, MTRRVCOperationalStateOperationalState) { - MTRRVCOperationalStateOperationalStateStopped MTR_PROVISIONALLY_AVAILABLE = 0x00, - MTRRVCOperationalStateOperationalStateRunning MTR_PROVISIONALLY_AVAILABLE = 0x01, - MTRRVCOperationalStateOperationalStatePaused MTR_PROVISIONALLY_AVAILABLE = 0x02, - MTRRVCOperationalStateOperationalStateError MTR_PROVISIONALLY_AVAILABLE = 0x03, + MTRRVCOperationalStateOperationalStateStopped MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x00, + MTRRVCOperationalStateOperationalStateRunning MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x01, + MTRRVCOperationalStateOperationalStatePaused MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x02, + MTRRVCOperationalStateOperationalStateError MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4)) = 0x03, MTRRVCOperationalStateOperationalStateSeekingCharger MTR_AVAILABLE(ios(17.4), macos(14.4), watchos(10.4), tvos(17.4)) = 0x40, MTRRVCOperationalStateOperationalStateCharging MTR_AVAILABLE(ios(17.4), macos(14.4), watchos(10.4), tvos(17.4)) = 0x41, MTRRVCOperationalStateOperationalStateDocked MTR_AVAILABLE(ios(17.4), macos(14.4), watchos(10.4), tvos(17.4)) = 0x42, diff --git a/src/darwin/Framework/CHIPTests/MTRCommissionableBrowserTests.m b/src/darwin/Framework/CHIPTests/MTRCommissionableBrowserTests.m index 0acfbd9a580371..d2b5f797e4514b 100644 --- a/src/darwin/Framework/CHIPTests/MTRCommissionableBrowserTests.m +++ b/src/darwin/Framework/CHIPTests/MTRCommissionableBrowserTests.m @@ -104,6 +104,22 @@ - (void)controller:(MTRDeviceController *)controller didFindCommissionableDevice [_results addObject:snapshot]; + XCTAssertLessThanOrEqual(_results.count, kExpectedDiscoveredDevicesCount); + + __auto_type instanceName = device.instanceName; + __auto_type vendorId = device.vendorID; + __auto_type productId = device.productID; + __auto_type discriminator = device.discriminator; + __auto_type commissioningMode = device.commissioningMode; + + XCTAssertEqual(instanceName.length, 16); // The instance name is random, so just ensure the len is right. + XCTAssertEqualObjects(vendorId, @(kTestVendorId)); + XCTAssertTrue([kTestProductIds containsObject:productId]); + XCTAssertTrue([kTestDiscriminators containsObject:discriminator]); + XCTAssertEqual(commissioningMode, YES); + + NSLog(@"Found device %@", snapshot); + if (_results.count == kExpectedDiscoveredDevicesCount) { // Do some sanity checking on our results and removedResults to make // sure we really only saw the relevant set of things. @@ -123,39 +139,17 @@ - (void)controller:(MTRDeviceController *)controller didFindCommissionableDevice [self.expectation fulfill]; } } - - XCTAssertLessThanOrEqual(_results.count, kExpectedDiscoveredDevicesCount); - - __auto_type instanceName = device.instanceName; - __auto_type vendorId = device.vendorID; - __auto_type productId = device.productID; - __auto_type discriminator = device.discriminator; - __auto_type commissioningMode = device.commissioningMode; - - XCTAssertEqual(instanceName.length, 16); // The instance name is random, so just ensure the len is right. - XCTAssertEqualObjects(vendorId, @(kTestVendorId)); - XCTAssertTrue([kTestProductIds containsObject:productId]); - XCTAssertTrue([kTestDiscriminators containsObject:discriminator]); - XCTAssertEqual(commissioningMode, YES); - - NSLog(@"Found Device (%@) with discriminator: %@ (vendor: %@, product: %@)", instanceName, discriminator, vendorId, productId); } - (void)controller:(MTRDeviceController *)controller didRemoveCommissionableDevice:(MTRCommissionableBrowserResult *)device { - __auto_type instanceName = device.instanceName; - __auto_type vendorId = device.vendorID; - __auto_type productId = device.productID; - __auto_type discriminator = device.discriminator; - - NSLog( - @"Removed Device (%@) with discriminator: %@ (vendor: %@, product: %@)", instanceName, discriminator, vendorId, productId); - __auto_type * snapshot = ResultSnapshot(device); - XCTAssertTrue([_results containsObject:snapshot], @"Removed device %@ is not something we found before", snapshot); + XCTAssertTrue([_results containsObject:snapshot], @"Removed device %@ is not something we found before: %@", snapshot, _results); [_removedResults addObject:snapshot]; [_results removeObject:snapshot]; + + NSLog(@"Removed device %@", snapshot); } @end diff --git a/src/darwin/Framework/CHIPTests/MTRErrorMappingTests.m b/src/darwin/Framework/CHIPTests/MTRErrorMappingTests.m new file mode 100644 index 00000000000000..3bcc6ba8046fd7 --- /dev/null +++ b/src/darwin/Framework/CHIPTests/MTRErrorMappingTests.m @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Matter/Matter.h> +#import <XCTest/XCTest.h> + +// NOTE: This is a .mm file, so that it can include MTRError_Internal.h + +#import "MTRError_Testable.h" + +@interface MTRErrorMappingTests : XCTestCase +@end + +@implementation MTRErrorMappingTests + +- (void)testPublicNonInteractionAPIValues +{ + for (int errorCode = 1; errorCode <= MTRMaxErrorCode; errorCode++) { + // A few error codes are not actually representing CHIP_ERROR values. + if (errorCode == MTRErrorCodeWrongAddressType || errorCode == MTRErrorCodeUnknownSchema) { + continue; + } + + // All of these should round-trip appropriately. + __auto_type * error = [NSError errorWithDomain:MTRErrorDomain code:errorCode userInfo:nil]; + __auto_type * newError1 = [MTRError errorWithCode:(MTRErrorCode) errorCode]; + XCTAssertEqual(newError1.domain, error.domain, "Testing error code %d", errorCode); + XCTAssertEqual(newError1.code, error.code, "Testing error code %d", errorCode); + + __auto_type chipError = [MTRError errorToCHIPIntegerCode:error]; + __auto_type * newError2 = [MTRError errorForCHIPIntegerCode:chipError]; + XCTAssertEqual(newError2.domain, error.domain, "Testing error code %d", errorCode); + XCTAssertEqual(newError2.code, error.code, "Testing error code %d", errorCode); + } + + // Check that an unknown value becomes GeneralError. + __auto_type * error = [MTRError errorWithCode:(MTRErrorCode) (MTRMaxErrorCode + 1)]; + XCTAssertEqual(error.domain, MTRErrorDomain); + XCTAssertEqual(error.code, MTRMaxErrorCode + 1); + + __auto_type chipError = [MTRError errorToCHIPIntegerCode:error]; + __auto_type * newError = [MTRError errorForCHIPIntegerCode:chipError]; + XCTAssertEqual(newError.domain, MTRErrorDomain); + XCTAssertEqual(newError.code, MTRErrorCodeGeneralError); +} + +@end diff --git a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj index 1de3c69f2f1417..f2b89f0ca48a3f 100644 --- a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj +++ b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj @@ -178,6 +178,8 @@ 51565CB22A7AD77600469F18 /* MTRDeviceControllerDataStore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51565CB02A7AD77600469F18 /* MTRDeviceControllerDataStore.mm */; }; 51565CB42A7AD78D00469F18 /* MTRDeviceControllerStorageDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 51565CB32A7AD78D00469F18 /* MTRDeviceControllerStorageDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 51565CB62A7B0D6600469F18 /* MTRDeviceControllerParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 51565CB52A7B0D6600469F18 /* MTRDeviceControllerParameters.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 51578AE92D0B9B1D001716FF /* MTRErrorMappingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 51578AE82D0B9B1D001716FF /* MTRErrorMappingTests.m */; }; + 51578AEB2D0B9DC0001716FF /* MTRError_Testable.h in Headers */ = {isa = PBXBuildFile; fileRef = 51578AEA2D0B9DC0001716FF /* MTRError_Testable.h */; }; 515BE4ED2B72C0C5000BC1FD /* MTRUnfairLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 515BE4EC2B72C0C5000BC1FD /* MTRUnfairLock.h */; }; 515C1C6F284F9FFB00A48F0C /* MTRFramework.mm in Sources */ = {isa = PBXBuildFile; fileRef = 515C1C6D284F9FFB00A48F0C /* MTRFramework.mm */; }; 515C1C70284F9FFB00A48F0C /* MTRFramework.h in Headers */ = {isa = PBXBuildFile; fileRef = 515C1C6E284F9FFB00A48F0C /* MTRFramework.h */; }; @@ -669,6 +671,8 @@ 51565CB02A7AD77600469F18 /* MTRDeviceControllerDataStore.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRDeviceControllerDataStore.mm; sourceTree = "<group>"; }; 51565CB32A7AD78D00469F18 /* MTRDeviceControllerStorageDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRDeviceControllerStorageDelegate.h; sourceTree = "<group>"; }; 51565CB52A7B0D6600469F18 /* MTRDeviceControllerParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRDeviceControllerParameters.h; sourceTree = "<group>"; }; + 51578AE82D0B9B1D001716FF /* MTRErrorMappingTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MTRErrorMappingTests.m; sourceTree = "<group>"; }; + 51578AEA2D0B9DC0001716FF /* MTRError_Testable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRError_Testable.h; sourceTree = "<group>"; }; 515BE4EC2B72C0C5000BC1FD /* MTRUnfairLock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRUnfairLock.h; sourceTree = "<group>"; }; 515C1C6D284F9FFB00A48F0C /* MTRFramework.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRFramework.mm; sourceTree = "<group>"; }; 515C1C6E284F9FFB00A48F0C /* MTRFramework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRFramework.h; sourceTree = "<group>"; }; @@ -1540,6 +1544,7 @@ 5109E9B32CB8B5DF0006884B /* MTRDeviceType.mm */, 5129BCFC26A9EE3300122DDF /* MTRError.h */, B2E0D7AB245B0B5C003C5B48 /* MTRError_Internal.h */, + 51578AEA2D0B9DC0001716FF /* MTRError_Testable.h */, B2E0D7AA245B0B5C003C5B48 /* MTRError.mm */, 754F3DF327FBB94B00E60580 /* MTREventTLVValueDecoder_Internal.h */, 515C1C6E284F9FFB00A48F0C /* MTRFramework.h */, @@ -1618,6 +1623,7 @@ 5109E9B62CB8B83D0006884B /* MTRDeviceTypeTests.m */, 51D9CB0A2BA37DCE0049D6DB /* MTRDSTOffsetTests.m */, 3D0C484A29DA4FA0006D811F /* MTRErrorTests.m */, + 51578AE82D0B9B1D001716FF /* MTRErrorMappingTests.m */, 5173A47829C0E82300F67F48 /* MTRFabricInfoTests.m */, 8874C1312B69C7060084BEFD /* MTRMetricsTests.m */, 510CECA6297F72470064E0B3 /* MTROperationalCertificateIssuerTests.m */, @@ -1941,6 +1947,7 @@ 9B5CCB5D2C6EC890009DD99B /* MTRDevice_XPC.h in Headers */, 991DC08B247704DC00C13860 /* MTRLogging_Internal.h in Headers */, 51FE723F2ACDEF3E00437032 /* MTRCommandPayloadExtensions_Internal.h in Headers */, + 51578AEB2D0B9DC0001716FF /* MTRError_Testable.h in Headers */, 51D0B12E2B6177FD006E3511 /* MTRAccessGrant.h in Headers */, 5109E9B52CB8B5DF0006884B /* MTRDeviceType.h in Headers */, 1E4D655029C208DD00BC3478 /* MTRCommissionableBrowserDelegate.h in Headers */, @@ -2348,6 +2355,7 @@ 518D3F852AA14006008E0007 /* MTRControllerAdvertisingTests.m in Sources */, 51C8E3F82825CDB600D47D00 /* MTRTestKeys.m in Sources */, 51C984622A61CE2A00B0AD9A /* MTRFabricInfoChecker.m in Sources */, + 51578AE92D0B9B1D001716FF /* MTRErrorMappingTests.m in Sources */, 99C65E10267282F1003402F6 /* MTRControllerTests.m in Sources */, 8874C1322B69C7060084BEFD /* MTRMetricsTests.m in Sources */, 1E5801C328941C050033A199 /* MTRTestOTAProvider.m in Sources */, diff --git a/src/data-model-providers/codegen/CodegenDataModelProvider.cpp b/src/data-model-providers/codegen/CodegenDataModelProvider.cpp index 95bac8fbbf82f3..b599ba1dfdc0dd 100644 --- a/src/data-model-providers/codegen/CodegenDataModelProvider.cpp +++ b/src/data-model-providers/codegen/CodegenDataModelProvider.cpp @@ -35,6 +35,7 @@ #include <lib/core/CHIPError.h> #include <lib/core/DataModelTypes.h> #include <lib/support/CodeUtils.h> +#include <lib/support/SpanSearchValue.h> #include <optional> #include <variant> @@ -106,6 +107,19 @@ using detail::EnumeratorCommandFinder; namespace { +/// Search by device type within a span of EmberAfDeviceType (finds the device type that matches the given +/// DataModel::DeviceTypeEntry) +struct ByDeviceType +{ + using Key = DataModel::DeviceTypeEntry; + using Type = const EmberAfDeviceType; + static Span<Type> GetSpan(Span<const EmberAfDeviceType> & data) { return data; } + static bool HasKey(const Key & id, const Type & instance) + { + return (instance.deviceId == id.deviceTypeId) && (instance.deviceVersion == id.deviceTypeRevision); + } +}; + const CommandId * AcceptedCommands(const EmberAfCluster & cluster) { return cluster.acceptedCommandList; @@ -268,51 +282,17 @@ DataModel::CommandEntry CommandEntryFrom(const ConcreteClusterPath & clusterPath // to a common type is probably better. Need to figure out dependencies since // this would make ember return datamodel-provider types. // See: https://github.com/project-chip/connectedhomeip/issues/35889 -DataModel::DeviceTypeEntry DeviceTypeEntryFromEmber(const EmberAfDeviceType & other) +std::optional<DataModel::DeviceTypeEntry> DeviceTypeEntryFromEmber(const EmberAfDeviceType * other) { - DataModel::DeviceTypeEntry entry; - - entry.deviceTypeId = other.deviceId; - entry.deviceTypeRevision = other.deviceVersion; - - return entry; -} - -// Explicitly compare for identical entries. note that types are different, -// so you must do `a == b` and the `b == a` will not work. -bool operator==(const DataModel::DeviceTypeEntry & a, const EmberAfDeviceType & b) -{ - return (a.deviceTypeId == b.deviceId) && (a.deviceTypeRevision == b.deviceVersion); -} - -/// Find the `index` where one of the following holds: -/// - types[index - 1] == previous OR -/// - index == types.size() // i.e. not found or there is no next -/// -/// hintWherePreviousMayBe represents a search hint where previous may exist. -unsigned FindNextDeviceTypeIndex(Span<const EmberAfDeviceType> types, const DataModel::DeviceTypeEntry & previous, - unsigned hintWherePreviousMayBe) -{ - if (hintWherePreviousMayBe < types.size()) - { - // this is a valid hint ... see if we are lucky - if (previous == types[hintWherePreviousMayBe]) - { - return hintWherePreviousMayBe + 1; // return the next index - } - } - - // hint was not useful. We have to do a full search - for (unsigned idx = 0; idx < types.size(); idx++) + if (other == nullptr) { - if (previous == types[idx]) - { - return idx + 1; - } + return std::nullopt; } - // cast should be safe as we know we do not have that many types - return static_cast<unsigned>(types.size()); + return DataModel::DeviceTypeEntry{ + .deviceTypeId = other->deviceId, + .deviceTypeRevision = other->deviceVersion, + }; } const ConcreteCommandPath kInvalidCommandPath(kInvalidEndpointId, kInvalidClusterId, kInvalidCommandId); @@ -894,15 +874,9 @@ std::optional<DataModel::DeviceTypeEntry> CodegenDataModelProvider::FirstDeviceT CHIP_ERROR err = CHIP_NO_ERROR; Span<const EmberAfDeviceType> deviceTypes = emberAfDeviceTypeListFromEndpointIndex(*endpoint_index, err); + SpanSearchValue<chip::Span<const EmberAfDeviceType>> searchable(&deviceTypes); - if (deviceTypes.empty()) - { - return std::nullopt; - } - - // we start at the beginning - mDeviceTypeIterationHint = 0; - return DeviceTypeEntryFromEmber(deviceTypes[0]); + return DeviceTypeEntryFromEmber(searchable.First<ByDeviceType>(mDeviceTypeIterationHint).Value()); } std::optional<DataModel::DeviceTypeEntry> CodegenDataModelProvider::NextDeviceType(EndpointId endpoint, @@ -917,18 +891,11 @@ std::optional<DataModel::DeviceTypeEntry> CodegenDataModelProvider::NextDeviceTy return std::nullopt; } - CHIP_ERROR err = CHIP_NO_ERROR; - Span<const EmberAfDeviceType> deviceTypes = emberAfDeviceTypeListFromEndpointIndex(*endpoint_index, err); - - unsigned idx = FindNextDeviceTypeIndex(deviceTypes, previous, mDeviceTypeIterationHint); - - if (idx >= deviceTypes.size()) - { - return std::nullopt; - } + CHIP_ERROR err = CHIP_NO_ERROR; + chip::Span<const EmberAfDeviceType> deviceTypes = emberAfDeviceTypeListFromEndpointIndex(*endpoint_index, err); + SpanSearchValue<chip::Span<const EmberAfDeviceType>> searchable(&deviceTypes); - mDeviceTypeIterationHint = idx; - return DeviceTypeEntryFromEmber(deviceTypes[idx]); + return DeviceTypeEntryFromEmber(searchable.Next<ByDeviceType>(previous, mDeviceTypeIterationHint).Value()); } std::optional<DataModel::Provider::SemanticTag> CodegenDataModelProvider::GetFirstSemanticTag(EndpointId endpoint) diff --git a/src/include/platform/CHIPDeviceEvent.h b/src/include/platform/CHIPDeviceEvent.h index 09f4c46b652920..9618d93f5faa05 100644 --- a/src/include/platform/CHIPDeviceEvent.h +++ b/src/include/platform/CHIPDeviceEvent.h @@ -534,6 +534,7 @@ struct ChipDeviceEvent final FabricIndex fabricIndex; bool addNocCommandHasBeenInvoked; bool updateNocCommandHasBeenInvoked; + bool updateTermsAndConditionsHasBeenInvoked; } FailSafeTimerExpired; struct diff --git a/src/lib/support/BUILD.gn b/src/lib/support/BUILD.gn index a8daba8f5537e3..29a381d620f822 100644 --- a/src/lib/support/BUILD.gn +++ b/src/lib/support/BUILD.gn @@ -236,6 +236,7 @@ static_library("support") { "ScopedBuffer.h", "SetupDiscriminator.h", "SortUtils.h", + "SpanSearchValue.h", "StateMachine.h", "StringBuilder.cpp", "StringBuilder.h", diff --git a/src/lib/support/DefaultStorageKeyAllocator.h b/src/lib/support/DefaultStorageKeyAllocator.h index 9ed8a2f56cfd77..b0de78d085e48d 100644 --- a/src/lib/support/DefaultStorageKeyAllocator.h +++ b/src/lib/support/DefaultStorageKeyAllocator.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2021-2024 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -256,6 +256,10 @@ class DefaultStorageKeyAllocator // when new fabric is created, this list needs to be updated, // when client init DefaultICDClientStorage, this table needs to be loaded. static StorageKeyName ICDFabricList() { return StorageKeyName::FromConst("g/icdfl"); } + + // Terms and Conditions Acceptance Key + // Stores the terms and conditions acceptance including terms and conditions revision, TLV encoded + static StorageKeyName TermsAndConditionsAcceptance() { return StorageKeyName::FromConst("g/tc"); } }; } // namespace chip diff --git a/src/lib/support/SpanSearchValue.h b/src/lib/support/SpanSearchValue.h new file mode 100644 index 00000000000000..e11a9e64c0050d --- /dev/null +++ b/src/lib/support/SpanSearchValue.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include <cstddef> +#include <lib/support/Span.h> + +#include <optional> + +namespace chip { + +/// represents a wrapper around a type `T` that contains internal +/// `Span<...>` values of other sub-types. It allows searching within the container sub-spans +/// to create new containers. +/// +/// The use case is that we very often search within nested containers, like "find-endpoint" + "find-cluster" + "find-attribute" +/// and we generally only care about "does the last element exist or not" +/// +/// A typical example of the way this class is used looks like this: +/// +/// SpanSearchValue container(somePointer); +/// +/// const AcceptedCommandData * value = +/// container +/// .Find<ByEndpoint>(path.mEndpointId, mEndpointIndexHint) +/// .Find<ByServerCluster>(path.mClusterId, mServerClusterHint) +/// .Find<ByAcceptedCommand>(path.mCommandId, mAcceptedCommandHint) +/// .Value(); +/// +/// Where a `ByFoo` structure looks like: +/// +/// struct ByFoo { +/// using Key = int; // the KEY inside a type +/// using Type = SomeValueType; // The type that is indexed by `Key` +/// +/// /// Allows getting the "Span of Type" from an underlying structure. +/// /// A `SpanSearchValue<Foo>` will require a `GetSpan(Foo&)` +/// static Span<Type> GetSpan(ContainerType & data) { /* return ... */ } +/// +/// /// Checks that the `Type` value has the given `Key` or not +/// static bool HasKey(const Key & id, const Type & instance) { /* return "instance has key id" */ } +/// } +/// +/// Where we define: +/// - how to get a "span of sub-elements" for an object (`GetSpan`) +/// - how to determine if a given sub-element has the "correct key" +template <typename T> +class SpanSearchValue +{ +public: + SpanSearchValue() : mValue(nullptr) {} + SpanSearchValue(std::nullptr_t) : mValue(nullptr) {} + explicit SpanSearchValue(T * value) : mValue(value) {} + + /// Returns nullptr if such an element does not exist or non-null valid value if the element exists + T * Value() const { return mValue; } + + /// Gets the first element of `TYPE::Type` + template <typename TYPE> + SpanSearchValue<typename TYPE::Type> First(unsigned & indexHint) + { + // if no value, searching more also yields no value + VerifyOrReturnValue(mValue != nullptr, nullptr); + + Span<typename TYPE::Type> value_span = TYPE::GetSpan(*mValue); + VerifyOrReturnValue(!value_span.empty(), nullptr); + + // found it, save the hint + indexHint = 0; + return SpanSearchValue<typename TYPE::Type>(&value_span[0]); + } + + /// Find the value corresponding to `key` + template <typename TYPE> + SpanSearchValue<typename TYPE::Type> Find(typename TYPE::Key key, unsigned & indexHint) + { + VerifyOrReturnValue(mValue != nullptr, nullptr); + + Span<typename TYPE::Type> value_span = TYPE::GetSpan(*mValue); + + if (!FindIndexUsingHint(key, value_span, indexHint, TYPE::HasKey)) + { + return nullptr; + } + + return SpanSearchValue<typename TYPE::Type>(&value_span[indexHint]); + } + + /// Finds the value that occurs after `key` in the underlying collection. + template <typename TYPE> + SpanSearchValue<typename TYPE::Type> Next(typename TYPE::Key key, unsigned & indexHint) + { + VerifyOrReturnValue(mValue != nullptr, nullptr); + + Span<typename TYPE::Type> value_span = TYPE::GetSpan(*mValue); + + if (!FindIndexUsingHint(key, value_span, indexHint, TYPE::HasKey)) + { + return nullptr; + } + + VerifyOrReturnValue((indexHint + 1) < value_span.size(), nullptr); + + indexHint++; + return SpanSearchValue<typename TYPE::Type>(&value_span[indexHint]); + } + +private: + T * mValue = nullptr; // underlying value, NULL if such a value does not exist + + /// Search for the index where `needle` is located inside `haystack` + /// + /// using `haystackValueMatchesNeedle` to find if a given haystack value matches the given needle + /// + /// `in_out_hint` contains a start search point at the start and will contain the found index + /// location (if found) at the end. + /// + /// Returns true on success (index found) false on failure (index not found). If returning + /// false, the value of `in_out_hint` is unchanged + template <typename N, typename H> + static bool FindIndexUsingHint(const N & needle, Span<H> haystack, unsigned & in_out_hint, + bool (*haystackValueMatchesNeedle)(const N &, const typename std::remove_const<H>::type &)) + { + // search starts at `hint` rather than 0 + const unsigned haystackSize = static_cast<unsigned>(haystack.size()); + unsigned checkIndex = (in_out_hint < haystackSize) ? in_out_hint : 0; + + for (unsigned i = 0; i < haystackSize; i++, checkIndex++) + { + if (haystackValueMatchesNeedle(needle, haystack[checkIndex % haystackSize])) + { + in_out_hint = checkIndex % haystackSize; + return true; + } + } + + return false; + } +}; + +} // namespace chip diff --git a/src/lib/support/tests/BUILD.gn b/src/lib/support/tests/BUILD.gn index c6bfddb9269a7a..d814f70c477ed4 100644 --- a/src/lib/support/tests/BUILD.gn +++ b/src/lib/support/tests/BUILD.gn @@ -56,6 +56,7 @@ chip_test_suite("tests") { "TestScopedBuffer.cpp", "TestSorting.cpp", "TestSpan.cpp", + "TestSpanSearchValue.cpp", "TestStateMachine.cpp", "TestStaticSupportSmartPtr.cpp", "TestStringBuilder.cpp", diff --git a/src/lib/support/tests/TestSpanSearchValue.cpp b/src/lib/support/tests/TestSpanSearchValue.cpp new file mode 100644 index 00000000000000..469c590d0c1a38 --- /dev/null +++ b/src/lib/support/tests/TestSpanSearchValue.cpp @@ -0,0 +1,187 @@ +/* + * 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 "pw_unit_test/framework.h" +#include <pw_unit_test/framework.h> + +#include <lib/core/DataModelTypes.h> +#include <lib/core/StringBuilderAdapters.h> +#include <lib/support/SpanSearchValue.h> + +namespace { + +using namespace chip; + +struct ClusterData +{ + const ClusterId id; + const char * name; +}; + +struct EndpointData +{ + const EndpointId id; + + const char * name; + Span<const ClusterData> serverClusters; + Span<const ClusterData> clientClusters; +}; + +struct EndpointItemsWrapper +{ + Span<const EndpointData> data; + + template <size_t N> + EndpointItemsWrapper(EndpointData (&d)[N]) : data(d) + {} +}; + +const ClusterData gClusterList1[] = { + { + .id = 100, + .name = "one hundred", + }, + { + .id = 200, + .name = "two hundred", + }, +}; + +const ClusterData gClusterList2[] = { + { + .id = 1, + .name = "just one", + }, +}; + +EndpointData gEndpointDataItems[] = { + { + .id = 123, + .name = "foo", + .serverClusters = Span<const ClusterData>(gClusterList1), + .clientClusters = Span<const ClusterData>(gClusterList2), + }, + { + .id = 456, + .name = "bar", + .serverClusters = Span<const ClusterData>(gClusterList2), + .clientClusters = Span<const ClusterData>(), + }, + { + .id = 1000, + .name = "Empty", + .serverClusters = Span<const ClusterData>(), + .clientClusters = Span<const ClusterData>(), + }, +}; + +/// search index definitions +struct ByEndpoint +{ + using Key = EndpointId; + using Type = const EndpointData; + static Span<Type> GetSpan(EndpointItemsWrapper & data) { return data.data; } + static bool HasKey(const Key & id, const Type & instance) { return instance.id == id; } +}; + +struct ByServerCluster +{ + using Key = ClusterId; + using Type = const ClusterData; + static Span<Type> GetSpan(const EndpointData & data) { return data.serverClusters; } + static bool HasKey(const Key & id, const Type & instance) { return instance.id == id; } +}; + +struct ByClientCluster +{ + using Key = ClusterId; + using Type = const ClusterData; + static Span<Type> GetSpan(const EndpointData & data) { return data.clientClusters; } + static bool HasKey(const Key & id, const Type & instance) { return instance.id == id; } +}; + +} // namespace + +TEST(TestSpanSearchValue, TestFunctionality) +{ + EndpointItemsWrapper wrapper(gEndpointDataItems); + SpanSearchValue<EndpointItemsWrapper> tree(&wrapper); + + EXPECT_EQ(tree.Value(), &wrapper); // value getting to start matches + + // search first items + { + unsigned hint1 = 0; + auto ep = tree.First<ByEndpoint>(hint1); + + unsigned hint2 = 0; + auto cl = ep.First<ByServerCluster>(hint2); + + ASSERT_NE(cl.Value(), nullptr); + EXPECT_EQ(cl.Value()->id, 100u); + EXPECT_STREQ(cl.Value()->name, "one hundred"); + } + + // one level search, with hint + { + unsigned hint = 0; + ASSERT_NE(tree.Find<ByEndpoint>(123, hint).Value(), nullptr); + ASSERT_STREQ(tree.Find<ByEndpoint>(123, hint).Value()->name, "foo"); + EXPECT_EQ(hint, 0u); + + ASSERT_NE(tree.Find<ByEndpoint>(456, hint).Value(), nullptr); + EXPECT_EQ(hint, 1u); + EXPECT_STREQ(tree.Find<ByEndpoint>(456, hint).Value()->name, "bar"); + EXPECT_EQ(hint, 1u); + + // hint is ignored here + EXPECT_STREQ(tree.Find<ByEndpoint>(123, hint).Value()->name, "foo"); + EXPECT_EQ(hint, 0u); + + EXPECT_STREQ(tree.Find<ByEndpoint>(1000, hint).Value()->name, "Empty"); + EXPECT_EQ(hint, 2u); + + // Invalid searches + EXPECT_EQ(tree.Find<ByEndpoint>(12345, hint).Value(), nullptr); + EXPECT_EQ(tree.Find<ByEndpoint>(0, hint).Value(), nullptr); + } + + // searches for "next" + { + unsigned hint = 0; + auto next = tree.Next<ByEndpoint>(123, hint); + + ASSERT_NE(next.Value(), nullptr); + EXPECT_EQ(hint, 1u); + EXPECT_EQ(next.Value()->id, 456u); + EXPECT_STREQ(next.Value()->name, "bar"); + + next = tree.Next<ByEndpoint>(456, hint); + ASSERT_NE(next.Value(), nullptr); + EXPECT_EQ(hint, 2u); + EXPECT_EQ(next.Value()->id, 1000u); + EXPECT_STREQ(next.Value()->name, "Empty"); + + /// search at the end + next = tree.Next<ByEndpoint>(1000, hint); + EXPECT_EQ(next.Value(), nullptr); + + // null value preserves the failure + unsigned clusterHint = 0; + auto sub_item = next.Find<ByServerCluster>(123, clusterHint); + EXPECT_EQ(sub_item.Value(), nullptr); + } +} diff --git a/src/platform/DeviceInfoProvider.cpp b/src/platform/DeviceInfoProvider.cpp index 92ad84d86d49b8..28191cd4f82352 100644 --- a/src/platform/DeviceInfoProvider.cpp +++ b/src/platform/DeviceInfoProvider.cpp @@ -82,11 +82,16 @@ CHIP_ERROR DeviceInfoProvider::AppendUserLabel(EndpointId endpoint, const UserLa { size_t length; - // Increase the size of UserLabelList by 1 + // Fetch current list length ReturnErrorOnFailure(GetUserLabelLength(endpoint, length)); - ReturnErrorOnFailure(SetUserLabelLength(endpoint, length + 1)); - // Append the user label at the end of UserLabelList + if (length >= kMaxUserLabelListLength) + { + return CHIP_ERROR_NO_MEMORY; + } + + // Add the new entry to the list + ReturnErrorOnFailure(SetUserLabelLength(endpoint, length + 1)); ReturnErrorOnFailure(SetUserLabelAt(endpoint, length, label)); return CHIP_NO_ERROR; diff --git a/src/platform/Zephyr/BLEManagerImpl.cpp b/src/platform/Zephyr/BLEManagerImpl.cpp index 49751da62479e3..6b8ba4b6989ce6 100644 --- a/src/platform/Zephyr/BLEManagerImpl.cpp +++ b/src/platform/Zephyr/BLEManagerImpl.cpp @@ -284,6 +284,13 @@ struct BLEManagerImpl::ServiceData inline CHIP_ERROR BLEManagerImpl::PrepareAdvertisingRequest() { +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA + if (mCustomAdvertising.empty()) + { + ChipLogError(DeviceLayer, "mCustomAdvertising should be set when CONFIG_CHIP_CUSTOM_BLE_ADV_DATA is define"); + return CHIP_ERROR_INTERNAL; + } +#else static ServiceData serviceData; static std::array<bt_data, 2> advertisingData; static std::array<bt_data, 1> scanResponseData; @@ -304,9 +311,10 @@ inline CHIP_ERROR BLEManagerImpl::PrepareAdvertisingRequest() } #endif - advertisingData[0] = BT_DATA(BT_DATA_FLAGS, &kAdvertisingFlags, sizeof(kAdvertisingFlags)); - advertisingData[1] = BT_DATA(BT_DATA_SVC_DATA16, &serviceData, sizeof(serviceData)); - scanResponseData[0] = BT_DATA(BT_DATA_NAME_COMPLETE, name, nameSize); + advertisingData[0] = BT_DATA(BT_DATA_FLAGS, &kAdvertisingFlags, sizeof(kAdvertisingFlags)); + advertisingData[1] = BT_DATA(BT_DATA_SVC_DATA16, &serviceData, sizeof(serviceData)); + scanResponseData[0] = BT_DATA(BT_DATA_NAME_COMPLETE, name, nameSize); +#endif // CONFIG_CHIP_CUSTOM_BLE_ADV_DATA mAdvertisingRequest.priority = CHIP_DEVICE_BLE_ADVERTISING_PRIORITY; mAdvertisingRequest.options = kAdvertisingOptions; @@ -328,9 +336,13 @@ inline CHIP_ERROR BLEManagerImpl::PrepareAdvertisingRequest() mAdvertisingRequest.minInterval = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN; mAdvertisingRequest.maxInterval = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX; } +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA + mAdvertisingRequest.advertisingData = mCustomAdvertising; + mAdvertisingRequest.scanResponseData = mCustomScanResponse; +#else mAdvertisingRequest.advertisingData = Span<bt_data>(advertisingData); mAdvertisingRequest.scanResponseData = nameSize ? Span<bt_data>(scanResponseData) : Span<bt_data>{}; - +#endif mAdvertisingRequest.onStarted = [](int rc) { if (rc == 0) { @@ -967,6 +979,17 @@ ssize_t BLEManagerImpl::HandleC3Read(struct bt_conn * conId, const struct bt_gat } #endif +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA +void BLEManagerImpl::SetCustomAdvertising(Span<bt_data> CustomAdvertising) +{ + mCustomAdvertising = CustomAdvertising; +} +void BLEManagerImpl::SetCustomScanResponse(Span<bt_data> CustomScanResponse) +{ + mCustomScanResponse = CustomScanResponse; +} +#endif + } // namespace Internal } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/Zephyr/BLEManagerImpl.h b/src/platform/Zephyr/BLEManagerImpl.h index 8c09ed457f94b2..9e83dc47ed6ae6 100644 --- a/src/platform/Zephyr/BLEManagerImpl.h +++ b/src/platform/Zephyr/BLEManagerImpl.h @@ -105,6 +105,10 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla #endif // The summarized number of Bluetooth LE connections related to the device (including these not related to Matter service). uint16_t mTotalConnNum; +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA + Span<bt_data> mCustomAdvertising = {}; + Span<bt_data> mCustomScanResponse = {}; +#endif void DriveBLEState(void); CHIP_ERROR PrepareAdvertisingRequest(); @@ -150,6 +154,10 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla #if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING static ssize_t HandleC3Read(struct bt_conn * conn, const struct bt_gatt_attr * attr, void * buf, uint16_t len, uint16_t offset); #endif +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA + void SetCustomAdvertising(Span<bt_data> CustomAdvertising); + void SetCustomScanResponse(Span<bt_data> CustomScanResponse); +#endif }; /** diff --git a/src/platform/cc32xx/args.gni b/src/platform/cc32xx/args.gni index 288aa5a1edc188..d819c03536e330 100755 --- a/src/platform/cc32xx/args.gni +++ b/src/platform/cc32xx/args.gni @@ -34,3 +34,6 @@ chip_inet_config_enable_ipv4 = true chip_inet_config_enable_dns_resolver = false chip_build_tests = false + +# small binaries even in CI +optimize_debug_level = "s" diff --git a/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h b/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h index 5e5fd2b14d5fea..79ceb200dbe1c5 100644 --- a/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h +++ b/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h @@ -85,7 +85,8 @@ #ifndef CHIP_DEVICE_BLE_ADVERTISING_PRIORITY /// Priority of the Matter BLE advertising when there are multiple application /// components that compete for the BLE advertising. -#define CHIP_DEVICE_BLE_ADVERTISING_PRIORITY 0 +/// Increase priority to 1 to allow user to insert custom advertising data with higher priority (0) +#define CHIP_DEVICE_BLE_ADVERTISING_PRIORITY 1 #endif // CHIP_DEVICE_BLE_ADVERTISING_PRIORITY // ========== Platform-specific Configuration ========= diff --git a/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.cpp b/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.cpp index ee6b91da3f9c7e..f66b98317e27e3 100644 --- a/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.cpp +++ b/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.cpp @@ -29,6 +29,9 @@ namespace { // List of advertising requests ordered by priority sys_slist_t sRequests; +bool sIsInitialized = false; +uint8_t sBtId = 0; + // Cast an intrusive list node to the containing request object const BLEAdvertisingArbiter::Request & ToRequest(const sys_snode_t * node) { @@ -55,8 +58,9 @@ CHIP_ERROR RestartAdvertising() ReturnErrorOnFailure(MapErrorZephyr(bt_le_adv_stop())); VerifyOrReturnError(!sys_slist_is_empty(&sRequests), CHIP_NO_ERROR); - const Request & top = ToRequest(sys_slist_peek_head(&sRequests)); - const bt_le_adv_param params = BT_LE_ADV_PARAM_INIT(top.options, top.minInterval, top.maxInterval, nullptr); + const Request & top = ToRequest(sys_slist_peek_head(&sRequests)); + bt_le_adv_param params = BT_LE_ADV_PARAM_INIT(top.options, top.minInterval, top.maxInterval, nullptr); + params.id = sBtId; const int result = bt_le_adv_start(¶ms, top.advertisingData.data(), top.advertisingData.size(), top.scanResponseData.data(), top.scanResponseData.size()); @@ -70,8 +74,26 @@ CHIP_ERROR RestartAdvertising() } // namespace +CHIP_ERROR Init(uint8_t btId) +{ + if (sIsInitialized) + { + return CHIP_ERROR_INCORRECT_STATE; + } + + sBtId = btId; + sIsInitialized = true; + + return CHIP_NO_ERROR; +} + CHIP_ERROR InsertRequest(Request & request) { + if (!sIsInitialized) + { + return CHIP_ERROR_INCORRECT_STATE; + } + CancelRequest(request); sys_snode_t * prev = nullptr; @@ -109,6 +131,11 @@ CHIP_ERROR InsertRequest(Request & request) void CancelRequest(Request & request) { + if (!sIsInitialized) + { + return; + } + const bool isTopPriority = (sys_slist_peek_head(&sRequests) == &request); VerifyOrReturn(sys_slist_find_and_remove(&sRequests, &request)); diff --git a/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.h b/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.h index 11a90c7070cd0a..0204a406244eab 100644 --- a/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.h +++ b/src/platform/nxp/common/ble_zephyr/BLEAdvertisingArbiter.h @@ -62,6 +62,18 @@ struct Request : public sys_snode_t OnAdvertisingStopped onStopped; ///< (Optional) Callback invoked when the request stops being top-priority. }; +/** + * @brief Initialize BLE advertising arbiter + * + * @note This method must be called before trying to insert or cancel any requests. + * + * @param btId Local Bluetooth LE identifier to be used for the advertising parameters. Currently Bluetooth LE identifier used in + * this method will be used for all advertising requests and changing it dynamically is not supported. + * @return error If the module is already initialized. + * @return success Otherwise. + */ +CHIP_ERROR Init(uint8_t btId); + /** * @brief Request BLE advertising * @@ -75,6 +87,9 @@ struct Request : public sys_snode_t * @note This method does not take ownership of the request object so the object * must not get destroyed before it is cancelled. * + * @note The arbiter module has to be initialized using Init() method before + * invoking this method. + * * @param request Reference to advertising request that contains priority and * other advertising parameters. * @return error If the request is top-priority and failed to restart the @@ -95,6 +110,9 @@ CHIP_ERROR InsertRequest(Request & request); * An attempt to cancel a request that has not been registered at the * advertising arbiter is a no-op. That is, it returns immediately. * + * @note The arbiter module has to be initialized using Init() method before + * invoking this method. + * * @param request Reference to advertising request that contains priority and * other advertising parameters. */ diff --git a/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.cpp b/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.cpp index 0d1c4c0dcb8932..aca08a9339b243 100644 --- a/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.cpp +++ b/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.cpp @@ -27,9 +27,10 @@ #include "BLEManagerImpl.h" -#include <ble/CHIPBleServiceData.h> +#include <ble/Ble.h> #include <lib/support/CHIPMemString.h> #include <lib/support/CodeUtils.h> +#include <lib/support/SafeInt.h> #include <lib/support/logging/CHIPLogging.h> #include <platform/DeviceInstanceInfoProvider.h> #include <platform/internal/BLEManager.h> @@ -44,6 +45,10 @@ #include <zephyr/sys/byteorder.h> #include <zephyr/sys/util.h> +#ifdef CONFIG_BT_BONDABLE +#include <zephyr/settings/settings.h> +#endif // CONFIG_BT_BONDABLE + #include <array> using namespace ::chip; @@ -70,12 +75,6 @@ const bt_uuid_128 UUID128_CHIPoBLEChar_C3 = bt_uuid_16 UUID16_CHIPoBLEService = BT_UUID_INIT_16(0xFFF6); -const ChipBleUUID chipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, - 0x9D, 0x11 } }; - -const ChipBleUUID chipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, - 0x9D, 0x12 } }; - _bt_gatt_ccc CHIPoBLEChar_TX_CCC = BT_GATT_CCC_INITIALIZER(nullptr, BLEManagerImpl::HandleTXCCCWrite, nullptr); // clang-format off @@ -107,7 +106,13 @@ bt_gatt_service sChipoBleService = BT_GATT_SERVICE(sChipoBleAttributes); // This value should be adjusted accordingly if the service declaration changes. constexpr int kCHIPoBLE_CCC_AttributeIndex = 3; -CHIP_ERROR InitRandomStaticAddress() +#ifdef CONFIG_BT_BONDABLE +constexpr uint8_t kMatterBleIdentity = 1; +#else +constexpr uint8_t kMatterBleIdentity = 0; +#endif // CONFIG_BT_BONDABLE + +int InitRandomStaticAddress(bool idPresent, int & id) { // Generate a random static address for the default identity. // This must be done before bt_enable() as after that updating the default identity is not possible. @@ -122,20 +127,29 @@ CHIP_ERROR InitRandomStaticAddress() if (error) { ChipLogError(DeviceLayer, "Failed to create BLE address: %d", error); - return MapErrorZephyr(error); + return error; } - error = bt_id_create(&addr, nullptr); + if (!idPresent) + { + id = bt_id_create(&addr, nullptr); + } +#if CONFIG_BT_ID_MAX == 2 + else + { + id = bt_id_reset(1, &addr, nullptr); + } +#endif // CONFIG_BT_BONDABLE - if (error < 0) + if (id < 0) { ChipLogError(DeviceLayer, "Failed to create BLE identity: %d", error); - return MapErrorZephyr(error); + return id; } ChipLogProgress(DeviceLayer, "BLE address: %02X:%02X:%02X:%02X:%02X:%02X", addr.a.val[5], addr.a.val[4], addr.a.val[3], addr.a.val[2], addr.a.val[1], addr.a.val[0]); - return CHIP_NO_ERROR; + return 0; } } // unnamed namespace @@ -144,16 +158,41 @@ BLEManagerImpl BLEManagerImpl::sInstance; CHIP_ERROR BLEManagerImpl::_Init() { + int err = 0; + int id = 0; + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled; mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART); mFlags.Set(Flags::kFastAdvertisingEnabled, true); - mGAPConns = 0; + mMatterConnNum = 0; + mTotalConnNum = 0; memset(mSubscribedConns, 0, sizeof(mSubscribedConns)); - ReturnErrorOnFailure(InitRandomStaticAddress()); - int err = bt_enable(NULL); +#ifdef CONFIG_BT_BONDABLE + bt_addr_le_t idsAddr[CONFIG_BT_ID_MAX]; + size_t idsCount = CONFIG_BT_ID_MAX; + + err = bt_enable(nullptr); + + VerifyOrReturnError(err == 0, MapErrorZephyr(err)); + + settings_load(); + + bt_id_get(idsAddr, &idsCount); + + err = InitRandomStaticAddress(idsCount > 1, id); + + VerifyOrReturnError(err == 0 && id == kMatterBleIdentity, MapErrorZephyr(err)); + +#else + err = InitRandomStaticAddress(false, id); + VerifyOrReturnError(err == 0 && id == kMatterBleIdentity, MapErrorZephyr(err)); + err = bt_enable(nullptr); VerifyOrReturnError(err == 0, MapErrorZephyr(err)); +#endif // CONFIG_BT_BONDABLE + + BLEAdvertisingArbiter::Init(static_cast<uint8_t>(id)); memset(&mConnCallbacks, 0, sizeof(mConnCallbacks)); mConnCallbacks.connected = HandleConnect; @@ -199,7 +238,13 @@ void BLEManagerImpl::DriveBLEState() { mFlags.Clear(Flags::kAdvertisingRefreshNeeded); err = StartAdvertising(); - SuccessOrExit(err); + if (err != CHIP_NO_ERROR) + { + // Return prematurely but keep the CHIPoBLE service mode enabled to allow advertising retries + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled; + ChipLogError(DeviceLayer, "Could not start CHIPoBLE service due to error: %" CHIP_ERROR_FORMAT, err.Format()); + return; + } } } else @@ -207,7 +252,12 @@ void BLEManagerImpl::DriveBLEState() if (mFlags.Has(Flags::kAdvertising)) { err = StopAdvertising(); - SuccessOrExit(err); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %" CHIP_ERROR_FORMAT, err.Format()); + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled; + return; + } } // If no connections are active unregister also CHIPoBLE GATT service @@ -224,13 +274,6 @@ void BLEManagerImpl::DriveBLEState() } } } - -exit: - if (err != CHIP_NO_ERROR) - { - ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %" CHIP_ERROR_FORMAT, err.Format()); - mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled; - } } struct BLEManagerImpl::ServiceData @@ -241,6 +284,13 @@ struct BLEManagerImpl::ServiceData inline CHIP_ERROR BLEManagerImpl::PrepareAdvertisingRequest() { +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA + if (mCustomAdvertising.empty()) + { + ChipLogError(DeviceLayer, "mCustomAdvertising should be set when CONFIG_CHIP_CUSTOM_BLE_ADV_DATA is define"); + return CHIP_ERROR_INTERNAL; + } +#else static ServiceData serviceData; static std::array<bt_data, 2> advertisingData; static std::array<bt_data, 1> scanResponseData; @@ -252,21 +302,47 @@ inline CHIP_ERROR BLEManagerImpl::PrepareAdvertisingRequest() Encoding::LittleEndian::Put16(serviceData.uuid, UUID16_CHIPoBLEService.val); ReturnErrorOnFailure(ConfigurationMgr().GetBLEDeviceIdentificationInfo(serviceData.deviceIdInfo)); - advertisingData[0] = BT_DATA(BT_DATA_FLAGS, &kAdvertisingFlags, sizeof(kAdvertisingFlags)); - advertisingData[1] = BT_DATA(BT_DATA_SVC_DATA16, &serviceData, sizeof(serviceData)); - scanResponseData[0] = BT_DATA(BT_DATA_NAME_COMPLETE, name, nameSize); - - mAdvertisingRequest.priority = CHIP_DEVICE_BLE_ADVERTISING_PRIORITY; - mAdvertisingRequest.options = kAdvertisingOptions; - mAdvertisingRequest.minInterval = mFlags.Has(Flags::kFastAdvertisingEnabled) - ? CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN - : CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN; - mAdvertisingRequest.maxInterval = mFlags.Has(Flags::kFastAdvertisingEnabled) - ? CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX - : CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX; +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING + if (mFlags.Has(Flags::kExtendedAdvertisingEnabled)) + { + serviceData.deviceIdInfo.SetVendorId(DEVICE_HANDLE_NULL); + serviceData.deviceIdInfo.SetProductId(DEVICE_HANDLE_NULL); + serviceData.deviceIdInfo.SetExtendedAnnouncementFlag(true); + } +#endif + + advertisingData[0] = BT_DATA(BT_DATA_FLAGS, &kAdvertisingFlags, sizeof(kAdvertisingFlags)); + advertisingData[1] = BT_DATA(BT_DATA_SVC_DATA16, &serviceData, sizeof(serviceData)); + scanResponseData[0] = BT_DATA(BT_DATA_NAME_COMPLETE, name, nameSize); +#endif + + mAdvertisingRequest.priority = CHIP_DEVICE_BLE_ADVERTISING_PRIORITY; + mAdvertisingRequest.options = kAdvertisingOptions; + + if (mFlags.Has(Flags::kFastAdvertisingEnabled)) + { + mAdvertisingRequest.minInterval = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN; + mAdvertisingRequest.maxInterval = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX; + } +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING + else if (mFlags.Has(Flags::kExtendedAdvertisingEnabled)) + { + mAdvertisingRequest.minInterval = CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN; + mAdvertisingRequest.maxInterval = CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MAX; + } +#endif + else + { + mAdvertisingRequest.minInterval = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN; + mAdvertisingRequest.maxInterval = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX; + } +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA + mAdvertisingRequest.advertisingData = mCustomAdvertising; + mAdvertisingRequest.scanResponseData = mCustomScanResponse; +#else mAdvertisingRequest.advertisingData = Span<bt_data>(advertisingData); mAdvertisingRequest.scanResponseData = nameSize ? Span<bt_data>(scanResponseData) : Span<bt_data>{}; - +#endif mAdvertisingRequest.onStarted = [](int rc) { if (rc == 0) { @@ -275,29 +351,53 @@ inline CHIP_ERROR BLEManagerImpl::PrepareAdvertisingRequest() else { ChipLogError(DeviceLayer, "Failed to start CHIPoBLE advertising: %d", rc); + BLEManagerImpl().StopAdvertising(); } }; return CHIP_NO_ERROR; } -CHIP_ERROR BLEManagerImpl::StartAdvertising() +CHIP_ERROR BLEManagerImpl::RegisterGattService() { - // Prepare advertising request - ReturnErrorOnFailure(PrepareAdvertisingRequest()); - - // Register dynamically CHIPoBLE GATT service + // Register CHIPoBLE GATT service if (!mFlags.Has(Flags::kChipoBleGattServiceRegister)) { int err = bt_gatt_service_register(&sChipoBleService); - if (err != 0) - ChipLogError(DeviceLayer, "Failed to register CHIPoBLE GATT service"); + { + ChipLogError(DeviceLayer, "Failed to register CHIPoBLE GATT service: %d", err); + } VerifyOrReturnError(err == 0, MapErrorZephyr(err)); - mFlags.Set(Flags::kChipoBleGattServiceRegister); } + return CHIP_NO_ERROR; +} + +CHIP_ERROR BLEManagerImpl::UnregisterGattService() +{ + // Unregister CHIPoBLE GATT service + if (mFlags.Has(Flags::kChipoBleGattServiceRegister)) + { + int err = bt_gatt_service_unregister(&sChipoBleService); + if (err != 0) + { + ChipLogError(DeviceLayer, "Failed to unregister CHIPoBLE GATT service: %d", err); + } + + VerifyOrReturnError(err == 0, MapErrorZephyr(err)); + mFlags.Clear(Flags::kChipoBleGattServiceRegister); + } + return CHIP_NO_ERROR; +} + +CHIP_ERROR BLEManagerImpl::StartAdvertising() +{ + // Prepare advertising request + ReturnErrorOnFailure(PrepareAdvertisingRequest()); + // We need to register GATT service before issuing the advertising to start + ReturnErrorOnFailure(RegisterGattService()); // Initialize C3 characteristic data #if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING @@ -305,7 +405,13 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising() #endif // Request advertising - ReturnErrorOnFailure(BLEAdvertisingArbiter::InsertRequest(mAdvertisingRequest)); + CHIP_ERROR err = BLEAdvertisingArbiter::InsertRequest(mAdvertisingRequest); + if (CHIP_NO_ERROR != err) + { + // It makes not sense to keep GATT services registered after the advertising request failed + (void) UnregisterGattService(); + return err; + } // Transition to the Advertising state... if (!mFlags.Has(Flags::kAdvertising)) @@ -322,10 +428,17 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising() if (mFlags.Has(Flags::kFastAdvertisingEnabled)) { - // Start timer to change advertising interval. + // Start timer to change advertising interval from fast to slow. DeviceLayer::SystemLayer().StartTimer( System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME), - HandleBLEAdvertisementIntervalChange, this); + HandleSlowBLEAdvertisementInterval, this); + +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING + // Start timer to schedule start of the extended advertising + DeviceLayer::SystemLayer().StartTimer( + System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_CHANGE_TIME_MS), + HandleExtendedBLEAdvertisementInterval, this); +#endif } } @@ -342,6 +455,10 @@ CHIP_ERROR BLEManagerImpl::StopAdvertising() mFlags.Clear(Flags::kAdvertising); mFlags.Set(Flags::kFastAdvertisingEnabled, true); +#if CHIP_DEVICE_CONFIG_EXT_ADVERTISING + mFlags.Clear(Flags::kExtendedAdvertisingEnabled); +#endif + ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped"); // Post a CHIPoBLEAdvertisingChange(Stopped) event. @@ -353,7 +470,12 @@ CHIP_ERROR BLEManagerImpl::StopAdvertising() } // Cancel timer event changing CHIPoBLE advertisement interval - DeviceLayer::SystemLayer().CancelTimer(HandleBLEAdvertisementIntervalChange, this); + DeviceLayer::SystemLayer().CancelTimer(HandleSlowBLEAdvertisementInterval, this); + DeviceLayer::SystemLayer().CancelTimer(HandleExtendedBLEAdvertisementInterval, this); + } + else + { + ChipLogProgress(DeviceLayer, "CHIPoBLE advertising already stopped"); } return CHIP_NO_ERROR; @@ -361,13 +483,13 @@ CHIP_ERROR BLEManagerImpl::StopAdvertising() CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val) { - if (mFlags.Has(Flags::kAdvertisingEnabled) != val) - { - ChipLogDetail(DeviceLayer, "CHIPoBLE advertising set to %s", val ? "on" : "off"); + ChipLogDetail(DeviceLayer, "CHIPoBLE advertising set to %s", val ? "on" : "off"); - mFlags.Set(Flags::kAdvertisingEnabled, val); - PlatformMgr().ScheduleWork(DriveBLEState, 0); - } + mFlags.Set(Flags::kAdvertisingEnabled, val); + // Ensure that each enabling/disabling of the general advertising clears + // the extended mode, to make sure we always start fresh in the regular mode + mFlags.Set(Flags::kExtendedAdvertisingEnabled, false); + PlatformMgr().ScheduleWork(DriveBLEState, 0); return CHIP_NO_ERROR; } @@ -378,8 +500,14 @@ CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode) { case BLEAdvertisingMode::kFastAdvertising: mFlags.Set(Flags::kFastAdvertisingEnabled, true); + mFlags.Set(Flags::kExtendedAdvertisingEnabled, false); break; case BLEAdvertisingMode::kSlowAdvertising: + mFlags.Set(Flags::kFastAdvertisingEnabled, false); + mFlags.Set(Flags::kExtendedAdvertisingEnabled, false); + break; + case BLEAdvertisingMode::kExtendedAdvertising: + mFlags.Set(Flags::kExtendedAdvertisingEnabled, true); mFlags.Set(Flags::kFastAdvertisingEnabled, false); break; default: @@ -410,15 +538,13 @@ CHIP_ERROR BLEManagerImpl::HandleGAPConnect(const ChipDeviceEvent * event) if (connEvent->HciResult == BT_HCI_ERR_SUCCESS) { ChipLogProgress(DeviceLayer, "BLE connection established (ConnId: 0x%02x)", bt_conn_index(connEvent->BtConn)); - mGAPConns++; + mMatterConnNum++; } else { ChipLogError(DeviceLayer, "BLE connection failed (reason: 0x%02x)", connEvent->HciResult); } - ChipLogProgress(DeviceLayer, "Current number of connections: %u/%u", NumConnections(), CONFIG_BT_MAX_CONN); - mFlags.Set(Flags::kAdvertisingRefreshNeeded); PlatformMgr().ScheduleWork(DriveBLEState, 0); @@ -433,7 +559,10 @@ CHIP_ERROR BLEManagerImpl::HandleGAPDisconnect(const ChipDeviceEvent * event) ChipLogProgress(DeviceLayer, "BLE GAP connection terminated (reason 0x%02x)", connEvent->HciResult); - mGAPConns--; + if (mMatterConnNum > 0) + { + mMatterConnNum--; + } // If indications were enabled for this connection, record that they are now disabled and // notify the BLE Layer of a disconnect. @@ -461,8 +590,6 @@ CHIP_ERROR BLEManagerImpl::HandleGAPDisconnect(const ChipDeviceEvent * event) // Unref bt_conn before scheduling DriveBLEState. bt_conn_unref(connEvent->BtConn); - ChipLogProgress(DeviceLayer, "Current number of connections: %u/%u", NumConnections(), CONFIG_BT_MAX_CONN); - ChipDeviceEvent disconnectEvent; disconnectEvent.Type = DeviceEventType::kCHIPoBLEConnectionClosed; ReturnErrorOnFailure(PlatformMgr().PostEvent(&disconnectEvent)); @@ -485,7 +612,7 @@ CHIP_ERROR BLEManagerImpl::HandleTXCharCCCDWrite(const ChipDeviceEvent * event) if (writeEvent->Value == BT_GATT_CCC_INDICATE && SetSubscribed(writeEvent->BtConn)) { // Alert the BLE layer that CHIPoBLE "subscribe" has been received and increment the bt_conn reference counter. - HandleSubscribeReceived(writeEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX); + HandleSubscribeReceived(writeEvent->BtConn, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_2_UUID); ChipLogProgress(DeviceLayer, "CHIPoBLE connection established (ConnId: 0x%02x, GATT MTU: %u)", bt_conn_index(writeEvent->BtConn), GetMTU(writeEvent->BtConn)); @@ -501,7 +628,7 @@ CHIP_ERROR BLEManagerImpl::HandleTXCharCCCDWrite(const ChipDeviceEvent * event) { if (UnsetSubscribed(writeEvent->BtConn)) { - HandleUnsubscribeReceived(writeEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX); + HandleUnsubscribeReceived(writeEvent->BtConn, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_2_UUID); } } @@ -517,7 +644,7 @@ CHIP_ERROR BLEManagerImpl::HandleRXCharWrite(const ChipDeviceEvent * event) ChipLogDetail(DeviceLayer, "Write request received for CHIPoBLE RX characteristic (ConnId 0x%02x)", bt_conn_index(c1WriteEvent->BtConn)); - HandleWriteReceived(c1WriteEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_RX, + HandleWriteReceived(c1WriteEvent->BtConn, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_1_UUID, PacketBufferHandle::Adopt(c1WriteEvent->Data)); bt_conn_unref(c1WriteEvent->BtConn); @@ -532,7 +659,7 @@ CHIP_ERROR BLEManagerImpl::HandleTXCharComplete(const ChipDeviceEvent * event) bt_conn_index(c2IndDoneEvent->BtConn), c2IndDoneEvent->Result); // Signal the BLE Layer that the outstanding indication is complete. - HandleIndicationConfirmation(c2IndDoneEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX); + HandleIndicationConfirmation(c2IndDoneEvent->BtConn, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_2_UUID); bt_conn_unref(c2IndDoneEvent->BtConn); return CHIP_NO_ERROR; @@ -570,12 +697,18 @@ CHIP_ERROR BLEManagerImpl::PrepareC3CharData() } #endif -void BLEManagerImpl::HandleBLEAdvertisementIntervalChange(System::Layer * layer, void * param) +void BLEManagerImpl::HandleSlowBLEAdvertisementInterval(System::Layer * layer, void * param) { BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising); ChipLogProgress(DeviceLayer, "CHIPoBLE advertising mode changed to slow"); } +void BLEManagerImpl::HandleExtendedBLEAdvertisementInterval(System::Layer * layer, void * param) +{ + BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kExtendedAdvertising); + ChipLogProgress(DeviceLayer, "CHIPoBLE advertising mode changed to extended"); +} + void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -616,14 +749,13 @@ void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) uint16_t BLEManagerImpl::_NumConnections(void) { - return mGAPConns; + return mMatterConnNum; } CHIP_ERROR BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId) { ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (ConnId %02x)", bt_conn_index(conId)); - int status = bt_conn_disconnect(conId, BT_HCI_ERR_REMOTE_USER_TERM_CONN); - return (status == 0) ? CHIP_NO_ERROR : MapErrorZephyr(status); + return MapErrorZephyr(bt_conn_disconnect(conId, BT_HCI_ERR_REMOTE_USER_TERM_CONN)); } uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const @@ -662,7 +794,8 @@ CHIP_ERROR BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const Chi params->attr = &sChipoBleAttributes[kCHIPoBLE_CCC_AttributeIndex]; params->func = HandleTXIndicated; params->data = pBuf->Start(); - params->len = pBuf->DataLength(); + VerifyOrExit(CanCastTo<uint16_t>(pBuf->DataLength()), err = CHIP_ERROR_MESSAGE_TOO_LONG); + params->len = static_cast<uint16_t>(pBuf->DataLength()); status = bt_gatt_indicate(conId, params); VerifyOrExit(status == 0, err = MapErrorZephyr(status)); @@ -775,9 +908,16 @@ void BLEManagerImpl::HandleTXIndicated(struct bt_conn * conId, bt_gatt_indicate_ void BLEManagerImpl::HandleConnect(struct bt_conn * conId, uint8_t err) { ChipDeviceEvent event; + bt_conn_info bt_info; PlatformMgr().LockChipStack(); + sInstance.mTotalConnNum++; + ChipLogProgress(DeviceLayer, "Current number of connections: %u/%u", sInstance.mTotalConnNum, CONFIG_BT_MAX_CONN); + + VerifyOrExit(bt_conn_get_info(conId, &bt_info) == 0, ); + // Drop all callbacks incoming for the role other than peripheral, required by the Matter accessory + VerifyOrExit(bt_info.role == BT_CONN_ROLE_PERIPHERAL, ); // Don't handle BLE connecting events when it is not related to CHIPoBLE VerifyOrExit(sInstance.mFlags.Has(Flags::kChipoBleGattServiceRegister), ); @@ -794,9 +934,20 @@ void BLEManagerImpl::HandleConnect(struct bt_conn * conId, uint8_t err) void BLEManagerImpl::HandleDisconnect(struct bt_conn * conId, uint8_t reason) { ChipDeviceEvent event; + bt_conn_info bt_info; PlatformMgr().LockChipStack(); + if (sInstance.mTotalConnNum > 0) + { + sInstance.mTotalConnNum--; + } + + ChipLogProgress(DeviceLayer, "Current number of connections: %u/%u", sInstance.mTotalConnNum, CONFIG_BT_MAX_CONN); + + VerifyOrExit(bt_conn_get_info(conId, &bt_info) == 0, ); + // Drop all callbacks incoming for the role other than peripheral, required by the Matter accessory + VerifyOrExit(bt_info.role == BT_CONN_ROLE_PERIPHERAL, ); // Don't handle BLE disconnecting events when it is not related to CHIPoBLE VerifyOrExit(sInstance.mFlags.Has(Flags::kChipoBleGattServiceRegister), ); @@ -821,8 +972,21 @@ ssize_t BLEManagerImpl::HandleC3Read(struct bt_conn * conId, const struct bt_gat return 0; } + // For BLE, the max payload size is limited to UINT16_MAX since the length + // field is 2 bytes long. So, the cast to uint16_t should be fine. return bt_gatt_attr_read(conId, attr, buf, len, offset, sInstance.c3CharDataBufferHandle->Start(), - sInstance.c3CharDataBufferHandle->DataLength()); + static_cast<uint16_t>(sInstance.c3CharDataBufferHandle->DataLength())); +} +#endif + +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA +void BLEManagerImpl::SetCustomAdvertising(Span<bt_data> CustomAdvertising) +{ + mCustomAdvertising = CustomAdvertising; +} +void BLEManagerImpl::SetCustomScanResponse(Span<bt_data> CustomScanResponse) +{ + mCustomScanResponse = CustomScanResponse; } #endif diff --git a/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.h b/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.h index 4ae142b65cb6c0..db00009a938cea 100644 --- a/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.h +++ b/src/platform/nxp/common/ble_zephyr/BLEManagerImpl.h @@ -92,12 +92,13 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla kAdvertisingRefreshNeeded = 0x0010, /**< The advertising state/configuration has changed, but the SoftDevice has yet to be updated. */ kChipoBleGattServiceRegister = 0x0020, /**< The system has currently CHIPoBLE GATT service registered. */ + kExtendedAdvertisingEnabled = 0x0040, /**< The application has enabled extended advertising. */ }; struct ServiceData; BitFlags<Flags> mFlags; - uint16_t mGAPConns; + uint16_t mMatterConnNum; CHIPoBLEServiceMode mServiceMode; bool mSubscribedConns[CONFIG_BT_MAX_CONN]; bt_gatt_indicate_params mIndicateParams[CONFIG_BT_MAX_CONN]; @@ -106,6 +107,12 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla #if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING PacketBufferHandle c3CharDataBufferHandle; #endif + // The summarized number of Bluetooth LE connections related to the device (including these not related to Matter service). + uint16_t mTotalConnNum; +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA + Span<bt_data> mCustomAdvertising = {}; + Span<bt_data> mCustomScanResponse = {}; +#endif void DriveBLEState(void); CHIP_ERROR PrepareAdvertisingRequest(); @@ -123,6 +130,8 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla bool SetSubscribed(bt_conn * conn); bool UnsetSubscribed(bt_conn * conn); uint32_t GetAdvertisingInterval(); + CHIP_ERROR RegisterGattService(); + CHIP_ERROR UnregisterGattService(); static void DriveBLEState(intptr_t arg); @@ -130,7 +139,8 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla static void HandleTXIndicated(bt_conn * conn, bt_gatt_indicate_params * attr, uint8_t err); static void HandleConnect(bt_conn * conn, uint8_t err); static void HandleDisconnect(bt_conn * conn, uint8_t reason); - static void HandleBLEAdvertisementIntervalChange(System::Layer * layer, void * param); + static void HandleSlowBLEAdvertisementInterval(System::Layer * layer, void * param); + static void HandleExtendedBLEAdvertisementInterval(System::Layer * layer, void * param); // ===== Members for internal use by the following friends. @@ -148,6 +158,10 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla #if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING static ssize_t HandleC3Read(struct bt_conn * conn, const struct bt_gatt_attr * attr, void * buf, uint16_t len, uint16_t offset); #endif +#ifdef CONFIG_CHIP_CUSTOM_BLE_ADV_DATA + void SetCustomAdvertising(Span<bt_data> CustomAdvertising); + void SetCustomScanResponse(Span<bt_data> CustomScanResponse); +#endif }; /** diff --git a/src/python_testing/TC_OpstateCommon.py b/src/python_testing/TC_OpstateCommon.py index 557b7606ccbea3..1a4cfbe7150e30 100644 --- a/src/python_testing/TC_OpstateCommon.py +++ b/src/python_testing/TC_OpstateCommon.py @@ -210,8 +210,8 @@ def STEPS_TC_OPSTATE_BASE_1_1(self) -> list[TestStep]: async def TEST_TC_OPSTATE_BASE_1_1(self, endpoint=1, cluster_revision=1, feature_map=0): cluster = self.test_info.cluster attributes = cluster.Attributes - events = cluster.Events commands = cluster.Commands + events = cluster.Events self.init_test() @@ -245,7 +245,7 @@ async def TEST_TC_OPSTATE_BASE_1_1(self, endpoint=1, cluster_revision=1, feature attributes.ClusterRevision.attribute_id ] - if self.check_pics(f"{self.test_info.pics_code}.S.A0002"): + if await self.attribute_guard(endpoint=endpoint, attribute=attributes.CountdownTime): expected_value.append(attributes.CountdownTime.attribute_id) await self.read_and_expect_array_contains(endpoint=endpoint, @@ -259,7 +259,7 @@ async def TEST_TC_OPSTATE_BASE_1_1(self, endpoint=1, cluster_revision=1, feature events.OperationalError.event_id, ] - if self.check_pics(f"{self.test_info.pics_code}.S.E01"): + if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.E01")): expected_value.append(events.OperationCompletion.event_id) await self.read_and_expect_array_contains(endpoint=endpoint, @@ -270,19 +270,19 @@ async def TEST_TC_OPSTATE_BASE_1_1(self, endpoint=1, cluster_revision=1, feature self.step(6) expected_value = [] - if (self.check_pics(f"{self.test_info.pics_code}.S.C00.Rsp") or - self.check_pics(f"{self.test_info.pics_code}.S.C03.Rsp")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Pause)) or + (await self.command_guard(endpoint=endpoint, command=commands.Resume))): expected_value.append(commands.Pause.command_id) - if (self.check_pics(f"{self.test_info.pics_code}.S.C01.Rsp") or - self.check_pics(f"{self.test_info.pics_code}.S.C02.Rsp")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Stop)) or + (await self.command_guard(endpoint=endpoint, command=commands.Start))): expected_value.append(commands.Stop.command_id) - if self.check_pics(f"{self.test_info.pics_code}.S.C02.Rsp"): + if await self.command_guard(endpoint=endpoint, command=commands.Start): expected_value.append(commands.Start.command_id) - if (self.check_pics(f"{self.test_info.pics_code}.S.C03.Rsp") or - self.check_pics(f"{self.test_info.pics_code}.S.C00.Rsp")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Pause)) or + (await self.command_guard(endpoint=endpoint, command=commands.Resume))): expected_value.append(commands.Resume.command_id) await self.read_and_expect_array_contains(endpoint=endpoint, @@ -293,10 +293,10 @@ async def TEST_TC_OPSTATE_BASE_1_1(self, endpoint=1, cluster_revision=1, feature self.step(7) expected_value = [] - if (self.check_pics(f"{self.test_info.pics_code}.S.C00.Rsp") or - self.check_pics(f"{self.test_info.pics_code}.S.C01.Rsp") or - self.check_pics(f"{self.test_info.pics_code}.S.C02.Rsp") or - self.check_pics(f"{self.test_info.pics_code}.S.C03.Rsp")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Pause)) or + (await self.command_guard(endpoint=endpoint, command=commands.Resume)) or + (await self.command_guard(endpoint=endpoint, command=commands.Stop)) or + (await self.command_guard(endpoint=endpoint, command=commands.Start))): expected_value.append(commands.OperationalCommandResponse.command_id) await self.read_and_expect_array_contains(endpoint=endpoint, @@ -344,7 +344,7 @@ async def TEST_TC_OPSTATE_BASE_2_1(self, endpoint=1): # STEP 2: TH reads from the DUT the PhaseList attribute self.step(2) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0000")): + if await self.attribute_guard(endpoint=endpoint, attribute=attributes.PhaseList): phase_list = await self.read_expect_success(endpoint=endpoint, attribute=attributes.PhaseList) if phase_list is not NullValue: @@ -354,7 +354,7 @@ async def TEST_TC_OPSTATE_BASE_2_1(self, endpoint=1): # STEP 3: TH reads from the DUT the CurrentPhase attribute self.step(3) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0001")): + if await self.attribute_guard(endpoint=endpoint, attribute=attributes.CurrentPhase): current_phase = await self.read_expect_success(endpoint=endpoint, attribute=attributes.CurrentPhase) if (phase_list == NullValue) or (not phase_list): @@ -366,7 +366,7 @@ async def TEST_TC_OPSTATE_BASE_2_1(self, endpoint=1): # STEP 4: TH reads from the DUT the CountdownTime attribute self.step(4) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0002")): + if await self.attribute_guard(endpoint=endpoint, attribute=attributes.CountdownTime): countdown_time = await self.read_expect_success(endpoint=endpoint, attribute=attributes.CountdownTime) if countdown_time is not NullValue: @@ -375,7 +375,7 @@ async def TEST_TC_OPSTATE_BASE_2_1(self, endpoint=1): # STEP 5: TH reads from the DUT the OperationalStateList attribute self.step(5) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0003")): + if await self.attribute_guard(endpoint=endpoint, attribute=attributes.OperationalStateList): operational_state_list = await self.read_expect_success(endpoint=endpoint, attribute=attributes.OperationalStateList) defined_states = [state.value for state in cluster.Enums.OperationalStateEnum @@ -396,73 +396,72 @@ async def TEST_TC_OPSTATE_BASE_2_1(self, endpoint=1): # STEP 6: TH reads from the DUT the OperationalState attribute self.step(6) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0004")): - operational_state = await self.read_expect_success(endpoint=endpoint, - attribute=attributes.OperationalState) - in_range = (0x80 <= operational_state <= 0xBF) - asserts.assert_true(operational_state in defined_states or in_range, - "OperationalState has an invalid ID value!") - - # STEP 6a: Manually put the device in the Stopped(0x00) operational state - self.step("6a") - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.M.ST_STOPPED")): - self.send_manual_or_pipe_command(name="OperationalStateChange", - device=self.device, - operation="Stop") - # STEP 6b: TH reads from the DUT the OperationalState attribute - self.step("6b") - await self.read_and_expect_value(endpoint=endpoint, - attribute=attributes.OperationalState, - expected_value=cluster.Enums.OperationalStateEnum.kStopped) - else: - self.skip_step("6b") + operational_state = await self.read_expect_success(endpoint=endpoint, + attribute=attributes.OperationalState) + in_range = (0x80 <= operational_state <= 0xBF) + asserts.assert_true(operational_state in defined_states or in_range, + "OperationalState has an invalid ID value!") + + # STEP 6a: Manually put the device in the Stopped(0x00) operational state + self.step("6a") + if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.M.ST_STOPPED")): + self.send_manual_or_pipe_command(name="OperationalStateChange", + device=self.device, + operation="Stop") + # STEP 6b: TH reads from the DUT the OperationalState attribute + self.step("6b") + await self.read_and_expect_value(endpoint=endpoint, + attribute=attributes.OperationalState, + expected_value=cluster.Enums.OperationalStateEnum.kStopped) + else: + self.skip_step("6b") - # STEP 6c: Manually put the device in the Running(0x01) operational state - self.step("6c") - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.M.ST_RUNNING")): - self.send_manual_or_pipe_command(name="OperationalStateChange", - device=self.device, - operation="Start") - # STEP 6d: TH reads from the DUT the OperationalState attribute - self.step("6d") - await self.read_and_expect_value(endpoint=endpoint, - attribute=attributes.OperationalState, - expected_value=cluster.Enums.OperationalStateEnum.kRunning) - else: - self.skip_step("6d") + # STEP 6c: Manually put the device in the Running(0x01) operational state + self.step("6c") + if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.M.ST_RUNNING")): + self.send_manual_or_pipe_command(name="OperationalStateChange", + device=self.device, + operation="Start") + # STEP 6d: TH reads from the DUT the OperationalState attribute + self.step("6d") + await self.read_and_expect_value(endpoint=endpoint, + attribute=attributes.OperationalState, + expected_value=cluster.Enums.OperationalStateEnum.kRunning) + else: + self.skip_step("6d") - # STEP 6e: Manually put the device in the Paused(0x02) operational state - self.step("6e") - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.M.ST_PAUSED")): - self.send_manual_or_pipe_command(name="OperationalStateChange", - device=self.device, - operation="Pause") - # STEP 6f: TH reads from the DUT the OperationalState attribute - self.step("6f") - await self.read_and_expect_value(endpoint=endpoint, - attribute=attributes.OperationalState, - expected_value=cluster.Enums.OperationalStateEnum.kPaused) - else: - self.skip_step("6f") + # STEP 6e: Manually put the device in the Paused(0x02) operational state + self.step("6e") + if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.M.ST_PAUSED")): + self.send_manual_or_pipe_command(name="OperationalStateChange", + device=self.device, + operation="Pause") + # STEP 6f: TH reads from the DUT the OperationalState attribute + self.step("6f") + await self.read_and_expect_value(endpoint=endpoint, + attribute=attributes.OperationalState, + expected_value=cluster.Enums.OperationalStateEnum.kPaused) + else: + self.skip_step("6f") - # STEP 6g: Manually put the device in the Error(0x03) operational state - self.step("6g") - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.M.ST_ERROR")): - self.send_manual_or_pipe_command(name="OperationalStateChange", - device=self.device, - operation="OnFault", - param=cluster.Enums.ErrorStateEnum.kUnableToStartOrResume) - # STEP 6h: TH reads from the DUT the OperationalState attribute - self.step("6h") - await self.read_and_expect_value(endpoint=endpoint, - attribute=attributes.OperationalState, - expected_value=cluster.Enums.OperationalStateEnum.kError) - else: - self.skip_step("6h") + # STEP 6g: Manually put the device in the Error(0x03) operational state + self.step("6g") + if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.M.ST_ERROR")): + self.send_manual_or_pipe_command(name="OperationalStateChange", + device=self.device, + operation="OnFault", + param=cluster.Enums.ErrorStateEnum.kUnableToStartOrResume) + # STEP 6h: TH reads from the DUT the OperationalState attribute + self.step("6h") + await self.read_and_expect_value(endpoint=endpoint, + attribute=attributes.OperationalState, + expected_value=cluster.Enums.OperationalStateEnum.kError) + else: + self.skip_step("6h") # STEP 7: TH reads from the DUT the OperationalError attribute self.step(7) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0005")): + if await self.attribute_guard(endpoint=endpoint, attribute=attributes.OperationalError): operational_error = await self.read_expect_success(endpoint=endpoint, attribute=attributes.OperationalError) # Defined Errors @@ -566,7 +565,9 @@ def STEPS_TC_OPSTATE_BASE_2_2(self) -> list[TestStep]: async def TEST_TC_OPSTATE_BASE_2_2(self, endpoint=1): cluster = self.test_info.cluster attributes = cluster.Attributes + commands = cluster.Commands + generated_cmd_list = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attributes.GeneratedCommandList) self.init_test() @@ -595,7 +596,7 @@ async def TEST_TC_OPSTATE_BASE_2_2(self, endpoint=1): # STEP 3: TH reads from the DUT the OperationalStateList attribute self.step(3) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0003")): + if await self.attribute_guard(endpoint=endpoint, attribute=attributes.OperationalStateList): operational_state_list = await self.read_expect_success(endpoint=endpoint, attribute=attributes.OperationalStateList) @@ -610,22 +611,20 @@ async def TEST_TC_OPSTATE_BASE_2_2(self, endpoint=1): # STEP 4: TH sends Start command to the DUT self.step(4) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C02.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Start)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Start(), expected_response=cluster.Enums.ErrorStateEnum.kNoError) # STEP 5: TH reads from the DUT the OperationalState attribute self.step(5) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0004")): - await self.read_and_expect_value(endpoint=endpoint, - attribute=attributes.OperationalState, - expected_value=cluster.Enums.OperationalStateEnum.kRunning) + await self.read_and_expect_value(endpoint=endpoint, + attribute=attributes.OperationalState, + expected_value=cluster.Enums.OperationalStateEnum.kRunning) # STEP 6: TH reads from the DUT the OperationalError attribute self.step(6) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0005")): + if await self.attribute_guard(endpoint=endpoint, attribute=attributes.OperationalError): await self.read_and_expect_property_value(endpoint=endpoint, attribute=attributes.OperationalError, attr_property="errorStateID", @@ -633,7 +632,7 @@ async def TEST_TC_OPSTATE_BASE_2_2(self, endpoint=1): # STEP 7: TH reads from the DUT the CountdownTime attribute self.step(7) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0002")): + if await self.attribute_guard(endpoint=endpoint, attribute=attributes.CountdownTime): initial_countdown_time = await self.read_expect_success(endpoint=endpoint, attribute=attributes.CountdownTime) if initial_countdown_time is not NullValue: @@ -642,7 +641,7 @@ async def TEST_TC_OPSTATE_BASE_2_2(self, endpoint=1): # STEP 8: TH reads from the DUT the PhaseList attribute self.step(8) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0000")): + if await self.attribute_guard(endpoint=endpoint, attribute=attributes.PhaseList): phase_list = await self.read_expect_success(endpoint=endpoint, attribute=attributes.PhaseList) phase_list_len = 0 @@ -653,7 +652,7 @@ async def TEST_TC_OPSTATE_BASE_2_2(self, endpoint=1): # STEP 9: TH reads from the DUT the CurrentPhase attribute self.step(9) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0001")): + if await self.attribute_guard(endpoint=endpoint, attribute=attributes.CurrentPhase): current_phase = await self.read_expect_success(endpoint=endpoint, attribute=attributes.CurrentPhase) if (phase_list == NullValue) or (not phase_list): @@ -666,12 +665,12 @@ async def TEST_TC_OPSTATE_BASE_2_2(self, endpoint=1): # STEP 10: TH waits for {PIXIT.WAITTIME.COUNTDOWN} self.step(10) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0002")): + if await self.attribute_guard(endpoint=endpoint, attribute=attributes.CountdownTime): time.sleep(wait_time) # STEP 11: TH reads from the DUT the CountdownTime attribute self.step(11) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0002")): + if await self.attribute_guard(endpoint=endpoint, attribute=attributes.CountdownTime): countdown_time = await self.read_expect_success(endpoint=endpoint, attribute=attributes.CountdownTime) @@ -683,31 +682,27 @@ async def TEST_TC_OPSTATE_BASE_2_2(self, endpoint=1): # STEP 12: TH sends Start command to the DUT self.step(12) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C02.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Start)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Start(), expected_response=cluster.Enums.ErrorStateEnum.kNoError) # STEP 13: TH sends Stop command to the DUT self.step(13) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C01.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Stop)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Stop(), expected_response=cluster.Enums.ErrorStateEnum.kNoError) # STEP 14: TH reads from the DUT the OperationalState attribute self.step(14) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0004")): - await self.read_and_expect_value(endpoint=endpoint, - attribute=attributes.OperationalState, - expected_value=cluster.Enums.OperationalStateEnum.kStopped) + await self.read_and_expect_value(endpoint=endpoint, + attribute=attributes.OperationalState, + expected_value=cluster.Enums.OperationalStateEnum.kStopped) # STEP 15: TH sends Stop command to the DUT self.step(15) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C01.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Stop)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Stop(), expected_response=cluster.Enums.ErrorStateEnum.kNoError) @@ -722,9 +717,9 @@ async def TEST_TC_OPSTATE_BASE_2_2(self, endpoint=1): # STEP 17: TH sends Start command to the DUT self.step(17) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.M.ERR_UNABLE_TO_START_OR_RESUME") and - self.check_pics(f"{self.test_info.pics_code}.S.C02.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if self.pics_guard((self.check_pics(f"{self.test_info.pics_code}.S.M.ERR_UNABLE_TO_START_OR_RESUME")) and + ((await self.command_guard(endpoint=endpoint, command=commands.Start)) and + (commands.OperationalCommandResponse.command_id in generated_cmd_list))): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Start(), expected_response=cluster.Enums.ErrorStateEnum.kUnableToStartOrResume) @@ -757,7 +752,9 @@ def STEPS_TC_OPSTATE_BASE_2_3(self) -> list[TestStep]: async def TEST_TC_OPSTATE_BASE_2_3(self, endpoint=1): cluster = self.test_info.cluster attributes = cluster.Attributes + commands = cluster.Commands + generated_cmd_list = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attributes.GeneratedCommandList) self.init_test() @@ -786,37 +783,34 @@ async def TEST_TC_OPSTATE_BASE_2_3(self, endpoint=1): # STEP 3: TH reads from the DUT the OperationalStateList attribute self.step(3) - if self.pics_guard(self.check_pics((f"{self.test_info.pics_code}.S.A0003"))): - operational_state_list = await self.read_expect_success(endpoint=endpoint, - attribute=attributes.OperationalStateList) + operational_state_list = await self.read_expect_success(endpoint=endpoint, + attribute=attributes.OperationalStateList) - operational_state_list_ids = [op_state.operationalStateID for op_state in operational_state_list] + operational_state_list_ids = [op_state.operationalStateID for op_state in operational_state_list] - defined_states = [state.value for state in cluster.Enums.OperationalStateEnum - if state != cluster.Enums.OperationalStateEnum.kUnknownEnumValue] + defined_states = [state.value for state in cluster.Enums.OperationalStateEnum + if state != cluster.Enums.OperationalStateEnum.kUnknownEnumValue] - for state in defined_states: - if state not in operational_state_list_ids: - asserts.fail(f"The list shall include structs with the following OperationalStateIds: {defined_states}") + for state in defined_states: + if state not in operational_state_list_ids: + asserts.fail(f"The list shall include structs with the following OperationalStateIds: {defined_states}") # STEP 4: TH sends Pause command to the DUT self.step(4) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C00.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Pause)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Pause(), expected_response=cluster.Enums.ErrorStateEnum.kNoError) # STEP 5: TH reads from the DUT the OperationalState attribute self.step(5) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0004")): - await self.read_and_expect_value(endpoint=endpoint, - attribute=attributes.OperationalState, - expected_value=cluster.Enums.OperationalStateEnum.kPaused) + await self.read_and_expect_value(endpoint=endpoint, + attribute=attributes.OperationalState, + expected_value=cluster.Enums.OperationalStateEnum.kPaused) # STEP 6: TH reads from the DUT the CountdownTime attribute self.step(6) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0002")): + if await self.attribute_guard(endpoint=endpoint, attribute=attributes.CountdownTime): initial_countdown_time = await self.read_expect_success(endpoint=endpoint, attribute=attributes.CountdownTime) if initial_countdown_time is not NullValue: @@ -830,7 +824,7 @@ async def TEST_TC_OPSTATE_BASE_2_3(self, endpoint=1): # STEP 8: TH reads from the DUT the CountdownTime attribute self.step(8) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0002")): + if await self.attribute_guard(endpoint=endpoint, attribute=attributes.CountdownTime): countdown_time = await self.read_expect_success(endpoint=endpoint, attribute=attributes.CountdownTime) @@ -842,31 +836,27 @@ async def TEST_TC_OPSTATE_BASE_2_3(self, endpoint=1): # STEP 9: TH sends Pause command to the DUT self.step(9) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C00.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Pause)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Pause(), expected_response=cluster.Enums.ErrorStateEnum.kNoError) # STEP 10: TH sends Resume command to the DUT self.step(10) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C03.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Resume)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Resume(), expected_response=cluster.Enums.ErrorStateEnum.kNoError) # STEP 11: TH reads from the DUT the OperationalState attribute self.step(11) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0004")): - await self.read_and_expect_value(endpoint=endpoint, - attribute=attributes.OperationalState, - expected_value=cluster.Enums.OperationalStateEnum.kRunning) + await self.read_and_expect_value(endpoint=endpoint, + attribute=attributes.OperationalState, + expected_value=cluster.Enums.OperationalStateEnum.kRunning) # STEP 12: TH sends Resume command to the DUT self.step(12) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C03.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Resume)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Resume(), expected_response=cluster.Enums.ErrorStateEnum.kNoError) @@ -880,16 +870,14 @@ async def TEST_TC_OPSTATE_BASE_2_3(self, endpoint=1): # STEP 14: TH sends Pause command to the DUT self.step(14) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C00.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Pause)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Pause(), expected_response=cluster.Enums.ErrorStateEnum.kCommandInvalidInState) # STEP 15: TH sends Resume command to the DUT self.step(15) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C03.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Resume)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Resume(), expected_response=cluster.Enums.ErrorStateEnum.kCommandInvalidInState) @@ -904,16 +892,14 @@ async def TEST_TC_OPSTATE_BASE_2_3(self, endpoint=1): # STEP 17: TH sends Pause command to the DUT self.step(17) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C00.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Pause)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Pause(), expected_response=cluster.Enums.ErrorStateEnum.kCommandInvalidInState) # STEP 18: TH sends Resume command to the DUT self.step(18) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C03.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Resume)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Resume(), expected_response=cluster.Enums.ErrorStateEnum.kCommandInvalidInState) @@ -946,7 +932,7 @@ async def TEST_TC_OPSTATE_BASE_2_4(self, endpoint=1): # STEP 1: Commission DUT to TH (can be skipped if done in a preceding test) self.step(1) - if self.pics_guard(error_event_gen): + if error_event_gen: # STEP 2: Set up a subscription to the OperationalError event self.step(2) # Subscribe to Events and when they are sent push them to a queue for checking later @@ -976,10 +962,11 @@ async def TEST_TC_OPSTATE_BASE_2_4(self, endpoint=1): # STEP 4: TH reads from the DUT the OperationalState attribute self.step(4) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0004")): - await self.read_and_expect_value(endpoint=endpoint, - attribute=attributes.OperationalState, - expected_value=cluster.Enums.OperationalStateEnum.kError) + + await self.read_and_expect_value(endpoint=endpoint, + attribute=attributes.OperationalState, + expected_value=cluster.Enums.OperationalStateEnum.kError) + else: self.skip_step(2) self.skip_step(3) @@ -1017,7 +1004,10 @@ def STEPS_TC_OPSTATE_BASE_2_5(self) -> list[TestStep]: async def TEST_TC_OPSTATE_BASE_2_5(self, endpoint=1): cluster = self.test_info.cluster attributes = cluster.Attributes + commands = cluster.Commands + generated_cmd_list = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attributes.GeneratedCommandList) + events = cluster.Events self.init_test() @@ -1058,25 +1048,23 @@ async def TEST_TC_OPSTATE_BASE_2_5(self, endpoint=1): # STEP 4: TH sends Start command to the DUT self.step(4) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C02.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Start)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Start(), expected_response=cluster.Enums.ErrorStateEnum.kNoError) # STEP 5: TH reads from the DUT the CountdownTime attribute self.step(5) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0002")): + if await self.attribute_guard(endpoint=endpoint, attribute=attributes.CountdownTime): initial_countdown_time = await self.read_expect_success(endpoint=endpoint, attribute=attributes.CountdownTime) if initial_countdown_time is not NullValue: # STEP 6: TH reads from the DUT the OperationalState attribute self.step(6) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0004")): - await self.read_and_expect_value(endpoint=endpoint, - attribute=attributes.OperationalState, - expected_value=cluster.Enums.OperationalStateEnum.kRunning) + await self.read_and_expect_value(endpoint=endpoint, + attribute=attributes.OperationalState, + expected_value=cluster.Enums.OperationalStateEnum.kRunning) # STEP 7: TH waits for initial-countdown-time self.step(7) @@ -1085,8 +1073,7 @@ async def TEST_TC_OPSTATE_BASE_2_5(self, endpoint=1): # STEP 8: TH sends Stop command to the DUT self.step(8) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C01.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Stop)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Stop(), expected_response=cluster.Enums.ErrorStateEnum.kNoError) @@ -1109,10 +1096,9 @@ async def TEST_TC_OPSTATE_BASE_2_5(self, endpoint=1): # STEP 10: TH reads from the DUT the OperationalState attribute self.step(10) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0004")): - await self.read_and_expect_value(endpoint=endpoint, - attribute=attributes.OperationalState, - expected_value=cluster.Enums.OperationalStateEnum.kStopped) + await self.read_and_expect_value(endpoint=endpoint, + attribute=attributes.OperationalState, + expected_value=cluster.Enums.OperationalStateEnum.kStopped) # STEP 11: Restart DUT self.step(11) @@ -1135,33 +1121,29 @@ async def TEST_TC_OPSTATE_BASE_2_5(self, endpoint=1): # STEP 13: TH sends Start command to the DUT self.step(13) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C02.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Start)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Start(), expected_response=cluster.Enums.ErrorStateEnum.kNoError) # STEP 14: TH reads from the DUT the OperationalState attribute self.step(14) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0004")): - await self.read_and_expect_value(endpoint=endpoint, - attribute=attributes.OperationalState, - expected_value=cluster.Enums.OperationalStateEnum.kRunning) + await self.read_and_expect_value(endpoint=endpoint, + attribute=attributes.OperationalState, + expected_value=cluster.Enums.OperationalStateEnum.kRunning) # STEP 15: TH sends Pause command to the DUT self.step(15) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C00.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Pause)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Pause(), expected_response=cluster.Enums.ErrorStateEnum.kNoError) # STEP 16: TH reads from the DUT the OperationalState attribute self.step(16) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0004")): - await self.read_and_expect_value(endpoint=endpoint, - attribute=attributes.OperationalState, - expected_value=cluster.Enums.OperationalStateEnum.kPaused) + await self.read_and_expect_value(endpoint=endpoint, + attribute=attributes.OperationalState, + expected_value=cluster.Enums.OperationalStateEnum.kPaused) # STEP 17: TH waits for half of initial-countdown-time self.step(17) @@ -1169,18 +1151,16 @@ async def TEST_TC_OPSTATE_BASE_2_5(self, endpoint=1): # STEP 18: TH sends Resume command to the DUT self.step(18) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C03.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Resume)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Resume(), expected_response=cluster.Enums.ErrorStateEnum.kNoError) # STEP 19: TH reads from the DUT the OperationalState attribute self.step(19) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.A0004")): - await self.read_and_expect_value(endpoint=endpoint, - attribute=attributes.OperationalState, - expected_value=cluster.Enums.OperationalStateEnum.kRunning) + await self.read_and_expect_value(endpoint=endpoint, + attribute=attributes.OperationalState, + expected_value=cluster.Enums.OperationalStateEnum.kRunning) # STEP 20: TH waits for initial-countdown-time self.step(20) @@ -1188,8 +1168,7 @@ async def TEST_TC_OPSTATE_BASE_2_5(self, endpoint=1): # STEP 21: TH sends Stop command to the DUT self.step(21) - if self.pics_guard(self.check_pics(f"{self.test_info.pics_code}.S.C01.Rsp") and - self.check_pics(f"{self.test_info.pics_code}.S.C04.Tx")): + if ((await self.command_guard(endpoint=endpoint, command=commands.Stop)) and (commands.OperationalCommandResponse.command_id in generated_cmd_list)): await self.send_cmd_expect_response(endpoint=endpoint, cmd=commands.Stop(), expected_response=cluster.Enums.ErrorStateEnum.kNoError) diff --git a/src/python_testing/TC_RVCOPSTATE_2_1.py b/src/python_testing/TC_RVCOPSTATE_2_1.py index 428aa9a5ab14fd..4fc63fbe236632 100644 --- a/src/python_testing/TC_RVCOPSTATE_2_1.py +++ b/src/python_testing/TC_RVCOPSTATE_2_1.py @@ -85,6 +85,8 @@ def TC_RVCOPSTATE_2_1(self) -> list[str]: @async_test_body async def test_TC_RVCOPSTATE_2_1(self): + if self.matter_test_config.endpoint is None or self.matter_test_config.endpoint == 0: + asserts.fail("--endpoint must be set and not set to 0 for this test to run correctly.") self.endpoint = self.get_endpoint() asserts.assert_false(self.endpoint is None, "--endpoint <endpoint> must be included on the command line in.") self.is_ci = self.check_pics("PICS_SDK_CI_ONLY") @@ -94,7 +96,8 @@ async def test_TC_RVCOPSTATE_2_1(self): asserts.fail("The --app-pid flag must be set when PICS_SDK_CI_ONLY is set") self.app_pipe = self.app_pipe + str(app_pid) - attributes = Clusters.RvcOperationalState.Attributes + cluster = Clusters.RvcOperationalState + attributes = cluster.Attributes self.print_step(1, "Commissioning, already done") @@ -102,7 +105,7 @@ async def test_TC_RVCOPSTATE_2_1(self): if self.is_ci: self.write_to_app_pipe({"Name": "Reset"}) - if self.check_pics("RVCOPSTATE.S.A0000"): + if await self.attribute_guard(endpoint=self.endpoint, attribute=attributes.PhaseList): self.print_step(2, "Read PhaseList attribute") phase_list = await self.read_mod_attribute_expect_success(endpoint=self.endpoint, attribute=attributes.PhaseList) @@ -115,7 +118,7 @@ async def test_TC_RVCOPSTATE_2_1(self): asserts.assert_less_equal(phase_list_len, 32, "PhaseList length(%d) must be less than 32!" % phase_list_len) - if self.check_pics("RVCOPSTATE.S.A0001"): + if await self.attribute_guard(endpoint=self.endpoint, attribute=attributes.CurrentPhase): self.print_step(3, "Read CurrentPhase attribute") current_phase = await self.read_mod_attribute_expect_success(endpoint=self.endpoint, attribute=attributes.CurrentPhase) logging.info("CurrentPhase: %s" % (current_phase)) @@ -126,7 +129,7 @@ async def test_TC_RVCOPSTATE_2_1(self): asserts.assert_true(0 <= current_phase < phase_list_len, "CurrentPhase(%s) must be between 0 and %d" % (current_phase, (phase_list_len - 1))) - if self.check_pics("RVCOPSTATE.S.A0002"): + if await self.attribute_guard(endpoint=self.endpoint, attribute=attributes.CountdownTime): self.print_step(4, "Read CountdownTime attribute") countdown_time = await self.read_mod_attribute_expect_success(endpoint=self.endpoint, attribute=attributes.CountdownTime) @@ -136,7 +139,7 @@ async def test_TC_RVCOPSTATE_2_1(self): asserts.assert_true(countdown_time >= 0 and countdown_time <= 259200, "CountdownTime(%s) must be between 0 and 259200" % countdown_time) - if self.check_pics("RVCOPSTATE.S.A0003"): + if await self.attribute_guard(endpoint=self.endpoint, attribute=attributes.OperationalStateList): self.print_step(5, "Read OperationalStateList attribute") operational_state_list = await self.read_mod_attribute_expect_success(endpoint=self.endpoint, attribute=attributes.OperationalStateList) @@ -159,7 +162,7 @@ async def test_TC_RVCOPSTATE_2_1(self): asserts.assert_true(error_state_present, "The OperationalStateList does not have an ID entry of Error(0x03)") - if self.check_pics("RVCOPSTATE.S.A0004"): + if await self.attribute_guard(endpoint=self.endpoint, attribute=attributes.OperationalState): self.print_step(6, "Read OperationalState attribute") operational_state = await self.read_mod_attribute_expect_success(endpoint=self.endpoint, attribute=attributes.OperationalState) @@ -226,7 +229,7 @@ async def test_TC_RVCOPSTATE_2_1(self): self.wait_for_user_input(prompt_msg=f"{test_step}, and press Enter when done.\n") await self.read_and_validate_opstate(step="6n", expected_state=Clusters.RvcOperationalState.Enums.OperationalStateEnum.kDocked) - if self.check_pics("RVCOPSTATE.S.A0005"): + if await self.attribute_guard(endpoint=self.endpoint, attribute=attributes.OperationalError): self.print_step(7, "Read OperationalError attribute") operational_error = await self.read_mod_attribute_expect_success(endpoint=self.endpoint, attribute=attributes.OperationalError) diff --git a/src/python_testing/TC_TestAttrAvail.py b/src/python_testing/TC_TestAttrAvail.py new file mode 100644 index 00000000000000..b2fc40eae600c6 --- /dev/null +++ b/src/python_testing/TC_TestAttrAvail.py @@ -0,0 +1,164 @@ +# +# Copyright (c) 2023 Project CHIP Authors +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --manual-code 10054912339 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# --endpoint 1 +# factory-reset: true +# quiet: true +# run2: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --passcode 20202021 --KVS kvs1 +# script-args: > +# --storage-path admin_storage.json +# --discriminator 1234 +# --passcode 20202021 +# --endpoint 1 +# --commissioning-method on-network +# factory-reset: true +# quiet: true +# run3: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 +# script-args: > +# --storage-path admin_storage.json +# --endpoint 1 +# --discriminator 1234 +# --passcode 20202021 +# factory-reset: false +# quiet: true +# === END CI TEST ARGUMENTS === + +# Run 1: Tests PASE connection using manual code +# Run 2: Tests CASE connection using manual discriminator and passcode +# Run 3: Tests without factory reset + +import asyncio + +import chip.clusters as Clusters +from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts + + +class TC_TestAttrAvail(MatterBaseTest): + # Using get_code and a modified version of setup_class_helper functions from chip.testing.basic_composition module + def get_code(self, dev_ctrl): + created_codes = [] + for idx, discriminator in enumerate(self.matter_test_config.discriminators): + created_codes.append(dev_ctrl.CreateManualCode(discriminator, self.matter_test_config.setup_passcodes[idx])) + + setup_codes = self.matter_test_config.qr_code_content + self.matter_test_config.manual_code + created_codes + if not setup_codes: + return None + asserts.assert_equal(len(setup_codes), 1, + "Require exactly one of either --qr-code, --manual-code or (--discriminator and --passcode).") + return setup_codes[0] + + async def setup_class_helper(self, allow_pase: bool = True): + dev_ctrl = self.default_controller + self.problems = [] + + node_id = self.dut_node_id + + task_list = [] + if allow_pase and self.get_code(dev_ctrl): + setup_code = self.get_code(dev_ctrl) + pase_future = dev_ctrl.EstablishPASESession(setup_code, self.dut_node_id) + task_list.append(asyncio.create_task(pase_future)) + + case_future = dev_ctrl.GetConnectedDevice(nodeid=node_id, allowPASE=False) + task_list.append(asyncio.create_task(case_future)) + + for task in task_list: + asyncio.ensure_future(task) + + done, pending = await asyncio.wait(task_list, return_when=asyncio.FIRST_COMPLETED) + + for task in pending: + try: + task.cancel() + await task + except asyncio.CancelledError: + pass + + wildcard_read = (await dev_ctrl.Read(node_id, [()])) + + # ======= State kept for use by all tests ======= + # All endpoints in "full object" indexing format + self.endpoints = wildcard_read.attributes + + def steps_TC_TestAttrAvail(self) -> list[TestStep]: + return [ + TestStep(1, "Commissioning, already done", is_commissioning=True), + TestStep(2, "Checking OperationalState attribute is available on endpoint"), + TestStep(3, "Checking Operational Resume command is available on endpoint"), + TestStep(4, "Checking Timezone feature is available on endpoint"), + ] + + def TC_TestAttrAvail(self) -> list[str]: + return ["RVCOPSTATE.S"] + + @async_test_body + async def setup_class(self): + super().setup_class() + await self.setup_class_helper() + + # ======= START OF ACTUAL TESTS ======= + @async_test_body + async def test_TC_TestAttrAvail(self): + self.step(1) + + if self.matter_test_config.endpoint is None or self.matter_test_config.endpoint == 0: + asserts.fail("--endpoint must be set and not set to 0 for this test to run correctly.") + self.endpoint = self.get_endpoint() + asserts.assert_false(self.endpoint is None, "--endpoint <endpoint> must be included on the command line in.") + + cluster = Clusters.RvcOperationalState + attributes = cluster.Attributes + commands = cluster.Commands + self.th1 = self.default_controller + + self.step(2) + attr_should_be_there = await self.attribute_guard(endpoint=self.endpoint, attribute=attributes.OperationalState) + asserts.assert_true(attr_should_be_there, True) + self.print_step("Operational State Attr", attr_should_be_there) + + self.step(3) + cmd_should_be_there = await self.command_guard(endpoint=self.endpoint, command=commands.Resume) + asserts.assert_true(cmd_should_be_there, True) + self.print_step("Operational Resume Command available ", cmd_should_be_there) + + self.step(4) + feat_should_be_there = await self.feature_guard(endpoint=self.endpoint, cluster=Clusters.BooleanStateConfiguration, feature_int=Clusters.BooleanStateConfiguration.Bitmaps.Feature.kAudible) + asserts.assert_true(feat_should_be_there, True) + self.print_step("Boolean State Config Audio Feature available ", feat_should_be_there) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_VALCC_3_1.py b/src/python_testing/TC_VALCC_3_1.py index 5f3c58d0b96cf9..295c312c37f0cb 100644 --- a/src/python_testing/TC_VALCC_3_1.py +++ b/src/python_testing/TC_VALCC_3_1.py @@ -32,12 +32,10 @@ # quiet: true # === END CI TEST ARGUMENTS === -import time - import chip.clusters as Clusters from chip.clusters.Types import NullValue -from chip.interaction_model import InteractionModelError, Status -from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from chip.testing.matter_testing import (AttributeValue, ClusterAttributeChangeAccumulator, MatterBaseTest, TestStep, + async_test_body, default_matter_test_main) from mobly import asserts @@ -52,12 +50,16 @@ def desc_TC_VALCC_3_1(self) -> str: def steps_TC_VALCC_3_1(self) -> list[TestStep]: steps = [ TestStep(1, "Commissioning, already done", is_commissioning=True), - TestStep(2, "Send Open command"), - TestStep(3, "Read TargetState attribute"), - TestStep(4, "Read CurrentState attribute"), - TestStep(5, "Send Close command"), - TestStep(6, "Read TargetState attribute"), - TestStep(7, "Read CurrentState attribute"), + TestStep(2, "Set up a subscription to all attributes on the DUT"), + TestStep(3, "Send a close command to the DUT and wait until the CurrentState is closed", "DUT returns SUCCESS"), + TestStep(4, "Send Open command", "DUT returns SUCCESS"), + TestStep(5, "Wait until TH receives and data report for TargetState set to NULL and an attribute report for CurrentState set to Open (ordering does not matter)", + "Expected attribute reports are received"), + TestStep(6, "Read CurrentState and TargetState attribute", "CurrentState is Open, TargetState is NULL"), + TestStep(7, "Send Close command", "DUT returns SUCCESS"), + TestStep(8, "Wait until TH receives and data report for TargetState set to NULL and an attribute report for CurrentState set to Closed (ordering does not matter)", + "Expected attribute reports are received"), + TestStep(9, "Read CurrentState and TargetState attribute", "CurrentState is Closed, TargetState is NULL"), ] return steps @@ -72,62 +74,55 @@ async def test_TC_VALCC_3_1(self): endpoint = self.get_endpoint(default=1) - self.step(1) - attributes = Clusters.ValveConfigurationAndControl.Attributes + self.step(1) # commissioning - already done self.step(2) - try: - await self.send_single_cmd(cmd=Clusters.Objects.ValveConfigurationAndControl.Commands.Open(), endpoint=endpoint) - except InteractionModelError as e: - asserts.assert_equal(e.status, Status.Success, "Unexpected error returned") - pass + cluster = Clusters.ValveConfigurationAndControl + attributes = cluster.Attributes + attribute_subscription = ClusterAttributeChangeAccumulator(cluster) + await attribute_subscription.start(self.default_controller, self.dut_node_id, endpoint) self.step(3) - target_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.TargetState) - - asserts.assert_true(target_state_dut is not NullValue, "TargetState is null") - asserts.assert_equal(target_state_dut, Clusters.Objects.ValveConfigurationAndControl.Enums.ValveStateEnum.kOpen, - "TargetState is not the expected value") - - self.step(4) + # Wait for the entire duration of the test because this valve may be slow. The test will time out before this does. That's fine. + timeout = self.matter_test_config.timeout if self.matter_test_config.timeout is not None else self.default_timeout + await self.send_single_cmd(cmd=cluster.Commands.Close(), endpoint=endpoint) current_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentState) - asserts.assert_true(current_state_dut is not NullValue, "CurrentState is null") - - while current_state_dut is Clusters.Objects.ValveConfigurationAndControl.Enums.ValveStateEnum.kTransitioning: - time.sleep(1) - - current_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentState) - asserts.assert_true(current_state_dut is not NullValue, "CurrentState is null") + if current_state_dut != cluster.Enums.ValveStateEnum.kClosed: + current_state_closed = AttributeValue( + endpoint_id=endpoint, attribute=attributes.CurrentState, value=cluster.Enums.ValveStateEnum.kClosed) + attribute_subscription.await_all_final_values_reported( + expected_final_values=[current_state_closed], timeout_sec=timeout) - asserts.assert_equal(current_state_dut, Clusters.Objects.ValveConfigurationAndControl.Enums.ValveStateEnum.kOpen, - "CurrentState is not the expected value") + self.step(4) + attribute_subscription.reset() + await self.send_single_cmd(cmd=Clusters.Objects.ValveConfigurationAndControl.Commands.Open(), endpoint=endpoint) self.step(5) - try: - await self.send_single_cmd(cmd=Clusters.Objects.ValveConfigurationAndControl.Commands.Close(), endpoint=endpoint) - except InteractionModelError as e: - asserts.assert_equal(e.status, Status.Success, "Unexpected error returned") - pass + # Wait until the current state is open and the target state is Null. + expected_final_state = [AttributeValue(endpoint_id=endpoint, attribute=attributes.TargetState, value=NullValue), AttributeValue( + endpoint_id=endpoint, attribute=attributes.CurrentState, value=cluster.Enums.ValveStateEnum.kOpen)] + attribute_subscription.await_all_final_values_reported(expected_final_values=expected_final_state, timeout_sec=timeout) self.step(6) target_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.TargetState) - - asserts.assert_true(target_state_dut is not NullValue, "TargetState is null") - asserts.assert_equal(target_state_dut, Clusters.Objects.ValveConfigurationAndControl.Enums.ValveStateEnum.kClosed, - "TargetState is not the expected value") - - self.step(7) current_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentState) - asserts.assert_true(current_state_dut is not NullValue, "CurrentState is null") + asserts.assert_equal(current_state_dut, cluster.Enums.ValveStateEnum.kOpen, "CurrentState is not open") + asserts.assert_equal(target_state_dut, NullValue, "TargetState is not null") - while current_state_dut is Clusters.Objects.ValveConfigurationAndControl.Enums.ValveStateEnum.kTransitioning: - time.sleep(1) + self.step(7) + attribute_subscription.reset() + await self.send_single_cmd(cmd=cluster.Commands.Close(), endpoint=endpoint) - current_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentState) - asserts.assert_true(current_state_dut is not NullValue, "CurrentState is null") + self.step(8) + expected_final_state = [AttributeValue(endpoint_id=endpoint, attribute=attributes.TargetState, value=NullValue), AttributeValue( + endpoint_id=endpoint, attribute=attributes.CurrentState, value=cluster.Enums.ValveStateEnum.kClosed)] + attribute_subscription.await_all_final_values_reported(expected_final_values=expected_final_state, timeout_sec=timeout) - asserts.assert_equal(current_state_dut, Clusters.Objects.ValveConfigurationAndControl.Enums.ValveStateEnum.kClosed, - "CurrentState is not the expected value") + self.step(9) + target_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.TargetState) + current_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentState) + asserts.assert_equal(current_state_dut, cluster.Enums.ValveStateEnum.kClosed, "CurrentState is not closed") + asserts.assert_equal(target_state_dut, NullValue, "TargetState is not null") if __name__ == "__main__": diff --git a/src/python_testing/TC_VALCC_3_2.py b/src/python_testing/TC_VALCC_3_2.py index 44dc320c0a8f33..5e22cda0ef39f0 100644 --- a/src/python_testing/TC_VALCC_3_2.py +++ b/src/python_testing/TC_VALCC_3_2.py @@ -25,6 +25,7 @@ # --commissioning-method on-network # --discriminator 1234 # --passcode 20202021 +# --endpoint 1 # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # --endpoint 1 @@ -32,13 +33,11 @@ # quiet: true # === END CI TEST ARGUMENTS === -import logging -import time - import chip.clusters as Clusters from chip.clusters.Types import NullValue from chip.interaction_model import InteractionModelError, Status -from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from chip.testing.matter_testing import (AttributeValue, ClusterAttributeChangeAccumulator, MatterBaseTest, TestStep, + async_test_body, default_matter_test_main) from mobly import asserts @@ -53,13 +52,18 @@ def desc_TC_VALCC_3_2(self) -> str: def steps_TC_VALCC_3_2(self) -> list[TestStep]: steps = [ TestStep(1, "Commissioning, already done", is_commissioning=True), - TestStep(2, "Read FeatureMap attribute"), - TestStep(3, "Send Open command with TargetLevel set to 100"), - TestStep(4, "Read TargetLevel attribute"), - TestStep(5, "Read CurrentLevel attribute"), - TestStep(6, "Send Close command"), - TestStep(7, "Read TargetLevel attribute"), - TestStep(8, "Read CurrentLevel attribute"), + TestStep(2, "Set up a subscription to all attributes on the DUT"), + TestStep(3, "Send a close command to the DUT and wait until the CurrentState is closed", "DUT returns SUCCESS"), + TestStep(4, "TH sends command Open command with TargetLevel field set to 100 and the remaining fields not populated.", + "Verify DUT responds w/ status SUCCESS(0x00)."), + TestStep(5, "Wait until TH receives data reports for TargetState set to NULL, TargetLevel set to NULL, CurrentState set to Open and CurrentLevel set to 100 (ordering does not matter)", + "Expected attribute reports are received"), + TestStep(6, "Read CurrentState, CurrentLevel, TargetState and TargetLevel attributes", + "CurrentState is Open, CurrentLevel is 100, TargetState is NULL and TargetLevel is NULL"), + TestStep(7, "Send Close command", "DUT returns SUCCESS"), + TestStep(8, "Wait until TH receives and data report for TargetState set to NULL and an attribute report for CurrentState set to Closed (ordering does not matter)", + "Expected attribute reports are received"), + TestStep(9, "Read CurrentState and TargetState attribute", "CurrentState is Closed, TargetState is NULL"), ] return steps @@ -73,82 +77,83 @@ def pics_TC_VALCC_3_2(self) -> list[str]: async def test_TC_VALCC_3_2(self): endpoint = self.get_endpoint(default=1) + asserts.assert_is_not_none( + endpoint, "Endpoint is required for this tests. The test endpoint is set using the --endpoint flag") self.step(1) attributes = Clusters.ValveConfigurationAndControl.Attributes - - self.step(2) + # TODO: replace with top-level check using run_if_endpoint_matches feature_map = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.FeatureMap) - is_lvl_feature_supported = feature_map & Clusters.ValveConfigurationAndControl.Bitmaps.Feature.kLevel + if not is_lvl_feature_supported: + asserts.skip('Endpoint does not match test requirements') + + self.step(2) + cluster = Clusters.ValveConfigurationAndControl + attributes = cluster.Attributes + attribute_subscription = ClusterAttributeChangeAccumulator(cluster) + await attribute_subscription.start(self.default_controller, self.dut_node_id, endpoint) self.step(3) - if is_lvl_feature_supported: - try: - await self.send_single_cmd(cmd=Clusters.Objects.ValveConfigurationAndControl.Commands.Open(targetLevel=100), endpoint=endpoint) - except InteractionModelError as e: - asserts.assert_equal(e.status, Status.Success, "Unexpected error returned") - pass - else: - logging.info("Test step skipped") + # Wait for the entire duration of the test because this valve may be slow. The test will time out before this does. That's fine. + timeout = self.matter_test_config.timeout if self.matter_test_config.timeout is not None else self.default_timeout + await self.send_single_cmd(cmd=cluster.Commands.Close(), endpoint=endpoint) + current_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentState) + if current_state_dut != cluster.Enums.ValveStateEnum.kClosed: + current_state_closed = AttributeValue( + endpoint_id=endpoint, attribute=attributes.CurrentState, value=cluster.Enums.ValveStateEnum.kClosed) + attribute_subscription.await_all_final_values_reported( + expected_final_values=[current_state_closed], timeout_sec=timeout) self.step(4) - if is_lvl_feature_supported: - target_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.TargetLevel) - - asserts.assert_true(target_level_dut is not NullValue, "TargetLevel is null") - asserts.assert_equal(target_level_dut, 100, "TargetLevel is not the expected value") - else: - logging.info("Test step skipped") + attribute_subscription.reset() + try: + await self.send_single_cmd(cmd=Clusters.Objects.ValveConfigurationAndControl.Commands.Open(targetLevel=100), endpoint=endpoint) + except InteractionModelError as e: + asserts.assert_equal(e.status, Status.Success, "Unexpected error returned") + pass self.step(5) - if is_lvl_feature_supported: - current_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentLevel) - asserts.assert_true(current_level_dut is not NullValue, "CurrentLevel is null") - - while current_level_dut != 100: - time.sleep(1) - - current_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentLevel) - asserts.assert_true(current_level_dut is not NullValue, "CurrentLevel is null") - - asserts.assert_equal(current_level_dut, 100, "CurrentLevel is not the expected value") - else: - logging.info("Test step skipped") + # Wait until the current state is open and the target state is Null. + expected_final_state = [AttributeValue(endpoint_id=endpoint, attribute=attributes.TargetState, value=NullValue), + AttributeValue(endpoint_id=endpoint, attribute=attributes.CurrentState, + value=cluster.Enums.ValveStateEnum.kOpen), + AttributeValue(endpoint_id=endpoint, attribute=attributes.TargetLevel, value=NullValue), + AttributeValue(endpoint_id=endpoint, attribute=attributes.CurrentLevel, value=100)] + attribute_subscription.await_all_final_values_reported(expected_final_values=expected_final_state, timeout_sec=timeout) self.step(6) - if is_lvl_feature_supported: - try: - await self.send_single_cmd(cmd=Clusters.Objects.ValveConfigurationAndControl.Commands.Close(), endpoint=endpoint) - except InteractionModelError as e: - asserts.assert_equal(e.status, Status.Success, "Unexpected error returned") - pass - else: - logging.info("Test step skipped") + target_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.TargetState) + current_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentState) + target_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.TargetLevel) + current_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentLevel) + asserts.assert_equal(current_state_dut, cluster.Enums.ValveStateEnum.kOpen, "CurrentState is not open") + asserts.assert_equal(target_state_dut, NullValue, "TargetState is not null") + asserts.assert_equal(current_level_dut, 100, "CurrentLevel is not 100") + asserts.assert_equal(target_level_dut, NullValue, "TargetLevel is not null") self.step(7) - if is_lvl_feature_supported: - target_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.TargetLevel) - - asserts.assert_true(target_level_dut is not NullValue, "TargetLevel is null") - asserts.assert_equal(target_level_dut, 0, "TargetLevel is not the expected value") - else: - logging.info("Test step skipped") + attribute_subscription.reset() + await self.send_single_cmd(cmd=cluster.Commands.Close(), endpoint=endpoint) self.step(8) - if is_lvl_feature_supported: - current_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentLevel) - asserts.assert_true(current_level_dut is not NullValue, "CurrentLevel is null") - - while current_level_dut is Clusters.Objects.ValveConfigurationAndControl.Enums.ValveStateEnum.kTransitioning: - time.sleep(1) - - current_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentLevel) - asserts.assert_true(current_level_dut is not NullValue, "CurrentLevel is null") - - asserts.assert_equal(current_level_dut, 0, "CurrentLevel is not the expected value") - else: - logging.info("Test step skipped") + expected_final_state = [AttributeValue(endpoint_id=endpoint, attribute=attributes.TargetState, value=NullValue), + AttributeValue(endpoint_id=endpoint, attribute=attributes.CurrentState, + value=cluster.Enums.ValveStateEnum.kClosed), + AttributeValue(endpoint_id=endpoint, attribute=attributes.TargetLevel, value=NullValue), + AttributeValue(endpoint_id=endpoint, attribute=attributes.CurrentLevel, value=0)] + attribute_subscription.await_all_final_values_reported(expected_final_values=expected_final_state, timeout_sec=timeout) + attribute_subscription.await_all_final_values_reported(expected_final_values=expected_final_state, timeout_sec=timeout) + + self.step(9) + target_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.TargetState) + current_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentState) + target_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.TargetLevel) + current_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentLevel) + asserts.assert_equal(current_state_dut, cluster.Enums.ValveStateEnum.kClosed, "CurrentState is not closed") + asserts.assert_equal(target_state_dut, NullValue, "TargetState is not null") + asserts.assert_equal(current_level_dut, 0, "CurrentLevel is not 0") + asserts.assert_equal(target_level_dut, NullValue, "TargetLevel is not null") if __name__ == "__main__": diff --git a/src/python_testing/TC_VALCC_3_3.py b/src/python_testing/TC_VALCC_3_3.py index 97e29f9b1a82d1..2d962c22cb651a 100644 --- a/src/python_testing/TC_VALCC_3_3.py +++ b/src/python_testing/TC_VALCC_3_3.py @@ -32,13 +32,10 @@ # quiet: true # === END CI TEST ARGUMENTS === -import logging -import time - import chip.clusters as Clusters from chip.clusters.Types import NullValue -from chip.interaction_model import InteractionModelError, Status -from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from chip.testing.matter_testing import (AttributeValue, ClusterAttributeChangeAccumulator, MatterBaseTest, TestStep, + async_test_body, default_matter_test_main) from mobly import asserts @@ -53,14 +50,22 @@ def desc_TC_VALCC_3_3(self) -> str: def steps_TC_VALCC_3_3(self) -> list[TestStep]: steps = [ TestStep(1, "Commissioning, already done", is_commissioning=True), - TestStep(2, "Read AttributeList attribute"), - TestStep(3, "Read DefaultOpenLevel attribute, if supported"), - TestStep(4, "Send Open command"), - TestStep(5, "Read TargetLevel attribute"), - TestStep(6, "Read CurrentLevel attribute"), - TestStep(7, "Send Close command"), - TestStep(8, "Read TargetLevel attribute"), - TestStep(9, "Read CurrentLevel attribute"), + TestStep(2, "Read AttributeList attribute", "Verify that the DUT response contains the AttributeList attribute."), + TestStep(3, "If the DefaultOpenLevel is not supported, skip all remaining steps in this test"), + TestStep(4, "TH reads from the DUT the DefaultOpenLevel attribute. Store the value as defaultOpenLevel."), + TestStep(5, "Set up a subscription to all attributes on the DUT", "Subscription is successful"), + TestStep(6, "Send a close command to the DUT and wait until the CurrentState is reported as closed", "DUT returns SUCCESS"), + # TODO: this test should probably SET the default open attribute as well and un-set it at the end, so we're not testing against the default. + TestStep(7, "Send Open command with no fields populated", "DUT returns SUCCESS"), + TestStep(8, "Wait until TH receives the following data reports (ordering not checked): TargetState set to NULL, TargetLevel set to NULL, CurrentState set to Open, CurrentLevel set to defaultOpenLevel", + "Expected attribute reports are received"), + TestStep(9, "Read CurrentState and TargetState attribute", "CurrentState is Open, TargetState is NULL"), + TestStep(10, "Read CurrentLevel and TargetLevel attribute", "CurrentLevel is defaultOpenLevel, TargetLevel is NULL"), + TestStep(11, "Send Close command", "DUT returns SUCCESS"), + TestStep(12, "Wait until TH receives the following data reports (ordering not checked): TargetState set to NULL, TargetLevel set to NULL, CurrentState set to Closed, CurrentLevel set to 0", + "Expected attribute reports are received"), + TestStep(13, "Read CurrentState and TargetState attribute", "CurrentState is Closed, TargetState is NULL"), + TestStep(14, "Read CurrentLevel and TargetLevel attribute", "CurrentLevel is 0, TargetLevel is NULL"), ] return steps @@ -82,78 +87,75 @@ async def test_TC_VALCC_3_3(self): attribute_list = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.AttributeList) self.step(3) - if attributes.DefaultOpenLevel.attribute_id in attribute_list: - defaultOpenLevel = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.DefaultOpenLevel) - else: - logging.info("Test step skipped") + if attributes.DefaultOpenLevel.attribute_id not in attribute_list: + asserts.skip('Endpoint does not match test requirements') self.step(4) - if attributes.DefaultOpenLevel.attribute_id in attribute_list: - try: - await self.send_single_cmd(cmd=Clusters.Objects.ValveConfigurationAndControl.Commands.Open(), endpoint=endpoint) - except InteractionModelError as e: - asserts.assert_equal(e.status, Status.Success, "Unexpected error returned") - pass - else: - logging.info("Test step skipped") + default_open_level = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.DefaultOpenLevel) self.step(5) - if attributes.DefaultOpenLevel.attribute_id in attribute_list: - target_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.TargetLevel) - - asserts.assert_true(target_level_dut is not NullValue, "TargetLevel is null") - asserts.assert_equal(target_level_dut, defaultOpenLevel, "TargetLevel is not the expected value") - else: - logging.info("Test step skipped") + cluster = Clusters.ValveConfigurationAndControl + attributes = cluster.Attributes + attribute_subscription = ClusterAttributeChangeAccumulator(cluster) + await attribute_subscription.start(self.default_controller, self.dut_node_id, endpoint) self.step(6) - if attributes.DefaultOpenLevel.attribute_id in attribute_list: - current_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentLevel) - asserts.assert_true(current_level_dut is not NullValue, "CurrentLevel is null") - - while current_level_dut != defaultOpenLevel: - time.sleep(1) - - current_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentLevel) - asserts.assert_true(current_level_dut is not NullValue, "CurrentLevel is null") - - asserts.assert_equal(current_level_dut, defaultOpenLevel, "CurrentLevel is not the expected value") - else: - logging.info("Test step skipped") + timeout = self.matter_test_config.timeout if self.matter_test_config.timeout is not None else self.default_timeout + await self.send_single_cmd(cmd=cluster.Commands.Close(), endpoint=endpoint) + current_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentState) + if current_state_dut != cluster.Enums.ValveStateEnum.kClosed: + current_state_closed = AttributeValue( + endpoint_id=endpoint, attribute=attributes.CurrentState, value=cluster.Enums.ValveStateEnum.kClosed) + attribute_subscription.await_all_final_values_reported( + expected_final_values=[current_state_closed], timeout_sec=timeout) self.step(7) - if attributes.DefaultOpenLevel.attribute_id in attribute_list: - try: - await self.send_single_cmd(cmd=Clusters.Objects.ValveConfigurationAndControl.Commands.Close(), endpoint=endpoint) - except InteractionModelError as e: - asserts.assert_equal(e.status, Status.Success, "Unexpected error returned") - pass - else: - logging.info("Test step skipped") + attribute_subscription.reset() + await self.send_single_cmd(cmd=Clusters.Objects.ValveConfigurationAndControl.Commands.Open(), endpoint=endpoint) self.step(8) - if attributes.DefaultOpenLevel.attribute_id in attribute_list: - target_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.TargetLevel) - - asserts.assert_true(target_level_dut is not NullValue, "TargetLevel is null") - asserts.assert_equal(target_level_dut, 0, "TargetLevel is not the expected value") - else: - logging.info("Test step skipped") + expected_final_state = [AttributeValue(endpoint_id=endpoint, attribute=attributes.TargetState, value=NullValue), + AttributeValue(endpoint_id=endpoint, attribute=attributes.CurrentState, + value=cluster.Enums.ValveStateEnum.kOpen), + AttributeValue(endpoint_id=endpoint, attribute=attributes.TargetLevel, value=NullValue), + AttributeValue(endpoint_id=endpoint, attribute=attributes.CurrentLevel, value=default_open_level)] + attribute_subscription.await_all_final_values_reported(expected_final_values=expected_final_state, timeout_sec=timeout) self.step(9) - if attributes.DefaultOpenLevel.attribute_id in attribute_list: - current_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentLevel) - asserts.assert_true(current_level_dut is not NullValue, "CurrentLevel is null") - - while current_level_dut is Clusters.Objects.ValveConfigurationAndControl.Enums.ValveStateEnum.kTransitioning: - time.sleep(1) - - current_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentLevel) - asserts.assert_true(current_level_dut is not NullValue, "CurrentLevel is null") - - asserts.assert_equal(current_level_dut, 0, "CurrentLevel is not the expected value") - else: - logging.info("Test step skipped") + target_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.TargetState) + current_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentState) + asserts.assert_equal(current_state_dut, cluster.Enums.ValveStateEnum.kOpen, "CurrentState is not open") + asserts.assert_equal(target_state_dut, NullValue, "TargetState is not null") + + self.step(10) + target_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.TargetLevel) + current_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentLevel) + asserts.assert_equal(current_level_dut, default_open_level, "CurrentLevel is not defaultOpenLevel") + asserts.assert_equal(target_level_dut, NullValue, "TargetLevel is not null") + + self.step(11) + attribute_subscription.reset() + await self.send_single_cmd(cmd=Clusters.Objects.ValveConfigurationAndControl.Commands.Close(), endpoint=endpoint) + + self.step(12) + expected_final_state = [AttributeValue(endpoint_id=endpoint, attribute=attributes.TargetState, value=NullValue), + AttributeValue(endpoint_id=endpoint, attribute=attributes.CurrentState, + value=cluster.Enums.ValveStateEnum.kClosed), + AttributeValue(endpoint_id=endpoint, attribute=attributes.TargetLevel, value=NullValue), + AttributeValue(endpoint_id=endpoint, attribute=attributes.CurrentLevel, value=0)] + attribute_subscription.await_all_final_values_reported(expected_final_values=expected_final_state, timeout_sec=timeout) + + self.step(13) + target_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.TargetState) + current_state_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentState) + asserts.assert_equal(current_state_dut, cluster.Enums.ValveStateEnum.kClosed, "CurrentState is not open") + asserts.assert_equal(target_state_dut, NullValue, "TargetState is not null") + + self.step(14) + target_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.TargetLevel) + current_level_dut = await self.read_valcc_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentLevel) + asserts.assert_equal(current_level_dut, 0, "CurrentLevel is not 0") + asserts.assert_equal(target_level_dut, NullValue, "TargetLevel is not null") if __name__ == "__main__": diff --git a/src/python_testing/TestSpecParsingSupport.py b/src/python_testing/TestSpecParsingSupport.py index b4c908c232fa94..7ab5847a276883 100644 --- a/src/python_testing/TestSpecParsingSupport.py +++ b/src/python_testing/TestSpecParsingSupport.py @@ -21,7 +21,7 @@ import jinja2 from chip.testing.global_attribute_ids import GlobalAttributeIds from chip.testing.matter_testing import MatterBaseTest, ProblemNotice, default_matter_test_main -from chip.testing.spec_parsing import (ClusterParser, DataModelLevel, PrebuiltDataModelDirectory, SpecParsingException, XmlCluster, +from chip.testing.spec_parsing import (ClusterParser, DataModelLevel, PrebuiltDataModelDirectory, XmlCluster, add_cluster_data_from_xml, build_xml_clusters, check_clusters_for_unknown_commands, combine_derived_clusters_with_base, get_data_model_directory) from mobly import asserts @@ -276,9 +276,6 @@ def test_build_xml_override(self): asserts.assert_count_equal(string_override_check.keys(), self.spec_xml_clusters.keys(), "Mismatched cluster generation") - with asserts.assert_raises(SpecParsingException): - build_xml_clusters("baddir") - def test_spec_parsing_access(self): strs = [None, 'view', 'operate', 'manage', 'admin'] for read in strs: diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py index 3b3fb6270b613c..0ad55369e106cb 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py @@ -1124,6 +1124,12 @@ def setup_class(self): self.current_step_index = 0 self.step_start_time = datetime.now(timezone.utc) self.step_skipped = False + self.global_wildcard = asyncio.wait_for(self.default_controller.Read(self.dut_node_id, [(Clusters.Descriptor), Attribute.AttributePath(None, None, GlobalAttributeIds.ATTRIBUTE_LIST_ID), Attribute.AttributePath( + None, None, GlobalAttributeIds.FEATURE_MAP_ID), Attribute.AttributePath(None, None, GlobalAttributeIds.ACCEPTED_COMMAND_LIST_ID)]), timeout=60) + # self.stored_global_wildcard stores value of self.global_wildcard after first async call. + # Because setup_class can be called before commissioning, this variable is lazy-initialized + # where the read is deferred until the first guard function call that requires global attributes. + self.stored_global_wildcard = None def setup_test(self): self.current_step_index = 0 @@ -1455,6 +1461,66 @@ def pics_guard(self, pics_condition: bool): self.mark_current_step_skipped() return pics_condition + async def attribute_guard(self, endpoint: int, attribute: ClusterObjects.ClusterAttributeDescriptor): + """Similar to pics_guard above, except checks a condition and if False marks the test step as skipped and + returns False using attributes against attributes_list, otherwise returns True. + For example can be used to check if a test step should be run: + + self.step("1") + if self.attribute_guard(condition1_needs_to_be_true_to_execute): + # do the test for step 1 + + self.step("2") + if self.attribute_guard(condition2_needs_to_be_false_to_skip_step): + # skip step 2 if condition not met + """ + if self.stored_global_wildcard is None: + self.stored_global_wildcard = await self.global_wildcard + attr_condition = _has_attribute(wildcard=self.stored_global_wildcard, endpoint=endpoint, attribute=attribute) + if not attr_condition: + self.mark_current_step_skipped() + return attr_condition + + async def command_guard(self, endpoint: int, command: ClusterObjects.ClusterCommand): + """Similar to attribute_guard above, except checks a condition and if False marks the test step as skipped and + returns False using command id against AcceptedCmdsList, otherwise returns True. + For example can be used to check if a test step should be run: + + self.step("1") + if self.command_guard(condition1_needs_to_be_true_to_execute): + # do the test for step 1 + + self.step("2") + if self.command_guard(condition2_needs_to_be_false_to_skip_step): + # skip step 2 if condition not met + """ + if self.stored_global_wildcard is None: + self.stored_global_wildcard = await self.global_wildcard + cmd_condition = _has_command(wildcard=self.stored_global_wildcard, endpoint=endpoint, command=command) + if not cmd_condition: + self.mark_current_step_skipped() + return cmd_condition + + async def feature_guard(self, endpoint: int, cluster: ClusterObjects.ClusterObjectDescriptor, feature_int: IntFlag): + """Similar to command_guard and attribute_guard above, except checks a condition and if False marks the test step as skipped and + returns False using feature id against feature_map, otherwise returns True. + For example can be used to check if a test step should be run: + + self.step("1") + if self.feature_guard(condition1_needs_to_be_true_to_execute): + # do the test for step 1 + + self.step("2") + if self.feature_guard(condition2_needs_to_be_false_to_skip_step): + # skip step 2 if condition not met + """ + if self.stored_global_wildcard is None: + self.stored_global_wildcard = await self.global_wildcard + feat_condition = _has_feature(wildcard=self.stored_global_wildcard, endpoint=endpoint, cluster=cluster, feature=feature_int) + if not feat_condition: + self.mark_current_step_skipped() + return feat_condition + def mark_current_step_skipped(self): try: steps = self.get_test_steps(self.current_test_info.name) @@ -2105,6 +2171,41 @@ def has_attribute(attribute: ClusterObjects.ClusterAttributeDescriptor) -> Endpo return partial(_has_attribute, attribute=attribute) +def _has_command(wildcard, endpoint, command: ClusterObjects.ClusterCommand) -> bool: + cluster = get_cluster_from_command(command) + try: + cmd_list = wildcard.attributes[endpoint][cluster][cluster.Attributes.AcceptedCommandList] + if not isinstance(cmd_list, list): + asserts.fail( + f"Failed to read mandatory AcceptedCommandList command value for cluster {cluster} on endpoint {endpoint}: {cmd_list}.") + return command.command_id in cmd_list + except KeyError: + return False + + +def has_command(command: ClusterObjects.ClusterCommand) -> EndpointCheckFunction: + """ EndpointCheckFunction that can be passed as a parameter to the run_if_endpoint_matches decorator. + + Use this function with the run_if_endpoint_matches decorator to run this test on all endpoints with + the specified attribute. For example, given a device with the following conformance + + EP0: cluster A, B, C + EP1: cluster D with command d, E + EP2, cluster D with command d + EP3, cluster D without command d + + And the following test specification: + @run_if_endpoint_matches(has_command(Clusters.D.Commands.d)) + test_mytest(self): + ... + + If you run this test with --endpoint 1 or --endpoint 2, the test will be run. If you run this test + with any other --endpoint the run_if_endpoint_matches decorator will call the on_skip function to + notify the test harness that the test is not applicable to this node and the test will not be run. + """ + return partial(_has_command, command=command) + + def _has_feature(wildcard, endpoint: int, cluster: ClusterObjects.ClusterObjectDescriptor, feature: IntFlag) -> bool: try: feature_map = wildcard.attributes[endpoint][cluster][cluster.Attributes.FeatureMap] diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/spec_parsing.py b/src/python_testing/matter_testing_infrastructure/chip/testing/spec_parsing.py index 97a13606eabc45..3607f515d3a9ec 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/spec_parsing.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/spec_parsing.py @@ -15,15 +15,16 @@ # limitations under the License. # -import glob +import importlib +import importlib.resources as pkg_resources import logging -import os import typing import xml.etree.ElementTree as ElementTree from copy import deepcopy from dataclasses import dataclass from enum import Enum, auto -from typing import Callable, Optional +from importlib.abc import Traversable +from typing import Callable, Optional, Union import chip.clusters as Clusters import chip.testing.conformance as conformance_support @@ -512,56 +513,83 @@ class PrebuiltDataModelDirectory(Enum): k1_4 = auto() kMaster = auto() - -class DataModelLevel(str, Enum): - kCluster = 'clusters' - kDeviceType = 'device_types' - - -def _get_data_model_root() -> str: - """Attempts to find ${CHIP_ROOT}/data_model or equivalent.""" - - # Since this class is generally in a module, we have to rely on being bootstrapped or - # we use CWD if we cannot - choices = [os.getcwd()] - - if 'PW_PROJECT_ROOT' in os.environ: - choices.insert(0, os.environ['PW_PROJECT_ROOT']) - - for c in choices: - data_model_path = os.path.join(c, 'data_model') - if os.path.exists(os.path.join(data_model_path, 'master', 'scraper_version')): - return data_model_path - raise FileNotFoundError('Cannot find a CHIP_ROOT/data_model path. Tried %r as prefixes.' % choices) - - -def get_data_model_directory(data_model_directory: typing.Union[PrebuiltDataModelDirectory, str], data_model_level: DataModelLevel) -> str: - if data_model_directory == PrebuiltDataModelDirectory.k1_3: - return os.path.join(_get_data_model_root(), '1.3', data_model_level) - elif data_model_directory == PrebuiltDataModelDirectory.k1_4: - return os.path.join(_get_data_model_root(), '1.4', data_model_level) - elif data_model_directory == PrebuiltDataModelDirectory.kMaster: - return os.path.join(_get_data_model_root(), 'master', data_model_level) + @property + def dirname(self): + if self == PrebuiltDataModelDirectory.k1_3: + return "1.3" + if self == PrebuiltDataModelDirectory.k1_4: + return "1.4" + if self == PrebuiltDataModelDirectory.kMaster: + return "master" + raise KeyError("Invalid enum: %r" % self) + + +class DataModelLevel(Enum): + kCluster = auto() + kDeviceType = auto() + + @property + def dirname(self): + if self == DataModelLevel.kCluster: + return "clusters" + if self == DataModelLevel.kDeviceType: + return "device_types" + raise KeyError("Invalid enum: %r" % self) + + +def get_data_model_directory(data_model_directory: Union[PrebuiltDataModelDirectory, Traversable], data_model_level: DataModelLevel = DataModelLevel.kCluster) -> Traversable: + """ + Get the directory of the data model for a specific version and level from the installed package. + + + `data_model_directory` given as a path MUST be of type Traversable (often `pathlib.Path(somepathstring)`). + If `data_model_directory` is given as a Traversable, it is returned directly WITHOUT using the data_model_level at all. + """ + # If it's a prebuilt directory, build the path based on the version and data model level + if isinstance(data_model_directory, PrebuiltDataModelDirectory): + return pkg_resources.files(importlib.import_module('chip.testing')).joinpath( + 'data_model').joinpath(data_model_directory.dirname).joinpath(data_model_level.dirname) else: return data_model_directory -def build_xml_clusters(data_model_directory: typing.Union[PrebuiltDataModelDirectory, str] = PrebuiltDataModelDirectory.k1_4) -> tuple[dict[uint, XmlCluster], list[ProblemNotice]]: - dir = get_data_model_directory(data_model_directory, DataModelLevel.kCluster) +def build_xml_clusters(data_model_directory: Union[PrebuiltDataModelDirectory, Traversable] = PrebuiltDataModelDirectory.k1_4) -> typing.Tuple[dict[int, dict], list]: + """ + Build XML clusters from the specified data model directory. + This function supports both pre-built locations and full paths. + + `data_model_directory`` given as a path MUST be of type Traversable (often `pathlib.Path(somepathstring)`). + If data_model_directory is a Travesable, it is assumed to already contain `clusters` (i.e. be a directory + with all XML files in it) + """ clusters: dict[int, XmlCluster] = {} pure_base_clusters: dict[str, XmlCluster] = {} ids_by_name: dict[str, int] = {} problems: list[ProblemNotice] = [] - files = glob.glob(f'{dir}/*.xml') - if not files: - raise SpecParsingException(f'No data model files found in specified directory {dir}') - for xml in files: - logging.info(f'Parsing file {xml}') - tree = ElementTree.parse(f'{xml}') - root = tree.getroot() - add_cluster_data_from_xml(root, clusters, pure_base_clusters, ids_by_name, problems) + top = get_data_model_directory(data_model_directory, DataModelLevel.kCluster) + logging.info("Reading XML clusters from %r", top) + + found_xmls = 0 + for f in top.iterdir(): + if not f.name.endswith('.xml'): + logging.info("Ignoring non-XML file %s", f.name) + continue + + logging.info('Parsing file %s', f.name) + found_xmls += 1 + with f.open("r", encoding="utf8") as file: + root = ElementTree.parse(file).getroot() + add_cluster_data_from_xml(root, clusters, pure_base_clusters, ids_by_name, problems) + + # For now we assume even a single XML means the directory was probaly OK + # we may increase this later as most our data model directories are larger + # + # Intent here is to make user aware of typos in paths instead of silently having + # empty parsing + if found_xmls < 1: + raise SpecParsingException(f'No data model files found in specified directory {top:!r}') # There are a few clusters where the conformance columns are listed as desc. These clusters need specific, targeted tests # to properly assess conformance. Here, we list them as Optional to allow these for the general test. Targeted tests are described below. @@ -721,7 +749,7 @@ def combine_attributes(base: dict[uint, XmlAttribute], derived: dict[uint, XmlAt xml_clusters[id] = new -def parse_single_device_type(root: ElementTree.Element) -> tuple[list[ProblemNotice], dict[int, XmlDeviceType]]: +def parse_single_device_type(root: ElementTree.Element) -> tuple[dict[int, XmlDeviceType], list[ProblemNotice]]: problems: list[ProblemNotice] = [] device_types: dict[int, XmlDeviceType] = {} device = root.iter('deviceType') @@ -793,17 +821,26 @@ def parse_single_device_type(root: ElementTree.Element) -> tuple[list[ProblemNot return device_types, problems -def build_xml_device_types(data_model_directory: typing.Union[PrebuiltDataModelDirectory, str] = PrebuiltDataModelDirectory.k1_4) -> tuple[dict[int, XmlDeviceType], list[ProblemNotice]]: - dir = get_data_model_directory(data_model_directory, DataModelLevel.kDeviceType) +def build_xml_device_types(data_model_directory: typing.Union[PrebuiltDataModelDirectory, Traversable] = PrebuiltDataModelDirectory.k1_4) -> tuple[dict[int, XmlDeviceType], list[ProblemNotice]]: + top = get_data_model_directory(data_model_directory, DataModelLevel.kDeviceType) device_types: dict[int, XmlDeviceType] = {} problems = [] - for xml in glob.glob(f"{dir}/*.xml"): - logging.info(f'Parsing file {xml}') - tree = ElementTree.parse(f'{xml}') - root = tree.getroot() - tmp_device_types, tmp_problems = parse_single_device_type(root) - problems = problems + tmp_problems - device_types.update(tmp_device_types) + + found_xmls = 0 + + for file in top.iterdir(): + if not file.name.endswith('.xml'): + continue + logging.info('Parsing file %r / %s', top, file.name) + found_xmls += 1 + with file.open('r', encoding="utf8") as xml: + root = ElementTree.parse(xml).getroot() + tmp_device_types, tmp_problems = parse_single_device_type(root) + problems = problems + tmp_problems + device_types.update(tmp_device_types) + + if found_xmls < 1: + logging.warning("No XML files found in the specified device type directory: %r", top) if -1 not in device_types.keys(): raise ConformanceException("Base device type not found in device type xml data") diff --git a/src/python_testing/test_metadata.yaml b/src/python_testing/test_metadata.yaml index a6f0ba5bf6174e..dcabdeffdadb1d 100644 --- a/src/python_testing/test_metadata.yaml +++ b/src/python_testing/test_metadata.yaml @@ -97,6 +97,7 @@ slow_tests: - { name: TC_PS_2_3.py, duration: 30 seconds } - { name: TC_RR_1_1.py, duration: 25 seconds } - { name: TC_SWTCH.py, duration: 1 minute } + - { name: TC_TestAttrAvail.py, duration: 30 seconds } - { name: TC_TIMESYNC_2_10.py, duration: 20 seconds } - { name: TC_TIMESYNC_2_11.py, duration: 30 seconds } - { name: TC_TIMESYNC_2_12.py, duration: 20 seconds } diff --git a/third_party/nxp/nxp_matter_support b/third_party/nxp/nxp_matter_support index 7323d61dfc746a..2fff7067131f13 160000 --- a/third_party/nxp/nxp_matter_support +++ b/third_party/nxp/nxp_matter_support @@ -1 +1 @@ -Subproject commit 7323d61dfc746aff677cb40c17cfed9d43dd9c1d +Subproject commit 2fff7067131f130c560de9fa49f247022270ca55 diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp index afb3da76dc8bc3..10f67cad3ffd77 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp @@ -32754,53 +32754,6 @@ Protocols::InteractionModel::Status Set(EndpointId endpoint, } // namespace OccupancySensorTypeBitmap -namespace PIROccupiedToUnoccupiedDelay { - -Protocols::InteractionModel::Status Get(EndpointId endpoint, uint16_t * value) -{ - using Traits = NumericAttributeTraits<uint16_t>; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::OccupancySensing::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits<uint16_t>; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(ConcreteAttributePath(endpoint, Clusters::OccupancySensing::Id, Id), - EmberAfWriteDataInput(writable, ZCL_INT16U_ATTRIBUTE_TYPE).SetMarkDirty(markDirty)); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value) -{ - using Traits = NumericAttributeTraits<uint16_t>; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::OccupancySensing::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE); -} - -} // namespace PIROccupiedToUnoccupiedDelay - namespace PIRUnoccupiedToOccupiedDelay { Protocols::InteractionModel::Status Get(EndpointId endpoint, uint16_t * value) @@ -32895,53 +32848,6 @@ Protocols::InteractionModel::Status Set(EndpointId endpoint, uint8_t value) } // namespace PIRUnoccupiedToOccupiedThreshold -namespace UltrasonicOccupiedToUnoccupiedDelay { - -Protocols::InteractionModel::Status Get(EndpointId endpoint, uint16_t * value) -{ - using Traits = NumericAttributeTraits<uint16_t>; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::OccupancySensing::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits<uint16_t>; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(ConcreteAttributePath(endpoint, Clusters::OccupancySensing::Id, Id), - EmberAfWriteDataInput(writable, ZCL_INT16U_ATTRIBUTE_TYPE).SetMarkDirty(markDirty)); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value) -{ - using Traits = NumericAttributeTraits<uint16_t>; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::OccupancySensing::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE); -} - -} // namespace UltrasonicOccupiedToUnoccupiedDelay - namespace UltrasonicUnoccupiedToOccupiedDelay { Protocols::InteractionModel::Status Get(EndpointId endpoint, uint16_t * value) @@ -33036,53 +32942,6 @@ Protocols::InteractionModel::Status Set(EndpointId endpoint, uint8_t value) } // namespace UltrasonicUnoccupiedToOccupiedThreshold -namespace PhysicalContactOccupiedToUnoccupiedDelay { - -Protocols::InteractionModel::Status Get(EndpointId endpoint, uint16_t * value) -{ - using Traits = NumericAttributeTraits<uint16_t>; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::OccupancySensing::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits<uint16_t>; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(ConcreteAttributePath(endpoint, Clusters::OccupancySensing::Id, Id), - EmberAfWriteDataInput(writable, ZCL_INT16U_ATTRIBUTE_TYPE).SetMarkDirty(markDirty)); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value) -{ - using Traits = NumericAttributeTraits<uint16_t>; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::OccupancySensing::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE); -} - -} // namespace PhysicalContactOccupiedToUnoccupiedDelay - namespace PhysicalContactUnoccupiedToOccupiedDelay { Protocols::InteractionModel::Status Get(EndpointId endpoint, uint16_t * value) diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h index c79c0657c5b11b..d77633d6d72bbc 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h +++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h @@ -4913,12 +4913,6 @@ Protocols::InteractionModel::Status Set(EndpointId endpoint, MarkAttributeDirty markDirty); } // namespace OccupancySensorTypeBitmap -namespace PIROccupiedToUnoccupiedDelay { -Protocols::InteractionModel::Status Get(EndpointId endpoint, uint16_t * value); // int16u -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value); -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty); -} // namespace PIROccupiedToUnoccupiedDelay - namespace PIRUnoccupiedToOccupiedDelay { Protocols::InteractionModel::Status Get(EndpointId endpoint, uint16_t * value); // int16u Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value); @@ -4931,12 +4925,6 @@ Protocols::InteractionModel::Status Set(EndpointId endpoint, uint8_t value); Protocols::InteractionModel::Status Set(EndpointId endpoint, uint8_t value, MarkAttributeDirty markDirty); } // namespace PIRUnoccupiedToOccupiedThreshold -namespace UltrasonicOccupiedToUnoccupiedDelay { -Protocols::InteractionModel::Status Get(EndpointId endpoint, uint16_t * value); // int16u -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value); -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty); -} // namespace UltrasonicOccupiedToUnoccupiedDelay - namespace UltrasonicUnoccupiedToOccupiedDelay { Protocols::InteractionModel::Status Get(EndpointId endpoint, uint16_t * value); // int16u Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value); @@ -4949,12 +4937,6 @@ Protocols::InteractionModel::Status Set(EndpointId endpoint, uint8_t value); Protocols::InteractionModel::Status Set(EndpointId endpoint, uint8_t value, MarkAttributeDirty markDirty); } // namespace UltrasonicUnoccupiedToOccupiedThreshold -namespace PhysicalContactOccupiedToUnoccupiedDelay { -Protocols::InteractionModel::Status Get(EndpointId endpoint, uint16_t * value); // int16u -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value); -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty); -} // namespace PhysicalContactOccupiedToUnoccupiedDelay - namespace PhysicalContactUnoccupiedToOccupiedDelay { Protocols::InteractionModel::Status Get(EndpointId endpoint, uint16_t * value); // int16u Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value);