diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt
index d92158e3277bc1..21708845b4ccfb 100644
--- a/.github/.wordlist.txt
+++ b/.github/.wordlist.txt
@@ -465,6 +465,7 @@ EchoMessage
EchoRequests
EchoResponse
EchoService
+ECW
edaf
edc
EDR
@@ -738,6 +739,7 @@ kCase
Kconfig
kDacPublicKey
KeypadInput
+keypair
keyset
kGroup
kInvalidCommandId
@@ -884,6 +886,7 @@ mlan
MLD
mmevk
moal
+Mobly
ModeSelect
modprobe
Modustoolbox
@@ -948,6 +951,7 @@ nrfdks
nrfutil
nrfxlib
NTAG
+NTP
nullable
nullptr
NUM
@@ -1013,6 +1017,7 @@ OTBR
otcli
outform
outgoingCommands
+overridable
OxygenConcentrationMeasurement
OzoneConcentrationMeasurement
PAA
@@ -1051,6 +1056,7 @@ perfetto
periodicQueryTimeout
pexpect
pickString
+PICSCODE
PID
Pigweed
PinCode
@@ -1366,6 +1372,7 @@ TestGenExample
TestGroupDemoConfig
TestMultiRead
TestName
+TestOnlySendCommandTimedRequestFlagWithNoTimedInvoke
TESTPASSWD
TestPICS
TESTSSID
diff --git a/.github/actions/checkout-submodules-and-bootstrap/action.yaml b/.github/actions/checkout-submodules-and-bootstrap/action.yaml
index 8ddaec14e7bc47..b514b8dd795509 100644
--- a/.github/actions/checkout-submodules-and-bootstrap/action.yaml
+++ b/.github/actions/checkout-submodules-and-bootstrap/action.yaml
@@ -15,6 +15,8 @@ inputs:
runs:
using: "composite"
steps:
+ - name: Maximize runner disk
+ uses: ./.github/actions/maximize-runner-disk
- name: Dump disk info
uses: ./.github/actions/dump-disk-info
- name: Set git safe directory for local act runs
diff --git a/.github/actions/maximize-runner-disk/action.yaml b/.github/actions/maximize-runner-disk/action.yaml
new file mode 100644
index 00000000000000..fe5f95352aa53e
--- /dev/null
+++ b/.github/actions/maximize-runner-disk/action.yaml
@@ -0,0 +1,50 @@
+name: Maximize runner disk
+description: Free up disk space on the github runner
+runs:
+ using: "composite"
+ steps:
+ - name: Free up disk space on the github runner
+ if: ${{ !env.ACT }}
+ shell: bash
+ run: |
+ # maximize-runner-disk
+ if [[ "$RUNNER_OS" == Linux ]]; then
+ # Directories to prune to free up space. Candidates:
+ # 1.6G /usr/share/dotnet
+ # 1.1G /usr/local/lib/android/sdk/platforms
+ # 1000M /usr/local/lib/android/sdk/build-tools
+ # 8.9G /usr/local/lib/android/sdk
+ # This list can be amended later to change the trade-off between the amount of
+ # disk space freed up, and how long it takes to do so (deleting many files is slow).
+ prune=(/usr/share/dotnet /usr/local/lib/android/sdk/platforms /usr/local/lib/android/sdk/build-tools)
+
+ if [[ "$UID" -eq 0 && -d /__w ]]; then
+ root=/runner-root-volume
+ if [[ ! -d "$root" ]]; then
+ echo "Unable to maximize disk space, job is running inside a container and $root is not mounted"
+ exit 0
+ fi
+ function sudo() { "$@"; } # we're already root (and sudo is probably unavailable)
+ elif [[ "$UID" -ne 0 && "$RUNNER_ENVIRONMENT" == github-hosted ]]; then
+ root=
+ else
+ echo "Unable to maximize disk space, unknown runner environment"
+ exit 0
+ fi
+
+ echo "Freeing up runner disk space on ${root:-/}"
+ function avail() { df -k --output=avail "${root:-/}" | grep '^[0-9]*$'; }
+ function now() { date '+%s'; }
+ before="$(avail)" start="$(now)"
+ for dir in "${prune[@]}"; do
+ if [[ -d "${root}${dir}" ]]; then
+ echo "- $dir"
+ # du -sh -- "${root}${dir}"
+ sudo rm -rf -- "${root}${dir}"
+ else
+ echo "- $dir (not found)"
+ fi
+ done
+ after="$(avail)" end="$(now)"
+ echo "Done, freed up $(( (after - before) / 1024 ))M of disk space in $(( end - start )) seconds."
+ fi
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 23dd3d3eb0f309..e509aab995c682 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -42,6 +42,7 @@ jobs:
container:
image: ghcr.io/project-chip/chip-build:35
volumes:
+ - "/:/runner-root-volume"
- "/tmp/log_output:/tmp/test_logs"
options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0
net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1"
@@ -137,6 +138,7 @@ jobs:
container:
image: ghcr.io/project-chip/chip-build:35
volumes:
+ - "/:/runner-root-volume"
- "/tmp/log_output:/tmp/test_logs"
options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0
net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1"
@@ -221,6 +223,7 @@ jobs:
run: |
./scripts/run_in_build_env.sh "./scripts/codepregen.py ./zzz_pregenerated"
mv scripts/codegen.py scripts/codegen.py.renamed
+ mv scripts/tools/zap/generate.py scripts/tools/zap/generate.py.renamed
- name: Clean output
run: rm -rf ./out
- name: Build using build_examples.py (pregen)
@@ -232,18 +235,11 @@ jobs:
--pregen-dir ./zzz_pregenerated \
build \
"
- - name: Check no code generation in output
- run: |
- CNT=$(find out -name "CHIPClusters.h" | wc -l)
- if [ "${CNT}" != "0" ]; then
- echo "ERROR: found unexpected generated files:"
- find out -name "CHIPClusters.h"
- exit 1
- fi
- name: Undo code pre-generation changes (make compile time codegen work again)
run: |
rm -rf ./zzz_pregenerated
mv scripts/codegen.py.renamed scripts/codegen.py
+ mv scripts/tools/zap/generate.py.renamed scripts/tools/zap/generate.py
- name: Run fake linux tests with build_examples
run: |
./scripts/run_in_build_env.sh \
@@ -285,6 +281,7 @@ jobs:
container:
image: ghcr.io/project-chip/chip-build:35
volumes:
+ - "/:/runner-root-volume"
- "/tmp/log_output:/tmp/test_logs"
options: --sysctl "net.ipv6.conf.all.disable_ipv6=0
net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1"
@@ -345,6 +342,7 @@ jobs:
container:
image: ghcr.io/project-chip/chip-build:35
volumes:
+ - "/:/runner-root-volume"
- "/tmp/log_output:/tmp/test_logs"
options: --sysctl "net.ipv6.conf.all.disable_ipv6=0
net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1"
@@ -453,6 +451,7 @@ jobs:
container:
image: ghcr.io/project-chip/chip-build:35
volumes:
+ - "/:/runner-root-volume"
- "/tmp/log_output:/tmp/test_logs"
options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0
net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1"
diff --git a/.github/workflows/cirque.yaml b/.github/workflows/cirque.yaml
index 9f1bfc207f92c8..c9fe4b296d6edb 100644
--- a/.github/workflows/cirque.yaml
+++ b/.github/workflows/cirque.yaml
@@ -71,7 +71,7 @@ jobs:
- name: Get Cirque Bootstrap cache key
id: cirque-bootstrap-cache-key
run: echo "val=$(scripts/tests/cirque_tests.sh cachekeyhash)" >> $GITHUB_OUTPUT
- - uses: Wandalen/wretry.action@v1.4.4
+ - uses: Wandalen/wretry.action@v1.4.5
name: Cirque Bootstrap cache
if: ${{ !env.ACT }}
continue-on-error: true
diff --git a/.github/workflows/darwin.yaml b/.github/workflows/darwin.yaml
index 2d7443f9e9758c..088c541495665b 100644
--- a/.github/workflows/darwin.yaml
+++ b/.github/workflows/darwin.yaml
@@ -49,6 +49,11 @@ jobs:
- name: Validate zap-cli is NOT available
# run_in_build_env.sh is used to ensure PATH is set to something that would otherwise find zap-cli
run: scripts/run_in_build_env.sh '(zap-cli --version && exit 1) || exit 0'
+ - name: Run watchOS Build Debug
+ working-directory: src/darwin/Framework
+ # Disable availability annotations, since we are not building a system
+ # Matter.framework.
+ run: xcodebuild -target "Matter" -sdk watchos -configuration Debug GCC_PREPROCESSOR_DEFINITIONS='${inherited} MTR_NO_AVAILABILITY=1'
- name: Run iOS Build Debug
working-directory: src/darwin/Framework
# Disable availability annotations, since we are not building a system
@@ -105,31 +110,24 @@ jobs:
mkdir -p /tmp/darwin/framework-tests
../../../out/debug/chip-all-clusters-app --interface-id -1 > >(tee /tmp/darwin/framework-tests/all-cluster-app.log) 2> >(tee /tmp/darwin/framework-tests/all-cluster-app-err.log >&2) &
../../../out/debug/chip-all-clusters-app --interface-id -1 --dac_provider ../../../credentials/development/commissioner_dut/struct_cd_origin_pid_vid_correct/test_case_vector.json --product-id 32768 --discriminator 3839 --secured-device-port 5539 --KVS /tmp/chip-all-clusters-app-kvs2 > >(tee /tmp/darwin/framework-tests/all-cluster-app-origin-vid.log) 2> >(tee /tmp/darwin/framework-tests/all-cluster-app-origin-vid-err.log >&2) &
- # Disable BLE because the app does not have the permission to use
- # it and that may crash the CI.
- #
- # -enableUndefinedBehaviorSanitizer instruments the code in Matter.framework,
- # but to instrument the code in the underlying libCHIP we need to pass CHIP_IS_UBSAN=YES
- TEST_RUNNER_ASAN_OPTIONS=__CURRENT_VALUE__:detect_stack_use_after_return=1 xcodebuild test -target "Matter" -scheme "Matter Framework Tests" -sdk macosx -enableAddressSanitizer YES -enableUndefinedBehaviorSanitizer YES OTHER_CFLAGS='${inherited} -Werror -Wconversion' CHIP_IS_UBSAN=YES CHIP_IS_BLE=NO GCC_PREPROCESSOR_DEFINITIONS='${inherited} MTR_NO_AVAILABILITY=1'> >(tee /tmp/darwin/framework-tests/darwin-tests-asan.log) 2> >(tee /tmp/darwin/framework-tests/darwin-tests-asan-err.log >&2)
+ # Disable BLE (CHIP_IS_BLE=NO) because the app does not have the permission to use it and that may crash the CI.
+
+ TEST_RUNNER_ASAN_OPTIONS=__CURRENT_VALUE__:detect_stack_use_after_return=1 xcodebuild test -target "Matter" -scheme "Matter Framework Tests" -sdk macosx -enableAddressSanitizer YES -enableUndefinedBehaviorSanitizer YES OTHER_CFLAGS='${inherited} -Werror -Wconversion' CHIP_IS_BLE=NO GCC_PREPROCESSOR_DEFINITIONS='${inherited} MTR_NO_AVAILABILITY=1'> >(tee /tmp/darwin/framework-tests/darwin-tests-asan.log) 2> >(tee /tmp/darwin/framework-tests/darwin-tests-asan-err.log >&2)
# And the same thing, but with MTR_PER_CONTROLLER_STORAGE_ENABLED turned off, so we test that it does not break for now.
- TEST_RUNNER_ASAN_OPTIONS=__CURRENT_VALUE__:detect_stack_use_after_return=1 xcodebuild test -target "Matter" -scheme "Matter Framework Tests" -sdk macosx -enableAddressSanitizer YES -enableUndefinedBehaviorSanitizer YES OTHER_CFLAGS='${inherited} -Werror -Wconversion' CHIP_IS_UBSAN=YES CHIP_IS_BLE=NO GCC_PREPROCESSOR_DEFINITIONS='${inherited} MTR_NO_AVAILABILITY=1 MTR_PER_CONTROLLER_STORAGE_ENABLED=0' > >(tee /tmp/darwin/framework-tests/darwin-tests-asan-controller-storage.log) 2> >(tee /tmp/darwin/framework-tests/darwin-tests-asan-controller-storage-err.log >&2)
+ TEST_RUNNER_ASAN_OPTIONS=__CURRENT_VALUE__:detect_stack_use_after_return=1 xcodebuild test -target "Matter" -scheme "Matter Framework Tests" -sdk macosx -enableAddressSanitizer YES -enableUndefinedBehaviorSanitizer YES OTHER_CFLAGS='${inherited} -Werror -Wconversion' CHIP_IS_BLE=NO GCC_PREPROCESSOR_DEFINITIONS='${inherited} MTR_NO_AVAILABILITY=1 MTR_PER_CONTROLLER_STORAGE_ENABLED=0' > >(tee /tmp/darwin/framework-tests/darwin-tests-asan-controller-storage.log) 2> >(tee /tmp/darwin/framework-tests/darwin-tests-asan-controller-storage-err.log >&2)
# And the same thing, but with MTR_NO_AVAILABILITY not turned on. This requires -Wno-unguarded-availability-new to avoid availability errors.
- TEST_RUNNER_ASAN_OPTIONS=__CURRENT_VALUE__:detect_stack_use_after_return=1 xcodebuild test -target "Matter" -scheme "Matter Framework Tests" -sdk macosx -enableAddressSanitizer YES -enableUndefinedBehaviorSanitizer YES OTHER_CFLAGS='${inherited} -Werror -Wconversion -Wno-unguarded-availability-new' CHIP_IS_UBSAN=YES CHIP_IS_BLE=NO GCC_PREPROCESSOR_DEFINITIONS='${inherited}' > >(tee /tmp/darwin/framework-tests/darwin-tests-asan-with-availability-annotations.log) 2> >(tee /tmp/darwin/framework-tests/darwin-tests-asan-with-availability-annotations-err.log >&2)
- # -enableThreadSanitizer instruments the code in Matter.framework,
- # but to instrument the code in the underlying libCHIP we need to pass CHIP_IS_TSAN=YES
- xcodebuild test -target "Matter" -scheme "Matter Framework Tests" -sdk macosx -enableThreadSanitizer YES OTHER_CFLAGS='${inherited} -Werror -Wconversion' CHIP_IS_TSAN=YES CHIP_IS_BLE=NO GCC_PREPROCESSOR_DEFINITIONS='${inherited} MTR_NO_AVAILABILITY=1' > >(tee /tmp/darwin/framework-tests/darwin-tests-tsan.log) 2> >(tee /tmp/darwin/framework-tests/darwin-tests-tsan-err.log >&2)
+ TEST_RUNNER_ASAN_OPTIONS=__CURRENT_VALUE__:detect_stack_use_after_return=1 xcodebuild test -target "Matter" -scheme "Matter Framework Tests" -sdk macosx -enableAddressSanitizer YES -enableUndefinedBehaviorSanitizer YES OTHER_CFLAGS='${inherited} -Werror -Wconversion -Wno-unguarded-availability-new' CHIP_IS_BLE=NO GCC_PREPROCESSOR_DEFINITIONS='${inherited}' > >(tee /tmp/darwin/framework-tests/darwin-tests-asan-with-availability-annotations.log) 2> >(tee /tmp/darwin/framework-tests/darwin-tests-asan-with-availability-annotations-err.log >&2)
+
+ xcodebuild test -target "Matter" -scheme "Matter Framework Tests" -sdk macosx -enableThreadSanitizer YES OTHER_CFLAGS='${inherited} -Werror -Wconversion' CHIP_IS_BLE=NO GCC_PREPROCESSOR_DEFINITIONS='${inherited} MTR_NO_AVAILABILITY=1' > >(tee /tmp/darwin/framework-tests/darwin-tests-tsan.log) 2> >(tee /tmp/darwin/framework-tests/darwin-tests-tsan-err.log >&2)
working-directory: src/darwin/Framework
- name: Build Matter TV Casting Bridge
run: |
xcodebuild -target "MatterTvCastingBridge" -sdk iphoneos
working-directory: examples/tv-casting-app/darwin/MatterTvCastingBridge
- - name: Uploading .ips files in Xcode derived data to debug the failure
- uses: actions/upload-artifact@v4
- if: ${{ failure() && !env.ACT }}
- with:
- name: darwin-framework-derived-data
- path: ~/Library/Developer/Xcode/DerivedData/**/*.ips
- retention-days: 5
+ - name: Collect crash logs
+ run: |
+ mkdir -p /tmp/darwin/framework-tests
+ find ~/Library/Developer/Xcode/DerivedData /Library/Logs/DiagnosticReports -name '*.ips' -print0 | xargs -0 -J % cp % /tmp/darwin/framework-tests
- name: Uploading log files
uses: actions/upload-artifact@v4
if: ${{ failure() && !env.ACT }}
diff --git a/.github/workflows/examples-esp32.yaml b/.github/workflows/examples-esp32.yaml
index e24492d94e60a7..2317da776e6a95 100644
--- a/.github/workflows/examples-esp32.yaml
+++ b/.github/workflows/examples-esp32.yaml
@@ -71,6 +71,7 @@ jobs:
run: |
./scripts/run_in_build_env.sh "./scripts/codepregen.py ./zzz_pregenerated"
mv scripts/codegen.py scripts/codegen.py.renamed
+ mv scripts/tools/zap/generate.py scripts/tools/zap/generate.py.renamed
- name: Clean output
run: rm -rf ./out
- name: Build some M5Stack variations with pregen
@@ -84,18 +85,11 @@ jobs:
build \
--copy-artifacts-to out/artifacts \
"
- - name: Check no code generation in output
- run: |
- CNT=$(find out -name "CHIPClusters.h" | wc -l)
- if [ "${CNT}" != "0" ]; then
- echo "ERROR: found unexpected generated files:"
- find out -name "CHIPClusters.h"
- exit 1
- fi
- name: Undo code pregeneration changes
run: |
rm -rf ./zzz_pregenerated
mv scripts/codegen.py.renamed scripts/codegen.py
+ mv scripts/tools/zap/generate.py.renamed scripts/tools/zap/generate.py
- name: Build example All Clusters App C3
run: scripts/examples/esp_example.sh all-clusters-app sdkconfig_c3devkit.defaults
- name: Copy aside build products
diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml
index fadc0da4a42f3c..97617480d8f292 100644
--- a/.github/workflows/gradle-wrapper-validation.yml
+++ b/.github/workflows/gradle-wrapper-validation.yml
@@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- - uses: Wandalen/wretry.action@v1.4.4
+ - uses: Wandalen/wretry.action@v1.4.5
name: Gradle Validation
continue-on-error: true
with:
diff --git a/.github/workflows/java-tests.yaml b/.github/workflows/java-tests.yaml
index f19d451fbc2df6..8d21ca0bd4c56d 100644
--- a/.github/workflows/java-tests.yaml
+++ b/.github/workflows/java-tests.yaml
@@ -132,6 +132,17 @@ jobs:
--tool-cluster "im" \
--tool-args "onnetwork-long-im-invoke --nodeid 1 --setup-pin-code 20202021 --discriminator 3840 -t 1000" \
--factoryreset \
+ '
+ - name: Run IM Extendable Invoke Test
+ run: |
+ scripts/run_in_python_env.sh out/venv \
+ './scripts/tests/run_java_test.py \
+ --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app \
+ --app-args "--discriminator 3840 --interface-id -1" \
+ --tool-path out/linux-x64-java-matter-controller \
+ --tool-cluster "im" \
+ --tool-args "onnetwork-long-im-extendable-invoke --nodeid 1 --setup-pin-code 20202021 --discriminator 3840 -t 1000" \
+ --factoryreset \
'
- name: Run IM Read Test
run: |
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 69613217033e8b..70edd539eee0bf 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -92,16 +92,11 @@ jobs:
--known-failure controller/ExamplePersistentStorage.h \
--known-failure app/AttributeAccessInterface.h \
--known-failure app/AttributeAccessToken.h \
- --known-failure app/att-storage.h \
--known-failure app/CommandHandler.h \
--known-failure app/CommandHandlerInterface.h \
--known-failure app/CommandSenderLegacyCallback.h \
- --known-failure app/CompatEnumNames.h \
--known-failure app/data-model/ListLargeSystemExtensions.h \
- --known-failure app/EventHeader.h \
- --known-failure app/EventLoggingTypes.h \
--known-failure app/ReadHandler.h \
- --known-failure app/ReadPrepareParams.h \
--known-failure app/reporting/tests/MockReportScheduler.cpp \
--known-failure app/reporting/tests/MockReportScheduler.h \
--known-failure app/TestEventTriggerDelegate.h \
@@ -114,23 +109,19 @@ jobs:
--known-failure app/util/attribute-table.h \
--known-failure app/util/binding-table.cpp \
--known-failure app/util/binding-table.h \
- --known-failure app/util/common.h \
--known-failure app/util/config.h \
--known-failure app/util/DataModelHandler.cpp \
--known-failure app/util/DataModelHandler.h \
--known-failure app/util/ember-compatibility-functions.cpp \
--known-failure app/util/endpoint-config-api.h \
- --known-failure app/util/endpoint-config-defines.h \
--known-failure app/util/generic-callbacks.h \
--known-failure app/util/generic-callback-stubs.cpp \
--known-failure app/util/im-client-callbacks.h \
--known-failure app/util/MatterCallbacks.h \
- --known-failure app/util/message.cpp \
--known-failure app/util/odd-sized-integers.h \
--known-failure app/util/util.cpp \
--known-failure app/util/util.h \
--known-failure app/WriteHandler.h \
- --known-failure lib/core/CHIPVendorIdentifiers.hpp \
--known-failure platform/DeviceSafeQueue.cpp \
--known-failure platform/DeviceSafeQueue.h \
--known-failure platform/GLibTypeDeleter.h \
@@ -205,7 +196,7 @@ jobs:
# TODO: TLVDebug should ideally not be excluded here.
# TODO: protocol_decoder.cpp should ideally not be excluded here.
# TODO: PersistentStorageMacros.h should ideally not be excluded here.
- git grep -I -n "PRI.64" -- './*' ':(exclude).github/workflows/lint.yml' ':(exclude)examples/chip-tool' ':(exclude)examples/tv-casting-app' ':(exclude)src/app/MessageDef/MessageDefHelper.cpp' ':(exclude)src/app/tests/integration/chip_im_initiator.cpp' ':(exclude)src/lib/core/TLVDebug.cpp' ':(exclude)src/lib/dnssd/tests/TestTxtFields.cpp' ':(exclude)src/lib/format/protocol_decoder.cpp' ':(exclude)src/lib/support/PersistentStorageMacros.h' ':(exclude)src/messaging/tests/echo/echo_requester.cpp' ':(exclude)src/platform/Linux' ':(exclude)src/platform/Ameba' ':(exclude)src/platform/ESP32' ':(exclude)src/platform/webos' ':(exclude)zzz_generated/chip-tool' ':(exclude)src/tools/chip-cert/Cmd_PrintCert.cpp' && exit 1 || exit 0
+ git grep -I -n "PRI.64" -- './*' ':(exclude).github/workflows/lint.yml' ':(exclude)examples/chip-tool' ':(exclude)examples/tv-casting-app' ':(exclude)src/app/MessageDef/MessageDefHelper.cpp' ':(exclude)src/app/tests/integration/chip_im_initiator.cpp' ':(exclude)src/lib/core/TLVDebug.cpp' ':(exclude)src/lib/dnssd/tests/TestTxtFields.cpp' ':(exclude)src/lib/format/protocol_decoder.cpp' ':(exclude)src/lib/support/PersistentStorageMacros.h' ':(exclude)src/messaging/tests/echo/echo_requester.cpp' ':(exclude)src/platform/Linux' ':(exclude)src/platform/Ameba' ':(exclude)src/platform/ESP32' ':(exclude)src/platform/Darwin' ':(exclude)src/darwin' ':(exclude)src/platform/webos' ':(exclude)zzz_generated/chip-tool' ':(exclude)src/tools/chip-cert/Cmd_PrintCert.cpp' && exit 1 || exit 0
# git grep exits with 0 if it finds a match, but we want
# to fail (exit nonzero) on match. And we want to exclude this file,
diff --git a/.github/workflows/smoketest-android.yaml b/.github/workflows/smoketest-android.yaml
index 396fb3ae153a46..64efaeb82ff20f 100644
--- a/.github/workflows/smoketest-android.yaml
+++ b/.github/workflows/smoketest-android.yaml
@@ -39,6 +39,7 @@ jobs:
container:
image: ghcr.io/project-chip/chip-build-android:35
volumes:
+ - "/:/runner-root-volume"
- "/tmp/log_output:/tmp/test_logs"
steps:
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index 83d921c2fa4188..41138dd787360c 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -508,7 +508,6 @@ jobs:
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-lit-icd-ipv6only-no-ble-no-wifi-tsan-clang-test/lit-icd-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_ICDM_2_1.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS src/app/tests/suites/certification/ci-pics-values --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_IDM_1_2.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json --enable-key 000102030405060708090a0b0c0d0e0f" --script "src/python_testing/TC_IDM_1_4.py" --script-args "--hex-arg PIXIT.DGGEN.TEST_EVENT_TRIGGER_KEY:000102030405060708090a0b0c0d0e0f --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"'
- scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_IDM_4_2.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_PWRTL_2_1.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RR_1_1.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_SC_3_6.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"'
diff --git a/.github/workflows/unit_integration_test.yaml b/.github/workflows/unit_integration_test.yaml
index 62231116bb92c1..15199d4d6532e3 100644
--- a/.github/workflows/unit_integration_test.yaml
+++ b/.github/workflows/unit_integration_test.yaml
@@ -39,6 +39,7 @@ jobs:
container:
image: ghcr.io/project-chip/chip-build:35
volumes:
+ - "/:/runner-root-volume"
- "/tmp/log_output:/tmp/test_logs"
options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1"
diff --git a/.spellcheck.yml b/.spellcheck.yml
index 27a48c7de8e174..7313f64ebd6976 100644
--- a/.spellcheck.yml
+++ b/.spellcheck.yml
@@ -65,7 +65,7 @@ matrix:
# converts markdown to HTML
- pyspelling.filters.markdown:
sources:
- - '**/*.md|!third_party/**|!examples/common/**/repo/**|!docs/ERROR_CODES.md|!docs/clusters.md|!docs/testing/yaml_schema.md|!docs/testing/yaml_pseudocluster.md'
+ - '**/*.md|!third_party/**|!examples/common/**/repo/**|!docs/ERROR_CODES.md|!docs/clusters.md|!docs/testing/yaml_schema.md|!docs/testing/yaml_pseudocluster.md | !docs/testing/python.md | !docs/testing/ChipDeviceCtrlAPI.md'
aspell:
ignore-case: true
camel-case: true
diff --git a/build/chip/chip_codegen.gni b/build/chip/chip_codegen.gni
index 02acd08150aae8..ee82204af22f40 100644
--- a/build/chip/chip_codegen.gni
+++ b/build/chip/chip_codegen.gni
@@ -31,11 +31,7 @@ template("_chip_build_time_codegen") {
_name = target_name
_generator = invoker.generator
- config("${_name}_config") {
- include_dirs = [ target_gen_dir ]
- }
-
- pw_python_action("${_name}_codegen") {
+ pw_python_action("${_name}_generate") {
script = "${chip_root}/scripts/codegen.py"
# TODO: this seems to touch internals. Is this ok? speeds up builds!
@@ -99,7 +95,7 @@ template("_chip_build_time_codegen") {
if (!defined(deps)) {
deps = []
}
- deps += [ ":${_name}_codegen" ]
+ deps += [ ":${_name}_generate" ]
}
}
@@ -124,10 +120,6 @@ template("_chip_build_time_zapgen") {
_name = target_name
_generator = invoker.generator
- config("${_name}_config") {
- include_dirs = [ "${target_gen_dir}/zapgen/" ]
- }
-
assert(_generator == "app-templates")
if (_generator == "app-templates") {
@@ -152,7 +144,7 @@ template("_chip_build_time_zapgen") {
_output_subdir = "zap-generated"
}
- pw_python_action("${_name}_zap_pregen") {
+ pw_python_action("${_name}_generate") {
script = "${chip_root}/scripts/tools/zap/generate.py"
# TODO: this seems to touch internals. Is this ok? speeds up builds!
@@ -165,7 +157,7 @@ template("_chip_build_time_zapgen") {
"--templates",
_template_path,
"--output-dir",
- rebase_path(target_gen_dir) + "/zap_pregen/" + _output_subdir,
+ rebase_path(target_gen_dir) + "/zapgen/" + _output_subdir,
# TODO: lock file support should be removed as this serializes zap
# (slower), however this is currently done because on Darwin zap startup
@@ -188,54 +180,10 @@ template("_chip_build_time_zapgen") {
sources = [ _idl_file ]
- outputs = []
- foreach(name, invoker.outputs) {
- outputs += [ "${target_gen_dir}/zap_pregen/${name}" ]
- }
-
- forward_variables_from(invoker, [ "prune_outputs" ])
- if (defined(prune_outputs)) {
- foreach(name, prune_outputs) {
- outputs += [ "${target_gen_dir}/zap_pregen/${name}" ]
- }
- }
- }
-
- # This action ensures that any "extra" files generated by zap codegen
- # are actually deleted.
- #
- # This is to avoid double-codegen of configurations like endpoint config
- # or access credentials being generated for both "controller client" and
- # application-specific
- pw_python_action("${_name}_files") {
- # TODO: this seems to touch internals. Is this ok? speeds up builds!
- _pw_internal_run_in_venv = false
-
- script = "${chip_root}/scripts/tools/zap/prune_outputs.py"
-
- _keep_file = rebase_path("${target_gen_dir}/${_name}.keep.outputs")
- write_file(_keep_file, invoker.outputs, "list lines")
-
- args = [
- "--keep",
- _keep_file,
- "--input-dir",
- rebase_path("${target_gen_dir}/zap_pregen/"),
- "--output-dir",
- rebase_path("${target_gen_dir}/zapgen/"),
- ]
-
- inputs = []
- foreach(name, invoker.outputs) {
- inputs += [ "${target_gen_dir}/zap_pregen/${name}" ]
- }
-
outputs = []
foreach(name, invoker.outputs) {
outputs += [ "${target_gen_dir}/zapgen/${name}" ]
}
-
- deps = [ ":${_name}_zap_pregen" ]
}
source_set(_name) {
@@ -255,10 +203,7 @@ template("_chip_build_time_zapgen") {
if (!defined(public_deps)) {
public_deps = []
}
- public_deps += [
- ":${_name}_files",
- ":${_name}_zap_pregen",
- ]
+ public_deps += [ ":${_name}_generate" ]
}
}
@@ -272,6 +217,9 @@ template("_chip_build_time_zapgen") {
# generator
# Name of the generator to use (e.g. java-jni, java-class, cpp-app)
#
+# outputs MUST share the same directory prefix (e.g. 'app/' or 'tlv/meta'
+# or 'jni')
+#
# outputs
# Explicit names of the expected outputs. Enforced to validate that
# expected outputs are generated when processing input files.
@@ -312,7 +260,17 @@ template("_chip_build_time_zapgen") {
# ]
# }
#
+# Guarantees a target named "${target_name}_generate" exists and contains all
+# generated files (this works even in the case of using a pre-generated directory
+# by using a copy target to import pre-generated data)
+#
template("chip_codegen") {
+ _name = target_name
+
+ config("${_name}_config") {
+ include_dirs = [ target_gen_dir ]
+ }
+
if (chip_code_pre_generated_directory == "") {
_chip_build_time_codegen(target_name) {
forward_variables_from(invoker,
@@ -326,8 +284,6 @@ template("chip_codegen") {
])
}
} else {
- _name = target_name
-
not_needed(invoker, [ "options" ])
# This constructs a path like:
@@ -339,8 +295,21 @@ template("chip_codegen") {
string_replace(rebase_path(invoker.input, chip_root), ".matter", "") +
"/codegen/" + invoker.generator
- config("${_name}_config") {
- include_dirs = [ "${_generation_dir}" ]
+ # Generation in this case just involves some files copying
+ copy("${_name}_generate") {
+ sources = []
+
+ foreach(name, invoker.outputs) {
+ sources += [ "${_generation_dir}/${name}" ]
+ }
+
+ # NOTE: we assume ALL outputs have a common subdir. This is generally the case with
+ # paths like "app/callback-stub.cpp" and "app/PluginApplicationCallbacks.h"
+ _outputs = invoker.outputs
+ _dir_name = get_path_info(_outputs[0], "dir")
+ outputs = [ "${target_gen_dir}/${_dir_name}/{{source_file_part}}" ]
+
+ public_configs = [ ":${_name}_config" ]
}
source_set(_name) {
@@ -349,13 +318,13 @@ template("chip_codegen") {
if (defined(invoker.public_configs)) {
public_configs += invoker.public_configs
}
+ sources = get_target_outputs(":${_name}_generate")
forward_variables_from(invoker, [ "deps" ])
-
- sources = []
- foreach(name, invoker.outputs) {
- sources += [ "${_generation_dir}/${name}" ]
+ if (!defined(deps)) {
+ deps = []
}
+ deps += [ ":${_name}_generate" ]
}
}
}
@@ -374,6 +343,9 @@ template("chip_codegen") {
# Explicit names of the expected outputs. Enforced to validate that
# expected outputs are generated when processing input files.
#
+# outputs MUST share the same directory prefix (e.g. 'app/' or 'tlv/meta'
+# or 'jni')
+#
# deps, public_configs
# Forwarded to the resulting source set
#
@@ -399,18 +371,28 @@ template("chip_codegen") {
#
# Example usage:
#
-# chip_codegen("java-jni-generate") {
-# input = "controller-clusters.matter"
-# generator = "java-jni"
+# chip_zapgen("controller-clusters-zap") {
+# input = "controller-clusters.zap"
+# generator = "app-templates"
#
-# outputs = [
-# "jni/IdentifyClient-ReadImpl.cpp",
-# "jni/IdentifyClient-InvokeSubscribeImpl.cpp",
-# # ... more to follow
-# ]
-# }
+# outputs = [
+# "zap-generated/access.h",
+# "zap-generated/gen_config.h",
+# "zap-generated/endpoint_config.h",
+# ]
+# }
+#
+# Guarantees a target named "${target_name}_generate" exists and contains all
+# generated files (this works even in the case of using a pre-generated directory
+# by using a copy target to import pre-generated data)
#
template("chip_zapgen") {
+ _name = target_name
+
+ config("${_name}_config") {
+ include_dirs = [ "${target_gen_dir}/zapgen/" ]
+ }
+
if (chip_code_pre_generated_directory == "") {
_chip_build_time_zapgen(target_name) {
forward_variables_from(invoker,
@@ -420,12 +402,9 @@ template("chip_zapgen") {
"input",
"outputs",
"public_configs",
- "prune_outputs",
])
}
} else {
- _name = target_name
-
# This contstructs a path like:
# FROM all-clusters-app.zap (inside examples/all-clusters-app/all-clusters-common/)
# USING "cpp-app" for generator:
@@ -435,10 +414,6 @@ template("chip_zapgen") {
string_replace(rebase_path(invoker.input, chip_root), ".zap", "") +
"/zap/" + invoker.generator
- config("${_name}_config") {
- include_dirs = [ "${_generation_dir}" ]
- }
-
# Pick up only the headers and mark them available to use
# Specifically controller seems to require header files but NOT cpp (does)
# not want to include cpp compilation of IM command handler data
@@ -477,22 +452,40 @@ template("chip_zapgen") {
public_deps = [ ":${_name}_headers" ]
}
+ # Generation in this case just involves some files copying
+ copy("${_name}_generate") {
+ sources = []
+
+ foreach(name, invoker.outputs) {
+ sources += [ "${_generation_dir}/${name}" ]
+ }
+
+ # NOTE: we assume ALL outputs have a common subdir. This is generally the case with
+ # paths like "app/callback-stub.cpp" and "app/PluginApplicationCallbacks.h"
+ _outputs = invoker.outputs
+ _dir_name = get_path_info(_outputs[0], "dir")
+ outputs = [ "${target_gen_dir}/zapgen/${_dir_name}/{{source_file_part}}" ]
+
+ public_configs = [ ":${_name}_config" ]
+ }
+
source_set(_name) {
forward_variables_from(invoker,
[
"deps",
"public_configs",
- "prune_outputs",
])
if (!defined(public_configs)) {
public_configs = []
}
public_configs += [ ":${_name}_config" ]
- sources = []
- foreach(name, invoker.outputs) {
- sources += [ "${_generation_dir}/${name}" ]
+ if (!defined(public_deps)) {
+ public_deps = []
}
+ public_deps += [ ":${_name}_generate" ]
+
+ sources = get_target_outputs(":${_name}_generate")
# Ugly, but references WILL reference back into main code.
check_includes = false
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 01626726e0b9af..7eb09b79c4c22d 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -76,11 +76,11 @@ if (_chip_defaults.custom_toolchain != "") {
} else {
_target_compiler = "gcc"
}
-
_default_toolchain = "${_build_overrides.build_root}/toolchain/linux:linux_${target_cpu}_${_target_compiler}"
-} else if (target_os == host_os &&
- (target_cpu == host_cpu ||
- (target_cpu == "arm64e" && host_cpu == "arm64"))) {
+} else if (host_os == "mac" && (target_os == "mac" || target_os == "ios")) {
+ # On Mac the host toolchain supports building for all mac and ios targets
+ _default_toolchain = host_toolchain
+} else if (target_os == host_os && target_cpu == host_cpu) {
_default_toolchain = host_toolchain
} else if (target_os == "freertos") {
if (_chip_defaults.is_clang) {
@@ -113,9 +113,6 @@ if (_chip_defaults.custom_toolchain != "") {
} else {
assert(false, "Unsupported target_cpu: ${current_cpu}")
}
-} else if (target_os == "ios") {
- _default_toolchain =
- "${_build_overrides.build_root}/toolchain/ios:ios_${target_cpu}"
} else if (target_os == "tizen") {
_default_toolchain =
"${_build_overrides.build_root}/toolchain/tizen:tizen_${target_cpu}"
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index b6ad67a64944fd..df85153297cad7 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -343,7 +343,7 @@ config("cosmetic_default") {
}
config("runtime_default") {
- if (is_clang) {
+ if (is_clang) { # Using Pigweed clang instead of Darwin host clang
configs = [
"$dir_pw_toolchain/host_clang:no_system_libcpp",
"$dir_pw_toolchain/host_clang:xcode_sysroot",
@@ -395,11 +395,16 @@ declare_args() {
}
config("sanitize_address") {
+ defines = []
cflags = [
"-fsanitize=address",
"-fno-omit-frame-pointer",
]
ldflags = cflags
+
+ if ((target_os == "mac" || target_os == "ios") && !is_clang) {
+ defines += [ "_LIBCPP_HAS_NO_ASAN" ]
+ }
}
config("sanitize_thread") {
diff --git a/config/esp32/.gn b/config/esp32/.gn
index 9f5db65cdad79b..52535ffabaf95d 100644
--- a/config/esp32/.gn
+++ b/config/esp32/.gn
@@ -13,6 +13,7 @@
# limitations under the License.
import("//build_overrides/build.gni")
+import("//build_overrides/pigweed.gni")
# The location of the build configuration file.
buildconfig = "${build_root}/config/BUILDCONFIG.gn"
@@ -24,6 +25,15 @@ default_args = {
target_cpu = "esp32"
target_os = "freertos"
+ pw_sys_io_BACKEND = dir_pw_sys_io_stdio
+ pw_assert_BACKEND = dir_pw_assert_log
+ pw_log_BACKEND = dir_pw_log_basic
+
+ pw_build_LINK_DEPS = [
+ "$dir_pw_assert:impl",
+ "$dir_pw_log:impl",
+ ]
+
pw_build_PIP_CONSTRAINTS =
[ "//third_party/connectedhomeip/scripts/setup/constraints.txt" ]
pw_build_PIP_REQUIREMENTS = [
diff --git a/config/esp32/BUILD.gn b/config/esp32/BUILD.gn
index 1aacff5567ecf6..fe8c51af257713 100644
--- a/config/esp32/BUILD.gn
+++ b/config/esp32/BUILD.gn
@@ -36,6 +36,9 @@ group("esp32") {
}
if (chip_build_tests) {
- deps += [ "${chip_root}/src:tests" ]
+ deps += [
+ "${chip_root}/src:tests",
+ "${chip_root}/src/lib/support:pw_tests_wrapper",
+ ]
}
}
diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt
index 7f62ce6cc0087a..14594a03b74352 100644
--- a/config/esp32/components/chip/CMakeLists.txt
+++ b/config/esp32/components/chip/CMakeLists.txt
@@ -131,6 +131,25 @@ endif()
if(CONFIG_ENABLE_ICD_SERVER)
chip_gn_arg_append("chip_enable_icd_server" "true")
+ if(CONFIG_ICD_ENFORCE_SIT_SLOW_POLL_LIMIT)
+ chip_gn_arg_append("icd_enforce_sit_slow_poll_limit" "true")
+ endif()
+ if(CONFIG_ICD_REPORT_ON_ACTIVE_MODE)
+ chip_gn_arg_append("chip_icd_report_on_active_mode" "true")
+ endif()
+ if(CONFIG_ENABLE_ICD_LIT)
+ chip_gn_arg_append("chip_enable_icd_lit" "true")
+ if(CONFIG_ENABLE_ICD_CIP)
+ chip_gn_arg_append("chip_enable_icd_checkin" "true")
+ else()
+ chip_gn_arg_append("chip_enable_icd_checkin" "false")
+ endif()
+ if(CONFIG_ENABLE_ICD_USER_ACTIVE_MODE_TRIGGER)
+ chip_gn_arg_append("chip_enable_icd_user_active_mode_trigger" "true")
+ else()
+ chip_gn_arg_append("chip_enable_icd_user_active_mode_trigger" "false")
+ endif()
+ endif()
endif()
if(CONFIG_ENABLE_PW_RPC)
diff --git a/config/esp32/components/chip/Kconfig b/config/esp32/components/chip/Kconfig
index 0dce48b5f720be..589f33b1c70830 100644
--- a/config/esp32/components/chip/Kconfig
+++ b/config/esp32/components/chip/Kconfig
@@ -271,6 +271,12 @@ menu "CHIP Core"
Opens the commissioning window automatically at application boot time if
the node is not yet commissioned.
+ config ENABLE_SNTP_TIME_SYNC
+ bool "Enable SNTP time synchronization"
+ default n
+ help
+ Enable this option to enable SNTP time synchronization
+
endmenu # "System Options"
menu "Security Options"
@@ -340,13 +346,27 @@ menu "CHIP Device Layer"
help
Enables or Disables the support for Commissionable Device Type.
- config ENABLE_ICD_SERVER
+ menuconfig ENABLE_ICD_SERVER
bool "Enable ICD server"
depends on OPENTHREAD_MTD
default n
help
Enables or Disables ICD server
+ config ICD_ENFORCE_SIT_SLOW_POLL_LIMIT
+ bool "Enforce SIT Slow Polling Max value to 15 seconds"
+ depends on ENABLE_ICD_SERVER
+ default n
+ help
+ Set to true to enforce SIT Slow Polling Max value to 15seconds
+
+ config ICD_REPORT_ON_ACTIVE_MODE
+ bool "Emit a report on entering active mode"
+ depends on ENABLE_ICD_SERVER
+ default n
+ help
+ Make the ICD manager emit a report on entering active mode
+
config ICD_SLOW_POLL_INTERVAL_MS
int "ICD Slow Polling Interval(ms)"
depends on ENABLE_ICD_SERVER
@@ -389,14 +409,48 @@ menu "CHIP Device Layer"
This value indicates the minimum amount of time in milliseconds the server typically
will stay active after network activity when in active mode.
+ config ENABLE_ICD_LIT
+ bool "Enable Long Idle Time ICD"
+ depends on ENABLE_ICD_SERVER
+ default n
+ help
+ Enables or Disables LIT ICD
+
+ config ENABLE_ICD_CIP
+ bool "Enable Check-in protocol"
+ depends on ENABLE_ICD_LIT
+ default y
+ help
+ Enables or Disables ICD Check-in protocol
+
config ICD_CLIENTS_SUPPORTED_PER_FABRIC
int "ICD Clients Number Supported Per Fabric"
- depends on ENABLE_ICD_SERVER
+ depends on ENABLE_ICD_CIP
default 1
help
This value indicates the maximum number of entries that the ICD server is able to store
for each fabric in the RegisteredClients attribute.
+ config ICD_MAX_NOTIFICATION_SUBSCRIBERS
+ int "Max ICD notification subscribers"
+ depends on ENABLE_ICD_SERVER
+ default 1
+ help
+ The ICDManager implements the ICDListener functions and is always subscribed to the ICDNotifier
+ This allows other Matter modules to inform the ICDManager that it needs to go and may have to stay in Active Mode,
+ outside of its standard ActiveModeDuration and IdleModeDuration, without being tightly coupled the application
+ data model
+
+ This implementation also allows other modules to implement an ICDListener and subscribe to ICDNotifier
+ to couple behaviours with the ICD cycles. In such cases, ICD_MAX_NOTIFICATION_SUBSCRIBERS need to be adjusted
+
+ config ENABLE_ICD_USER_ACTIVE_MODE_TRIGGER
+ bool "Enable User Active Mode Trigger feature"
+ depends on ENABLE_ICD_LIT
+ default y
+ help
+ Enables or Disables ICD User Active Mode Trigger feature
+
config ENABLE_BG_EVENT_PROCESSING
bool "Enable Background event processing"
default n
diff --git a/config/nrfconnect/chip-gn/.gn b/config/nrfconnect/chip-gn/.gn
index bf81e1e8f52cef..b8e1a5a86cc803 100644
--- a/config/nrfconnect/chip-gn/.gn
+++ b/config/nrfconnect/chip-gn/.gn
@@ -14,6 +14,7 @@
import("//build_overrides/build.gni")
import("//build_overrides/chip.gni")
+import("//build_overrides/pigweed.gni")
# The location of the build configuration file.
buildconfig = "${build_root}/config/BUILDCONFIG.gn"
@@ -25,5 +26,14 @@ default_args = {
target_cpu = "arm"
target_os = "zephyr"
+ pw_sys_io_BACKEND = dir_pw_sys_io_stdio
+ pw_assert_BACKEND = dir_pw_assert_log
+ pw_log_BACKEND = dir_pw_log_basic
+
+ pw_build_LINK_DEPS = [
+ "$dir_pw_assert:impl",
+ "$dir_pw_log:impl",
+ ]
+
import("${chip_root}/config/nrfconnect/chip-gn/args.gni")
}
diff --git a/config/nrfconnect/chip-module/Kconfig b/config/nrfconnect/chip-module/Kconfig
index 3414bdd26c9687..c72080b7005409 100644
--- a/config/nrfconnect/chip-module/Kconfig
+++ b/config/nrfconnect/chip-module/Kconfig
@@ -206,6 +206,11 @@ choice CHIP_FACTORY_DATA_CERT_SOURCE
endchoice
+config CHIP_FACTORY_DATA_GENERATE_CD
+ bool "Generates Certification Declaration to the output build directory"
+ help
+ Generates the new Certification Declaration and stores it to the output build directory.
+
if CHIP_FACTORY_DATA_CERT_SOURCE_USER
config CHIP_FACTORY_DATA_USER_CERTS_DAC_CERT
@@ -230,6 +235,7 @@ endif # CHIP_FACTORY_DATA_CERT_SOURCE_USER
# Configs for SPAKE2+ generation
config CHIP_FACTORY_DATA_GENERATE_SPAKE2_VERIFIER
bool "Generate SPAKE2+ verifier"
+ default y
help
Enables the generation of the SPAKE2+ verifier for the configured SPAKE2+
passcode, iteration count and salt.
diff --git a/config/nrfconnect/chip-module/generate_factory_data.cmake b/config/nrfconnect/chip-module/generate_factory_data.cmake
index dc1794562d89cf..3c286fc21dddee 100644
--- a/config/nrfconnect/chip-module/generate_factory_data.cmake
+++ b/config/nrfconnect/chip-module/generate_factory_data.cmake
@@ -48,14 +48,25 @@ string(APPEND script_args "--hw_ver ${CONFIG_CHIP_DEVICE_HARDWARE_VERSION}\n")
string(APPEND script_args "--hw_ver_str \"${CONFIG_CHIP_DEVICE_HARDWARE_VERSION_STRING}\"\n")
# check if Rotating Device Id Unique Id should be generated
-if(NOT CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID)
- if(NOT DEFINED CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID)
- message(FATAL_ERROR "CHIP_DEVICE_ROTATING_DEVICE_UID was not provided. To generate it use CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID=y")
+if(CONFIG_CHIP_ROTATING_DEVICE_ID)
+ if(NOT CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID)
+ if(NOT DEFINED CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID)
+ message(FATAL_ERROR "CHIP_DEVICE_ROTATING_DEVICE_UID was not provided. To generate it use CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID=y")
+ else()
+ string(APPEND script_args "--rd_uid \"${CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID}\"\n")
+ endif()
else()
- string(APPEND script_args "--rd_uid \"${CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID}\"\n")
+ string(APPEND script_args "--generate_rd_uid\n")
endif()
-else()
- string(APPEND script_args "--generate_rd_uid\n")
+endif()
+
+if(CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_GENERATED OR CONFIG_CHIP_FACTORY_DATA_GENERATE_CD)
+ find_program(chip_cert_exe NAMES chip-cert REQUIRED)
+ string(APPEND script_args "--chip_cert_path ${chip_cert_exe}\n")
+endif()
+
+if(CONFIG_CHIP_FACTORY_DATA_GENERATE_CD)
+ string(APPEND script_args "--gen_cd\n")
endif()
# for development purpose user can use default certs instead of generating or providing them
@@ -77,10 +88,8 @@ elseif(CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_USER)
string(APPEND script_args "--dac_cert \"${CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_CERT}\"\n")
string(APPEND script_args "--dac_key \"${CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_KEY}\"\n")
string(APPEND script_args "--pai_cert \"${CONFIG_CHIP_FACTORY_DATA_USER_CERTS_PAI_CERT}\"\n")
-else()
- find_program(chip_cert_exe NAMES chip-cert REQUIRED)
- string(APPEND script_args "--gen_cd\n")
- string(APPEND script_args "--chip_cert_path ${chip_cert_exe}\n")
+elseif(CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_GENERATED)
+ string(APPEND script_args "--gen_certs\n")
endif()
# add Password-Authenticated Key Exchange parameters
@@ -90,8 +99,14 @@ string(APPEND script_args "--discriminator ${CONFIG_CHIP_DEVICE_DISCRIMINATOR}\n
string(APPEND script_args "--passcode ${CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE}\n")
string(APPEND script_args "--include_passcode\n")
string(APPEND script_args "--overwrite\n")
-string(APPEND script_args "--product_finish ${CONFIG_CHIP_DEVICE_PRODUCT_FINISH}\n")
+# check if spake2 verifier should be generated using script
+if(NOT CONFIG_CHIP_FACTORY_DATA_GENERATE_SPAKE2_VERIFIER)
+ # Spake2 verifier should be provided using kConfig
+ string(APPEND script_args "--spake2_verifier \"${CONFIG_CHIP_DEVICE_SPAKE2_TEST_VERIFIER}\"\n")
+endif()
+# Product appearance
+string(APPEND script_args "--product_finish ${CONFIG_CHIP_DEVICE_PRODUCT_FINISH}\n")
if(CONFIG_CHIP_DEVICE_PRODUCT_COLOR)
string(APPEND script_args "--product_color ${CONFIG_CHIP_DEVICE_PRODUCT_COLOR}\n")
endif()
@@ -100,12 +115,6 @@ if(CONFIG_CHIP_FACTORY_DATA_GENERATE_ONBOARDING_CODES)
string(APPEND script_args "--generate_onboarding\n")
endif()
-# check if spake2 verifier should be generated using script
-if(NOT CONFIG_CHIP_FACTORY_DATA_GENERATE_SPAKE2_VERIFIER)
- # Spake2 verifier should be provided using kConfig
- string(APPEND script_args "--spake2_verifier \"${CONFIG_CHIP_DEVICE_SPAKE2_TEST_VERIFIER}\"\n")
-endif()
-
if(CONFIG_CHIP_DEVICE_ENABLE_KEY)
# Add optional EnableKey that triggers user-specific action.
string(APPEND script_args "--enable_key \"${CONFIG_CHIP_DEVICE_ENABLE_KEY}\"\n")
diff --git a/data_model/clusters/Binding-Cluster.xml b/data_model/clusters/Binding-Cluster.xml
index eca291a7d895ff..937b9164e2a4f8 100644
--- a/data_model/clusters/Binding-Cluster.xml
+++ b/data_model/clusters/Binding-Cluster.xml
@@ -78,6 +78,7 @@ Davis, CA 95616, USA
+
diff --git a/data_model/clusters/ColorControl.xml b/data_model/clusters/ColorControl.xml
index b913009f852761..14d471b78a3043 100644
--- a/data_model/clusters/ColorControl.xml
+++ b/data_model/clusters/ColorControl.xml
@@ -107,6 +107,7 @@ Davis, CA 95616, USA
+
diff --git a/data_model/clusters/DoorLock.xml b/data_model/clusters/DoorLock.xml
index 6284b973eb63e1..16d26420fe2009 100644
--- a/data_model/clusters/DoorLock.xml
+++ b/data_model/clusters/DoorLock.xml
@@ -57,7 +57,7 @@ Davis, CA 95616, USA
:xrefstyle: basic
-->
-
+
@@ -66,7 +66,6 @@ Davis, CA 95616, USA
-
@@ -104,19 +103,14 @@ Davis, CA 95616, USA
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -130,14 +124,6 @@ Davis, CA 95616, USA
-
-
-
-
-
-
-
-
@@ -220,23 +206,6 @@ Davis, CA 95616, USA
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
-
@@ -370,21 +339,6 @@ Davis, CA 95616, USA
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
-
@@ -533,11 +487,6 @@ Davis, CA 95616, USA
- -
-
-
-
-
-
@@ -1109,81 +1058,6 @@ Davis, CA 95616, USA
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -2059,13 +1933,6 @@ Davis, CA 95616, USA
-
-
-
-
-
-
-
@@ -2092,36 +1959,6 @@ Davis, CA 95616, USA
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data_model/clusters/GeneralCommissioningCluster.xml b/data_model/clusters/GeneralCommissioningCluster.xml
index 635a6635990654..e7877635bbac68 100644
--- a/data_model/clusters/GeneralCommissioningCluster.xml
+++ b/data_model/clusters/GeneralCommissioningCluster.xml
@@ -128,5 +128,62 @@ Davis, CA 95616, USA
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data_model/clusters/ICDManagement.xml b/data_model/clusters/ICDManagement.xml
index 2a770a4f97f2b4..534b8340143083 100644
--- a/data_model/clusters/ICDManagement.xml
+++ b/data_model/clusters/ICDManagement.xml
@@ -69,6 +69,7 @@ Davis, CA 95616, USA
+
@@ -77,6 +78,7 @@ Davis, CA 95616, USA
+
@@ -84,7 +86,10 @@ Davis, CA 95616, USA
-
+
+
+
+
@@ -156,9 +161,12 @@ Davis, CA 95616, USA
-
-
-
+
+
+
+
+
+
@@ -168,9 +176,12 @@ Davis, CA 95616, USA
-
-
-
+
+
+
+
+
+
diff --git a/data_model/clusters/LevelControl.xml b/data_model/clusters/LevelControl.xml
index 6b2b3cace52ec3..13522bf0698b9e 100644
--- a/data_model/clusters/LevelControl.xml
+++ b/data_model/clusters/LevelControl.xml
@@ -126,6 +126,7 @@ Davis, CA 95616, USA
+
diff --git a/data_model/clusters/MediaPlayback.xml b/data_model/clusters/MediaPlayback.xml
index 0a457a446208dd..e9194b6854c569 100644
--- a/data_model/clusters/MediaPlayback.xml
+++ b/data_model/clusters/MediaPlayback.xml
@@ -202,6 +202,7 @@ Davis, CA 95616, USA
+
@@ -389,12 +390,13 @@ Davis, CA 95616, USA
-
+
-
-
+
+
+
@@ -404,7 +406,7 @@ Davis, CA 95616, USA
-
+
diff --git a/data_model/clusters/Messages.xml b/data_model/clusters/Messages.xml
index cea28ac15f54c9..61f21bef9c95f3 100644
--- a/data_model/clusters/Messages.xml
+++ b/data_model/clusters/Messages.xml
@@ -186,15 +186,11 @@ Davis, CA 95616, USA
-
-
-
+
-
-
-
+
@@ -216,7 +212,7 @@ Davis, CA 95616, USA
-
+
@@ -268,18 +264,20 @@ Davis, CA 95616, USA
-
+
+
+
@@ -288,6 +286,7 @@ Davis, CA 95616, USA
+
diff --git a/data_model/clusters/NetworkCommissioningCluster.xml b/data_model/clusters/NetworkCommissioningCluster.xml
index 86c7a01ce9f951..745a659f1b900b 100644
--- a/data_model/clusters/NetworkCommissioningCluster.xml
+++ b/data_model/clusters/NetworkCommissioningCluster.xml
@@ -59,8 +59,7 @@ Davis, CA 95616, USA
-
+
@@ -76,11 +75,6 @@ Added support for Wi-Fi Per-Device Credentials (PDC feature; QueryIdentity and Q
-
-
-
-
-
@@ -177,9 +171,6 @@ Added support for Wi-Fi Per-Device Credentials (PDC feature; QueryIdentity and Q
-
-
-
@@ -189,22 +180,6 @@ Added support for Wi-Fi Per-Device Credentials (PDC feature; QueryIdentity and Q
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -431,18 +406,6 @@ Added support for Wi-Fi Per-Device Credentials (PDC feature; QueryIdentity and Q
-
-
-
-
-
-
-
-
-
-
-
-
@@ -492,18 +455,6 @@ Added support for Wi-Fi Per-Device Credentials (PDC feature; QueryIdentity and Q
-
-
-
-
-
-
-
-
-
-
-
-
@@ -559,32 +510,5 @@ Added support for Wi-Fi Per-Device Credentials (PDC feature; QueryIdentity and Q
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/data_model/clusters/NetworkIdentityManagement.xml b/data_model/clusters/NetworkIdentityManagement.xml
index 8769b68583e4b9..20e264277a4330 100644
--- a/data_model/clusters/NetworkIdentityManagement.xml
+++ b/data_model/clusters/NetworkIdentityManagement.xml
@@ -57,14 +57,14 @@ Davis, CA 95616, USA
:xrefstyle: basic
-->
-
+
-
+
-
+
diff --git a/data_model/clusters/OperationalState.xml b/data_model/clusters/OperationalState.xml
index 0062b38b4b3981..37dc6b6e2f8cf4 100644
--- a/data_model/clusters/OperationalState.xml
+++ b/data_model/clusters/OperationalState.xml
@@ -65,6 +65,17 @@ Davis, CA 95616, USA
+
+ -
+
+
+ -
+
+
+ -
+
+
+
-
@@ -77,18 +88,7 @@ Davis, CA 95616, USA
-
-
- -
-
-
- -
-
-
- -
-
-
-
+
diff --git a/data_model/clusters/PowerSourceCluster.xml b/data_model/clusters/PowerSourceCluster.xml
index ffd628de6686b8..28a9154116ed7c 100644
--- a/data_model/clusters/PowerSourceCluster.xml
+++ b/data_model/clusters/PowerSourceCluster.xml
@@ -55,11 +55,10 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
-
@@ -82,16 +81,6 @@ Davis, CA 95616, USA
-
-
-
-
-
-
-
-
-
-
@@ -229,24 +218,6 @@ Davis, CA 95616, USA
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
-
@@ -259,23 +230,6 @@ Davis, CA 95616, USA
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
-
-
@@ -289,12 +243,6 @@ Davis, CA 95616, USA
-
- -
-
-
- -
-
-
-
@@ -541,17 +489,6 @@ Davis, CA 95616, USA
-
- -
-
-
- -
-
-
- -
-
-
-
-
@@ -838,125 +775,7 @@ Davis, CA 95616, USA
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -1006,77 +825,5 @@ Davis, CA 95616, USA
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/data_model/clusters/Thermostat.xml b/data_model/clusters/Thermostat.xml
index 756e27940c2cba..71a0c48c6a8eb8 100644
--- a/data_model/clusters/Thermostat.xml
+++ b/data_model/clusters/Thermostat.xml
@@ -55,7 +55,7 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
@@ -63,7 +63,6 @@ Davis, CA 95616, USA
-
@@ -106,17 +105,6 @@ Davis, CA 95616, USA
-
-
-
-
-
-
-
-
-
-
-
@@ -227,36 +215,13 @@ Davis, CA 95616, USA
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
-
-
-
-
-
-
-
+
-
@@ -410,14 +375,6 @@ Davis, CA 95616, USA
-
-
-
-
-
-
-
-
@@ -497,149 +454,6 @@ Davis, CA 95616, USA
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -1012,107 +826,6 @@ Davis, CA 95616, USA
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -1223,67 +936,5 @@ Davis, CA 95616, USA
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/data_model/clusters/TimeSync.xml b/data_model/clusters/TimeSync.xml
index 99ec173bc7e6e1..c6c57ece628bbd 100644
--- a/data_model/clusters/TimeSync.xml
+++ b/data_model/clusters/TimeSync.xml
@@ -100,6 +100,59 @@ Davis, CA 95616, USA
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
-
@@ -157,6 +210,163 @@ Davis, CA 95616, USA
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data_model/clusters/WaterHeaterManagement.xml b/data_model/clusters/WaterHeaterManagement.xml
index 4b6368555bf1d6..cc641c8269fb3c 100644
--- a/data_model/clusters/WaterHeaterManagement.xml
+++ b/data_model/clusters/WaterHeaterManagement.xml
@@ -134,7 +134,7 @@ Davis, CA 95616, USA
-
+
diff --git a/data_model/clusters/WiFiNetworkManagement.xml b/data_model/clusters/WiFiNetworkManagement.xml
index fbb7a84a4e17b2..1a3fceec2747d3 100644
--- a/data_model/clusters/WiFiNetworkManagement.xml
+++ b/data_model/clusters/WiFiNetworkManagement.xml
@@ -62,9 +62,9 @@ Davis, CA 95616, USA
-
+
-
+
diff --git a/data_model/clusters/bridge-clusters-BridgedDeviceBasicInformationCluster.xml b/data_model/clusters/bridge-clusters-BridgedDeviceBasicInformationCluster.xml
index 1dd336ef3656a3..db85cc296b8922 100644
--- a/data_model/clusters/bridge-clusters-BridgedDeviceBasicInformationCluster.xml
+++ b/data_model/clusters/bridge-clusters-BridgedDeviceBasicInformationCluster.xml
@@ -150,6 +150,9 @@ Davis, CA 95616, USA
+
+
+
diff --git a/data_model/device_types/BaseDeviceType.xml b/data_model/device_types/BaseDeviceType.xml
index 22cec956aa6061..0df3ba00d26e2b 100644
--- a/data_model/device_types/BaseDeviceType.xml
+++ b/data_model/device_types/BaseDeviceType.xml
@@ -62,4 +62,30 @@ Davis, CA 95616, USA
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data_model/device_types/BasicVideoPlayer.xml b/data_model/device_types/BasicVideoPlayer.xml
index 75d54e18d1c33f..2b9b52c3b43ee6 100644
--- a/data_model/device_types/BasicVideoPlayer.xml
+++ b/data_model/device_types/BasicVideoPlayer.xml
@@ -55,10 +55,11 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
@@ -68,6 +69,9 @@ Davis, CA 95616, USA
+
+
+
@@ -94,5 +98,11 @@ Davis, CA 95616, USA
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data_model/device_types/CastingVideoClient.xml b/data_model/device_types/CastingVideoClient.xml
index 8089f57507dd18..d79506b9cf66a0 100644
--- a/data_model/device_types/CastingVideoClient.xml
+++ b/data_model/device_types/CastingVideoClient.xml
@@ -55,10 +55,11 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
@@ -69,6 +70,9 @@ Davis, CA 95616, USA
+
+
+
@@ -105,5 +109,14 @@ Davis, CA 95616, USA
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data_model/device_types/CastingVideoPlayer.xml b/data_model/device_types/CastingVideoPlayer.xml
index 9997b276a6af5e..336416508660a8 100644
--- a/data_model/device_types/CastingVideoPlayer.xml
+++ b/data_model/device_types/CastingVideoPlayer.xml
@@ -55,10 +55,11 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
@@ -71,6 +72,9 @@ launch Content Apps and represent these apps as separate endpoints."/>
+
+
+
@@ -113,5 +117,11 @@ launch Content Apps and represent these apps as separate endpoints."/>
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data_model/device_types/ColorDimmerSwitch.xml b/data_model/device_types/ColorDimmerSwitch.xml
index 0adcfcedcdc92a..0da15b82a2cd08 100644
--- a/data_model/device_types/ColorDimmerSwitch.xml
+++ b/data_model/device_types/ColorDimmerSwitch.xml
@@ -55,11 +55,12 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
diff --git a/data_model/device_types/ColorTemperatureLight.xml b/data_model/device_types/ColorTemperatureLight.xml
index 5d6ac140803e23..5a54a36a7a0fbf 100644
--- a/data_model/device_types/ColorTemperatureLight.xml
+++ b/data_model/device_types/ColorTemperatureLight.xml
@@ -55,12 +55,13 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
diff --git a/data_model/device_types/ContentApp.xml b/data_model/device_types/ContentApp.xml
index 0db03141e7f9a1..84bf58698f426d 100644
--- a/data_model/device_types/ContentApp.xml
+++ b/data_model/device_types/ContentApp.xml
@@ -55,13 +55,19 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
+
+
+
+
+
@@ -91,5 +97,10 @@ Davis, CA 95616, USA
+
+
+
+
+
\ No newline at end of file
diff --git a/data_model/device_types/ControlBridge.xml b/data_model/device_types/ControlBridge.xml
index f97439b77f8c3b..f427becc14f791 100644
--- a/data_model/device_types/ControlBridge.xml
+++ b/data_model/device_types/ControlBridge.xml
@@ -55,12 +55,13 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
diff --git a/data_model/device_types/CookSurface.xml b/data_model/device_types/CookSurface.xml
index a9548d3ac6e3dd..b18897b3f0f9ff 100644
--- a/data_model/device_types/CookSurface.xml
+++ b/data_model/device_types/CookSurface.xml
@@ -62,6 +62,14 @@ Davis, CA 95616, USA
+
+
+
+
+
+
+
+
diff --git a/data_model/device_types/DeviceEnergyManagement.xml b/data_model/device_types/DeviceEnergyManagement.xml
index 9d993a9454ea15..cf148dabc13679 100644
--- a/data_model/device_types/DeviceEnergyManagement.xml
+++ b/data_model/device_types/DeviceEnergyManagement.xml
@@ -62,10 +62,16 @@ Davis, CA 95616, USA
-
+
+
+
+
-
+
+
+
+
\ No newline at end of file
diff --git a/data_model/device_types/DimmableLight.xml b/data_model/device_types/DimmableLight.xml
index 42c7d20fb4caad..ce0c280de6f0a6 100644
--- a/data_model/device_types/DimmableLight.xml
+++ b/data_model/device_types/DimmableLight.xml
@@ -55,11 +55,12 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
diff --git a/data_model/device_types/DimmablePlug-InUnit.xml b/data_model/device_types/DimmablePlug-InUnit.xml
index a41db3ad0ae255..98895640fe1bc5 100644
--- a/data_model/device_types/DimmablePlug-InUnit.xml
+++ b/data_model/device_types/DimmablePlug-InUnit.xml
@@ -55,12 +55,13 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
diff --git a/data_model/device_types/DimmerSwitch.xml b/data_model/device_types/DimmerSwitch.xml
index 8be246f3a16056..137adfd9117cf7 100644
--- a/data_model/device_types/DimmerSwitch.xml
+++ b/data_model/device_types/DimmerSwitch.xml
@@ -55,11 +55,12 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
diff --git a/data_model/device_types/DoorLock.xml b/data_model/device_types/DoorLock.xml
index b7a0beaa3946e6..9b6c7fd145621d 100644
--- a/data_model/device_types/DoorLock.xml
+++ b/data_model/device_types/DoorLock.xml
@@ -55,11 +55,12 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
@@ -70,41 +71,12 @@ Davis, CA 95616, USA
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -118,10 +90,11 @@ Davis, CA 95616, USA
-
-
-
-
+
+
+
+
+
@@ -130,54 +103,7 @@ Davis, CA 95616, USA
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/data_model/device_types/DoorLockController.xml b/data_model/device_types/DoorLockController.xml
index 0e4529c8b5e381..0279f0100a5fc0 100644
--- a/data_model/device_types/DoorLockController.xml
+++ b/data_model/device_types/DoorLockController.xml
@@ -55,26 +55,28 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
+
-
+
+
+
+
-
-
-
diff --git a/data_model/device_types/ExtendedColorLight.xml b/data_model/device_types/ExtendedColorLight.xml
index 73490485fa27fa..97cb3eaf66377c 100644
--- a/data_model/device_types/ExtendedColorLight.xml
+++ b/data_model/device_types/ExtendedColorLight.xml
@@ -55,12 +55,13 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
diff --git a/data_model/device_types/GenericSwitch.xml b/data_model/device_types/GenericSwitch.xml
index 24645b511ea5e7..e381914be42921 100644
--- a/data_model/device_types/GenericSwitch.xml
+++ b/data_model/device_types/GenericSwitch.xml
@@ -55,11 +55,12 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
diff --git a/data_model/device_types/NetworkInfraManager.xml b/data_model/device_types/NetworkInfraManager.xml
index cc7e22295f40be..67c3ee49f75f92 100644
--- a/data_model/device_types/NetworkInfraManager.xml
+++ b/data_model/device_types/NetworkInfraManager.xml
@@ -55,17 +55,17 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
-
+
-
+
diff --git a/data_model/device_types/OnOffLight.xml b/data_model/device_types/OnOffLight.xml
index 9762c718dcc05b..59e8739cab0275 100644
--- a/data_model/device_types/OnOffLight.xml
+++ b/data_model/device_types/OnOffLight.xml
@@ -55,11 +55,12 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
diff --git a/data_model/device_types/OnOffLightSwitch.xml b/data_model/device_types/OnOffLightSwitch.xml
index eb2c3ff938060a..9b9d72ba4f0964 100644
--- a/data_model/device_types/OnOffLightSwitch.xml
+++ b/data_model/device_types/OnOffLightSwitch.xml
@@ -55,11 +55,12 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
diff --git a/data_model/device_types/OnOffPlug-inUnit.xml b/data_model/device_types/OnOffPlug-inUnit.xml
index 41d0a1398ad6f3..4b4f49725cf9fa 100644
--- a/data_model/device_types/OnOffPlug-inUnit.xml
+++ b/data_model/device_types/OnOffPlug-inUnit.xml
@@ -55,11 +55,12 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
diff --git a/data_model/device_types/OnOffSensor.xml b/data_model/device_types/OnOffSensor.xml
index 904b5f6da74c7c..e1bd3c3806c8a4 100644
--- a/data_model/device_types/OnOffSensor.xml
+++ b/data_model/device_types/OnOffSensor.xml
@@ -55,12 +55,13 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
diff --git a/data_model/device_types/Pump.xml b/data_model/device_types/Pump.xml
index 4662ce0945b06d..9ab8700abb10f5 100644
--- a/data_model/device_types/Pump.xml
+++ b/data_model/device_types/Pump.xml
@@ -55,11 +55,12 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
diff --git a/data_model/device_types/PumpController.xml b/data_model/device_types/PumpController.xml
index 274eefb764de41..ca1486e4ea657e 100644
--- a/data_model/device_types/PumpController.xml
+++ b/data_model/device_types/PumpController.xml
@@ -55,11 +55,12 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
diff --git a/data_model/device_types/RoomAirConditioner.xml b/data_model/device_types/RoomAirConditioner.xml
index 888ec8a448a501..e8c557a21800b9 100644
--- a/data_model/device_types/RoomAirConditioner.xml
+++ b/data_model/device_types/RoomAirConditioner.xml
@@ -55,9 +55,10 @@ Connectivity Standards Alliance +
508 Second Street, Suite 206 +
Davis, CA 95616, USA
-->
-
+
+
@@ -85,6 +86,14 @@ Davis, CA 95616, USA
+
+
+
+
+
+
+
+
diff --git a/data_model/device_types/RootNodeDeviceType.xml b/data_model/device_types/RootNodeDeviceType.xml
index 1696791ab8a2b3..57b204036092c7 100644
--- a/data_model/device_types/RootNodeDeviceType.xml
+++ b/data_model/device_types/RootNodeDeviceType.xml
@@ -153,5 +153,27 @@ Davis, CA 95616, USA
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data_model/device_types/Thermostat.xml b/data_model/device_types/Thermostat.xml
index cbdedb7c039ed5..9f5c8e7de5b11c 100644
--- a/data_model/device_types/Thermostat.xml
+++ b/data_model/device_types/Thermostat.xml
@@ -55,11 +55,12 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
@@ -97,15 +98,18 @@ Davis, CA 95616, USA
-
-
-
-
+
+
+
+
+
+
+
diff --git a/data_model/device_types/VideoRemoteControl.xml b/data_model/device_types/VideoRemoteControl.xml
index eafa4cd63780b2..33bab95b9207c1 100644
--- a/data_model/device_types/VideoRemoteControl.xml
+++ b/data_model/device_types/VideoRemoteControl.xml
@@ -55,10 +55,11 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
@@ -102,5 +103,11 @@ Davis, CA 95616, USA
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data_model/device_types/WindowCovering.xml b/data_model/device_types/WindowCovering.xml
index 1a56bbd753f63a..b9a33b47ac4d9b 100644
--- a/data_model/device_types/WindowCovering.xml
+++ b/data_model/device_types/WindowCovering.xml
@@ -55,11 +55,12 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
diff --git a/data_model/device_types/WindowCoveringController.xml b/data_model/device_types/WindowCoveringController.xml
index 5bae9d81103247..76f0cf1b1e2147 100644
--- a/data_model/device_types/WindowCoveringController.xml
+++ b/data_model/device_types/WindowCoveringController.xml
@@ -55,11 +55,12 @@ Connectivity Standards Alliance
508 Second Street, Suite 206
Davis, CA 95616, USA
-->
-
+
+
diff --git a/data_model/spec_sha b/data_model/spec_sha
index 97f7f06deb9fe9..e9d780b94f334a 100644
--- a/data_model/spec_sha
+++ b/data_model/spec_sha
@@ -1 +1 @@
-b0310bae0264a29665f23a8f3d4dc4f742be6075
+c1a1e1e6bcf201334eb0b5216a464b39d9827ec4
diff --git a/docs/cluster_and_device_type_dev/cluster_and_device_type_dev.md b/docs/cluster_and_device_type_dev/cluster_and_device_type_dev.md
index 9e34e961ae6d87..f4c1c5eb890e71 100644
--- a/docs/cluster_and_device_type_dev/cluster_and_device_type_dev.md
+++ b/docs/cluster_and_device_type_dev/cluster_and_device_type_dev.md
@@ -16,14 +16,17 @@ types in the SDK.
- XML
- Describes the structures, enums, attributes, commands, events etc.
- Direct translation of the spec into code
- - src/app/zap-templates/zcl/data-model/chip/
+ - [src/app/zap-templates/zcl/data-model/chip/](https://github.com/project-chip/connectedhomeip/tree/master/src/app/zap-templates/zcl/data-model/chip)
- Cluster Implementation
- Client side - codegen, you write the glue
- Server side - cpp implementation through Ember and / or
- AttributeAccessInterface & CommandHandlerInterface
+ [AttributeAccessInterface](https://github.com/project-chip/connectedhomeip/blob/master/src/app/AttributeAccessInterface.h)
+ and
+ [CommandHandlerInterface](https://github.com/project-chip/connectedhomeip/blob/master/src/app/CommandHandlerInterface.h)
- src/app/clusters/
- - build file: src/app/chip_data_model.gni
+ - build file:
+ [src/app/chip_data_model.gni](https://github.com/project-chip/connectedhomeip/blob/master/src/app/chip_data_model.gni)
- build file uses data from the codegen to auto-populate the cluster
list.
- Follow examples in there to get your code building into the image
@@ -31,7 +34,7 @@ types in the SDK.
- Device Type Definitions
- XML defines conformance
- - src/app/zap-templates/zcl/data-model/chip/matter-devices.xml
+ - [src/app/zap-templates/zcl/data-model/chip/matter-devices.xml](https://github.com/project-chip/connectedhomeip/blob/master/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml)
The following wiki page has a detailed description of how and where to add
cluster and device type definitions so they are picked up properly by ZAP/ember
@@ -208,7 +211,7 @@ be used across examples
##### Command Handler Code
-- CommandHandlerInterface
+- [CommandHandlerInterface](https://github.com/project-chip/connectedhomeip/blob/master/src/app/CommandHandlerInterface.h)
- Can use HandleCommand function for convenience (sets handled)
- If not, need to set whether the command was handled
- if no, falls through to ember by default
@@ -238,7 +241,9 @@ pure CommandHandlerInterface implementations.
- **MatterReportingAttributeChangeCallback**
- **Events**
- No direct ember support
- - Call LogEvent function in EventLogging.h
+ - Call LogEvent function in EventLogging.h. Caller has to either lock the
+ Matter stack lock or queue the event to the Matter event queue when
+ using LogEvent.
#### A note on Dynamic Endpoints
diff --git a/docs/cluster_and_device_type_dev/img/cluster_commands.png b/docs/cluster_and_device_type_dev/img/cluster_commands.png
index 959774e071b717..c04dbe7279b28b 100644
Binary files a/docs/cluster_and_device_type_dev/img/cluster_commands.png and b/docs/cluster_and_device_type_dev/img/cluster_commands.png differ
diff --git a/docs/guides/nrfconnect_factory_data_configuration.md b/docs/guides/nrfconnect_factory_data_configuration.md
index d30a12f1e82025..e4c3be4899df4e 100644
--- a/docs/guides/nrfconnect_factory_data_configuration.md
+++ b/docs/guides/nrfconnect_factory_data_configuration.md
@@ -51,6 +51,7 @@ data secure by applying hardware write protection.
- [Building an example with factory data](#building-an-example-with-factory-data)
- [Providing factory data parameters as a build argument list](#providing-factory-data-parameters-as-a-build-argument-list)
- [Setting factory data parameters using interactive Kconfig interfaces](#setting-factory-data-parameters-using-interactive-kconfig-interfaces)
+ - [Default Kconfig values and developing aspects](#default-kconfig-values-and-developing-aspects)
- [Programming factory data](#programming-factory-data)
- [Using own factory data implementation](#using-own-factory-data-implementation)
@@ -272,6 +273,7 @@ To use this script, complete the following steps:
```
--chip_cert_path
+ --gen_certs
```
> **Note:** To generate new certificates, you need the `chip-cert`
@@ -293,7 +295,7 @@ To use this script, complete the following steps:
--rd_uid
```
- - Generate a new ID and provide it ():
+ - (optional) Generate a new ID and provide it:
```
--generate_rd_uid
@@ -328,6 +330,17 @@ To use this script, complete the following steps:
--product_color
```
+ j. (optional) Generate Certification Declaration for testing purposes
+
+ ```
+ --chip_cert_path
+ --gen_cd
+ ```
+
+ > **Note:** To generate new Certification Declaration, you need the
+ > `chip-cert` executable. See the note at the end of this section to learn
+ > how to get it.
+
4. Run the script using the prepared list of arguments:
```
@@ -794,6 +807,55 @@ snippet:
> interfaces, read the
> [Kconfig documentation](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/build/kconfig/menuconfig.html).
+### Default Kconfig values and developing aspects
+
+Each factory data parameter has its default value reflected in the Kconfig. The
+list below shows some Kconfig settings that are configured in the nRF Connect
+build system and have an impact on the application. You can modify them to
+achieve the desired behavior of your application.
+
+- The device uses the test certificates located in the
+ `credentials/development/attestation/` directory, which are generated using
+ all default values. If you want to change the default `vendor_id`,
+ `product_id`, `vendor_name`, or `device_name` and generate new test
+ certificates, add the `CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_GENERATED=y`
+ Kconfig option. Remember to build the `chip-cert` application and add it to
+ the system PATH.
+
+ For developing a production-ready product, you need to write the
+ certificates obtained during the certification process. To do this, add the
+ `CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_USER=y` Kconfig option and set the
+ appropriate paths for the following Kconfig options:
+
+ - `CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_CERT`
+ - `CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_KEY`
+ - `CONFIG_CHIP_FACTORY_DATA_USER_CERTS_PAI_CERT`
+
+- By default, the SPAKE2+ verifier is generated during each example's build.
+ This means that this value will change automatically if you change any of
+ the following parameters:
+
+ - `CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE`
+ - `CONFIG_CHIP_DEVICE_SPAKE2_SALT`
+ - `CONFIG_CHIP_DEVICE_SPAKE2_IT`
+
+ You can disable the generation of the SPAKE2+ verifier by setting the
+ `CONFIG_CHIP_FACTORY_DATA_GENERATE_SPAKE2_VERIFIER=n` Kconfig option. Then,
+ you will need to provide the externally-generated SPAKE2+ verifier using the
+ `CONFIG_CHIP_DEVICE_SPAKE2_TEST_VERIFIER` Kconfig value.
+
+- Generating the rotating device ID unique ID is disabled by default, but you
+ can enable it by setting the `CONFIG_CHIP_ROTATING_DEVICE_ID=y` and
+ `CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID=y` Kconfig values.
+ Moreover, if you set the `CONFIG_CHIP_ROTATING_DEVICE_ID` Kconfig option to
+ `y` and disable the `CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID`
+ Kconfig option, you will need to provide it manually using the
+ `CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID` Kconfig value.
+
+- You can generate the test Certification Declaration by using the
+ `CONFIG_CHIP_FACTORY_DATA_GENERATE_CD=y` Kconfig option. Remember to build
+ the `chip-cert` application and add it to the system PATH.
+
## Programming factory data
diff --git a/docs/testing/ChipDeviceCtrlAPI.md b/docs/testing/ChipDeviceCtrlAPI.md
new file mode 100644
index 00000000000000..944c787d647207
--- /dev/null
+++ b/docs/testing/ChipDeviceCtrlAPI.md
@@ -0,0 +1,1079 @@
+# Table of Contents
+
+- [Table of Contents](#table-of-contents)
+- [chip.ChipDeviceCtrl](#chipchipdevicectrl)
+ - [CommissionableNode](#commissionablenode)
+ - [Commission](#commission)
+ - [DeviceProxyWrapper](#deviceproxywrapper)
+ - [ChipDeviceControllerBase](#chipdevicecontrollerbase)
+ - [Shutdown](#shutdown)
+ - [ShutdownAll](#shutdownall)
+ - [ExpireSessions](#expiresessions)
+ - [DiscoverCommissionableNodes](#discovercommissionablenodes)
+ - [DiscoverCommissionableNodesLongDiscriminator](#discovercommissionablenodeslongdiscriminator)
+ - [DiscoverCommissionableNodesShortDiscriminator](#discovercommissionablenodesshortdiscriminator)
+ - [DiscoverCommissionableNodesVendor](#discovercommissionablenodesvendor)
+ - [DiscoverCommissionableNodesDeviceType](#discovercommissionablenodesdevicetype)
+ - [DiscoverCommissionableNodesCommissioningEnabled](#discovercommissionablenodescommissioningenabled)
+ - [PrintDiscoveredDevices](#printdiscovereddevices)
+ - [DiscoverAllCommissioning](#discoverallcommissioning)
+ - [OpenCommissioningWindow](#opencommissioningwindow)
+ - [GetFabricIdInternal](#getfabricidinternal)
+ - [GetNodeIdInternal](#getnodeidinternal)
+ - [GetConnectedDeviceSync](#getconnecteddevicesync)
+ - [ComputeRoundTripTimeout](#computeroundtriptimeout)
+ - [GetRemoteSessionParameters](#getremotesessionparameters)
+ - [TestOnlySendBatchCommands](#testonlysendbatchcommands)
+ - [TestOnlySendCommandTimedRequestFlagWithNoTimedInvoke](#testonlysendcommandtimedrequestflagwithnotimedinvoke)
+ - [SendCommand](#sendcommand)
+ - [SendBatchCommands](#sendbatchcommands)
+ - [SendGroupCommand](#sendgroupcommand)
+ - [WriteAttribute](#writeattribute)
+ - [WriteGroupAttribute](#writegroupattribute)
+ - [Read](#read)
+ - [ReadAttribute](#readattribute)
+ - [ReadEvent](#readevent)
+ - [ZCLSend](#zclsend)
+ - [ZCLReadAttribute](#zclreadattribute)
+ - [ZCLWriteAttribute](#zclwriteattribute)
+ - [ZCLSubscribeAttribute](#zclsubscribeattribute)
+ - [InitGroupTestingData](#initgrouptestingdata)
+ - [ChipDeviceController](#chipdevicecontroller)
+ - [Commission](#commission-1)
+ - [CommissionThread](#commissionthread)
+ - [CommissionWiFi](#commissionwifi)
+ - [SetWiFiCredentials](#setwificredentials)
+ - [SetThreadOperationalDataset](#setthreadoperationaldataset)
+ - [ResetCommissioningParameters](#resetcommissioningparameters)
+ - [SetTimeZone](#settimezone)
+ - [SetDSTOffset](#setdstoffset)
+ - [SetDefaultNTP](#setdefaultntp)
+ - [SetTrustedTimeSource](#settrustedtimesource)
+ - [SetCheckMatchingFabric](#setcheckmatchingfabric)
+ - [GetFabricCheckResult](#getfabriccheckresult)
+ - [CommissionOnNetwork](#commissiononnetwork)
+ - [CommissionWithCode](#commissionwithcode)
+ - [CommissionIP](#commissionip)
+ - [IssueNOCChain](#issuenocchain)
+ - [BareChipDeviceController](#barechipdevicecontroller)
+ - [\_\_init\_\_](#__init__)
+
+
+
+# chip.ChipDeviceCtrl
+
+Chip Device Controller interface
+
+
+
+## CommissionableNode
+
+```python
+class CommissionableNode(discovery.CommissionableNode)
+```
+
+
+
+#### Commission
+
+```python
+def Commission(nodeId: int, setupPinCode: int) -> PyChipError
+```
+
+Commission the device using the device controller discovered this device.
+
+nodeId: The nodeId commissioned to the device setupPinCode: The setup pin code
+of the device
+
+
+
+## DeviceProxyWrapper
+
+```python
+class DeviceProxyWrapper()
+```
+
+Encapsulates a pointer to OperationalDeviceProxy on the c++ side that needs to
+be freed when DeviceProxyWrapper goes out of scope. There is a potential issue
+where if this is copied around that a double free will occur, but how this is
+used today that is not an issue that needs to be accounted for and it will
+become very apparent if that happens.
+
+
+
+## ChipDeviceControllerBase
+
+```python
+class ChipDeviceControllerBase()
+```
+
+
+
+#### Shutdown
+
+```python
+def Shutdown()
+```
+
+Shuts down this controller and reclaims any used resources, including the bound
+C++ constructor instance in the SDK.
+
+
+
+#### ShutdownAll
+
+```python
+def ShutdownAll()
+```
+
+Shut down all active controllers and reclaim any used resources.
+
+
+
+#### ExpireSessions
+
+```python
+def ExpireSessions(nodeid)
+```
+
+Close all sessions with `nodeid` (if any existed) so that sessions get
+re-established.
+
+This is needed to properly handle operations that invalidate a node's state,
+such as UpdateNOC.
+
+WARNING: ONLY CALL THIS IF YOU UNDERSTAND THE SIDE-EFFECTS
+
+
+
+#### DiscoverCommissionableNodes
+
+```python
+def DiscoverCommissionableNodes(
+ filterType: discovery.FilterType = discovery.FilterType.NONE,
+ filter: typing.Any = None,
+ stopOnFirst: bool = False,
+ timeoutSecond: int = 5
+) -> typing.Union[None, CommissionableNode, typing.List[CommissionableNode]]
+```
+
+Discover commissionable nodes via DNS-SD with specified filters. Supported
+filters are:
+
+ discovery.FilterType.NONE
+ discovery.FilterType.SHORT_DISCRIMINATOR
+ discovery.FilterType.LONG_DISCRIMINATOR
+ discovery.FilterType.VENDOR_ID
+ discovery.FilterType.DEVICE_TYPE
+ discovery.FilterType.COMMISSIONING_MODE
+ discovery.FilterType.INSTANCE_NAME
+ discovery.FilterType.COMMISSIONER
+ discovery.FilterType.COMPRESSED_FABRIC_ID
+
+This function will always return a list of CommissionableDevice. When
+stopOnFirst is set, this function will return when at least one device is
+discovered or on timeout.
+
+
+
+#### DiscoverCommissionableNodesLongDiscriminator
+
+```python
+def DiscoverCommissionableNodesLongDiscriminator(long_discriminator)
+```
+
+Deprecated, use DiscoverCommissionableNodes
+
+
+
+#### DiscoverCommissionableNodesShortDiscriminator
+
+```python
+def DiscoverCommissionableNodesShortDiscriminator(short_discriminator)
+```
+
+Deprecated, use DiscoverCommissionableNodes
+
+
+
+#### DiscoverCommissionableNodesVendor
+
+```python
+def DiscoverCommissionableNodesVendor(vendor)
+```
+
+Deprecated, use DiscoverCommissionableNodes
+
+
+
+#### DiscoverCommissionableNodesDeviceType
+
+```python
+def DiscoverCommissionableNodesDeviceType(device_type)
+```
+
+Deprecated, use DiscoverCommissionableNodes
+
+
+
+#### DiscoverCommissionableNodesCommissioningEnabled
+
+```python
+def DiscoverCommissionableNodesCommissioningEnabled()
+```
+
+Deprecated, use DiscoverCommissionableNodes
+
+
+
+#### PrintDiscoveredDevices
+
+```python
+def PrintDiscoveredDevices()
+```
+
+Deprecated, use GetCommissionableNodes
+
+
+
+#### DiscoverAllCommissioning
+
+```python
+def DiscoverAllCommissioning()
+```
+
+Deprecated, use DiscoverCommissionableNodes
+
+
+
+#### OpenCommissioningWindow
+
+```python
+def OpenCommissioningWindow(
+ nodeid: int, timeout: int, iteration: int, discriminator: int,
+ option: CommissioningWindowPasscode) -> CommissioningParameters
+```
+
+Opens a commissioning window on the device with the given nodeid. nodeid: Node
+id of the device timeout: Command timeout iteration: The PAKE iteration count
+associated with the PAKE Passcode ID and ephemeral PAKE passcode verifier to be
+used for this commissioning. Valid range: 1000 - 100000 Ignored if option == 0
+discriminator: The long discriminator for the DNS-SD advertisement. Valid range:
+0-4095 Ignored if option == 0 option: 0 = kOriginalSetupCode 1 =
+kTokenWithRandomPIN
+
+Returns CommissioningParameters
+
+
+
+#### GetFabricIdInternal
+
+```python
+def GetFabricIdInternal()
+```
+
+Get the fabric ID from the object. Only used to validate cached value from
+property.
+
+
+
+#### GetNodeIdInternal
+
+```python
+def GetNodeIdInternal() -> int
+```
+
+Get the node ID from the object. Only used to validate cached value from
+property.
+
+
+
+#### GetConnectedDeviceSync
+
+```python
+def GetConnectedDeviceSync(nodeid, allowPASE=True, timeoutMs: int = None)
+```
+
+Returns DeviceProxyWrapper upon success.
+
+
+
+#### ComputeRoundTripTimeout
+
+```python
+def ComputeRoundTripTimeout(nodeid, upperLayerProcessingTimeoutMs: int = 0)
+```
+
+Returns a computed timeout value based on the round-trip time it takes for the
+peer at the other end of the session to receive a message, process it and send
+it back. This is computed based on the session type, the type of transport,
+sleepy characteristics of the target and a caller-provided value for the time it
+takes to process a message at the upper layer on the target For group sessions.
+
+This will result in a session being established if one wasn't already.
+
+
+
+#### GetRemoteSessionParameters
+
+```python
+def GetRemoteSessionParameters(nodeid) -> typing.Optional[SessionParameters]
+```
+
+Returns the SessionParameters of reported by the remote node associated with
+`nodeid`. If there is some error in getting SessionParameters None is returned.
+
+This will result in a session being established if one wasn't already
+established.
+
+
+
+#### TestOnlySendBatchCommands
+
+```python
+async def TestOnlySendBatchCommands(
+ nodeid: int,
+ commands: typing.List[ClusterCommand.InvokeRequestInfo],
+ timedRequestTimeoutMs: typing.Optional[int] = None,
+ interactionTimeoutMs: typing.Optional[int] = None,
+ busyWaitMs: typing.Optional[int] = None,
+ suppressResponse: typing.Optional[bool] = None,
+ remoteMaxPathsPerInvoke: typing.Optional[int] = None,
+ suppressTimedRequestMessage: bool = False,
+ commandRefsOverride: typing.Optional[typing.List[int]] = None)
+```
+
+Please see SendBatchCommands for description. TestOnly overridable arguments:
+remoteMaxPathsPerInvoke: Overrides the number of batch commands we think can be
+sent to remote node. suppressTimedRequestMessage: When set to true, we suppress
+sending Timed Request Message. commandRefsOverride: List of commandRefs to use
+for each command with the same index in `commands`.
+
+**Returns**:
+
+- TestOnlyBatchCommandResponse
+
+
+
+#### TestOnlySendCommandTimedRequestFlagWithNoTimedInvoke
+
+```python
+async def TestOnlySendCommandTimedRequestFlagWithNoTimedInvoke(
+ nodeid: int,
+ endpoint: int,
+ payload: ClusterObjects.ClusterCommand,
+ responseType=None)
+```
+
+Please see SendCommand for description.
+
+
+
+#### SendCommand
+
+```python
+async def SendCommand(nodeid: int,
+ endpoint: int,
+ payload: ClusterObjects.ClusterCommand,
+ responseType=None,
+ timedRequestTimeoutMs: typing.Union[None, int] = None,
+ interactionTimeoutMs: typing.Union[None, int] = None,
+ busyWaitMs: typing.Union[None, int] = None,
+ suppressResponse: typing.Union[None, bool] = None)
+```
+
+Send a cluster-object encapsulated command to a node and get returned a future
+that can be awaited upon to receive the response. If a valid responseType is
+passed in, that will be used to de-serialize the object. If not, the type will
+be automatically deduced from the metadata received over the wire.
+
+timedWriteTimeoutMs: Timeout for a timed invoke request. Omit or set to 'None'
+to indicate a non-timed request. interactionTimeoutMs: Overall timeout for the
+interaction. Omit or set to 'None' to have the SDK automatically compute the
+right timeout value based on transport characteristics as well as the
+responsiveness of the target.
+
+**Returns**:
+
+- command response. The type of the response is defined by the command.
+
+**Raises**:
+
+- InteractionModelError on error
+
+
+
+#### SendBatchCommands
+
+```python
+async def SendBatchCommands(
+ nodeid: int,
+ commands: typing.List[ClusterCommand.InvokeRequestInfo],
+ timedRequestTimeoutMs: typing.Optional[int] = None,
+ interactionTimeoutMs: typing.Optional[int] = None,
+ busyWaitMs: typing.Optional[int] = None,
+ suppressResponse: typing.Optional[bool] = None)
+```
+
+Send a batch of cluster-object encapsulated commands to a node and get returned
+a future that can be awaited upon to receive the responses. If a valid
+responseType is passed in, that will be used to de-serialize the object. If not,
+the type will be automatically deduced from the metadata received over the wire.
+
+nodeId: Target's Node ID commands: A list of InvokeRequestInfo containing the
+commands to invoke. timedWriteTimeoutMs: Timeout for a timed invoke request.
+Omit or set to 'None' to indicate a non-timed request. interactionTimeoutMs:
+Overall timeout for the interaction. Omit or set to 'None' to have the SDK
+automatically compute the right timeout value based on transport characteristics
+as well as the responsiveness of the target. busyWaitMs: How long to wait in ms
+after sending command to device before performing any other operations.
+suppressResponse: Do not send a response to this action
+
+**Returns**:
+
+- List of command responses in the same order as what was given in `commands`.
+ The type of the response is defined by the command.
+- A value of `None` indicates success.
+- If only a single command fails, for example with `UNSUPPORTED_COMMAND`, the
+ corresponding index associated with the command will, contain
+ `interaction_model.Status.UnsupportedCommand`.
+- If a command is not responded to by server, command will contain
+ `interaction_model.Status.NoCommandResponse`
+
+**Raises**:
+
+- InteractionModelError if error with sending of InvokeRequestMessage fails as
+ a whole.
+
+
+
+#### SendGroupCommand
+
+```python
+def SendGroupCommand(groupid: int,
+ payload: ClusterObjects.ClusterCommand,
+ busyWaitMs: typing.Union[None, int] = None)
+```
+
+Send a group cluster-object encapsulated command to a group_id and get returned
+a future that can be awaited upon to get confirmation command was sent.
+
+**Returns**:
+
+- None: responses are not sent to group commands
+
+**Raises**:
+
+- InteractionModelError on error
+
+
+
+#### WriteAttribute
+
+```python
+async def WriteAttribute(nodeid: int,
+ attributes: typing.List[typing.Tuple[
+ int, ClusterObjects.ClusterAttributeDescriptor]],
+ timedRequestTimeoutMs: typing.Union[None, int] = None,
+ interactionTimeoutMs: typing.Union[None, int] = None,
+ busyWaitMs: typing.Union[None, int] = None)
+```
+
+Write a list of attributes on a target node.
+
+nodeId: Target's Node ID timedWriteTimeoutMs: Timeout for a timed write request.
+Omit or set to 'None' to indicate a non-timed request. attributes: A list of
+tuples of type (endpoint, cluster-object): interactionTimeoutMs: Overall timeout
+for the interaction. Omit or set to 'None' to have the SDK automatically compute
+the right timeout value based on transport characteristics as well as the
+responsiveness of the target.
+
+E.g (1, Clusters.UnitTesting.Attributes.XYZAttribute('hello')) -- Write 'hello'
+to the XYZ attribute on the test cluster to endpoint 1
+
+**Returns**:
+
+- [AttributeStatus] (list - one for each path)
+
+
+
+#### WriteGroupAttribute
+
+```python
+def WriteGroupAttribute(groupid: int,
+ attributes: typing.List[typing.Tuple[
+ ClusterObjects.ClusterAttributeDescriptor, int]],
+ busyWaitMs: typing.Union[None, int] = None)
+```
+
+Write a list of attributes on a target group.
+
+groupid: Group ID to send write attribute to. attributes: A list of tuples of
+type (cluster-object, data-version). The data-version can be omitted.
+
+E.g (Clusters.UnitTesting.Attributes.XYZAttribute('hello'), 1) -- Group Write
+'hello' with data version 1
+
+
+
+#### Read
+
+```python
+async def Read(
+ nodeid: int,
+ attributes: typing.
+ List[typing.Union[
+ None, # Empty tuple, all wildcard
+ typing.Tuple[int], # Endpoint
+ # Wildcard endpoint, Cluster id present
+ typing.Tuple[typing.Type[ClusterObjects.Cluster]],
+ # Wildcard endpoint, Cluster + Attribute present
+ typing.Tuple[typing.Type[ClusterObjects.ClusterAttributeDescriptor]],
+ # Wildcard attribute id
+ typing.Tuple[int, typing.Type[ClusterObjects.Cluster]],
+ # Concrete path
+ typing.Tuple[
+ int,
+ typing.Type[ClusterObjects.ClusterAttributeDescriptor]]]] = None,
+ dataVersionFilters: typing.List[typing.Tuple[
+ int, typing.Type[ClusterObjects.Cluster], int]] = None,
+ events: typing.List[typing.Union[
+ None, # Empty tuple, all wildcard
+ typing.Tuple[str, int], # all wildcard with urgency set
+ typing.Tuple[int, int], # Endpoint,
+ # Wildcard endpoint, Cluster id present
+ typing.Tuple[typing.Type[ClusterObjects.Cluster], int],
+ # Wildcard endpoint, Cluster + Event present
+ typing.Tuple[typing.Type[ClusterObjects.ClusterEvent], int],
+ # Wildcard event id
+ typing.Tuple[int, typing.Type[ClusterObjects.Cluster], int],
+ # Concrete path
+ typing.Tuple[int, typing.Type[ClusterObjects.ClusterEvent],
+ int]]] = None,
+ eventNumberFilter: typing.Optional[int] = None,
+ returnClusterObject: bool = False,
+ reportInterval: typing.Tuple[int, int] = None,
+ fabricFiltered: bool = True,
+ keepSubscriptions: bool = False,
+ autoResubscribe: bool = True)
+```
+
+Read a list of attributes and/or events from a target node
+
+nodeId: Target's Node ID attributes: A list of tuples of varying types depending
+on the type of read being requested: (endpoint, Clusters.ClusterA.AttributeA):
+Endpoint = specific, Cluster = specific, Attribute = specific (endpoint,
+Clusters.ClusterA): Endpoint = specific, Cluster = specific, Attribute = _
+(Clusters.ClusterA.AttributeA): Endpoint = _, Cluster = specific, Attribute =
+specific endpoint: Endpoint = specific, Cluster = _, Attribute = _
+Clusters.ClusterA: Endpoint = _, Cluster = specific, Attribute = _ '_' or ():
+Endpoint = _, Cluster = _, Attribute = _
+
+The cluster and attributes specified above are to be selected from the generated
+cluster objects.
+
+e.g. ReadAttribute(1, [ 1 ] ) -- case 4 above. ReadAttribute(1, [
+Clusters.BasicInformation ] ) -- case 5 above. ReadAttribute(1, [ (1,
+Clusters.BasicInformation.Attributes.Location ] ) -- case 1 above.
+
+dataVersionFilters: A list of tuples of (endpoint, cluster, data version).
+
+events: A list of tuples of varying types depending on the type of read being
+requested: (endpoint, Clusters.ClusterA.EventA, urgent): Endpoint = specific,
+Cluster = specific, Event = specific, Urgent = True/False (endpoint,
+Clusters.ClusterA, urgent): Endpoint = specific, Cluster = specific, Event = _,
+Urgent = True/False (Clusters.ClusterA.EventA, urgent): Endpoint = _, Cluster =
+specific, Event = specific, Urgent = True/False endpoint: Endpoint = specific,
+Cluster = _, Event = _, Urgent = True/False Clusters.ClusterA: Endpoint = _,
+Cluster = specific, Event = _, Urgent = True/False '_' or (): Endpoint = _,
+Cluster = _, Event = _, Urgent = True/False
+
+eventNumberFilter: Optional minimum event number filter.
+
+returnClusterObject: This returns the data as consolidated cluster objects, with
+all attributes for a cluster inside a single cluster-wide cluster object.
+
+reportInterval: A tuple of two int-s for (MinIntervalFloor, MaxIntervalCeiling).
+Used by establishing subscriptions. When not provided, a read request will be
+sent.
+
+**Returns**:
+
+- AsyncReadTransaction.ReadResponse. Please see ReadAttribute and ReadEvent
+ for examples of how to access data.
+
+**Raises**:
+
+- InteractionModelError (chip.interaction_model) on error
+
+
+
+#### ReadAttribute
+
+```python
+async def ReadAttribute(
+ nodeid: int,
+ attributes: typing.
+ List[typing.Union[
+ None, # Empty tuple, all wildcard
+ typing.Tuple[int], # Endpoint
+ # Wildcard endpoint, Cluster id present
+ typing.Tuple[typing.Type[ClusterObjects.Cluster]],
+ # Wildcard endpoint, Cluster + Attribute present
+ typing.Tuple[typing.Type[ClusterObjects.ClusterAttributeDescriptor]],
+ # Wildcard attribute id
+ typing.Tuple[int, typing.Type[ClusterObjects.Cluster]],
+ # Concrete path
+ typing.Tuple[int,
+ typing.Type[ClusterObjects.ClusterAttributeDescriptor]]]],
+ dataVersionFilters: typing.List[typing.Tuple[
+ int, typing.Type[ClusterObjects.Cluster], int]] = None,
+ returnClusterObject: bool = False,
+ reportInterval: typing.Tuple[int, int] = None,
+ fabricFiltered: bool = True,
+ keepSubscriptions: bool = False,
+ autoResubscribe: bool = True)
+```
+
+Read a list of attributes from a target node, this is a wrapper of
+DeviceController.Read()
+
+nodeId: Target's Node ID attributes: A list of tuples of varying types depending
+on the type of read being requested: (endpoint, Clusters.ClusterA.AttributeA):
+Endpoint = specific, Cluster = specific, Attribute = specific (endpoint,
+Clusters.ClusterA): Endpoint = specific, Cluster = specific, Attribute = _
+(Clusters.ClusterA.AttributeA): Endpoint = _, Cluster = specific, Attribute =
+specific endpoint: Endpoint = specific, Cluster = _, Attribute = _
+Clusters.ClusterA: Endpoint = _, Cluster = specific, Attribute = _ '_' or ():
+Endpoint = _, Cluster = _, Attribute = _
+
+The cluster and attributes specified above are to be selected from the generated
+cluster objects.
+
+e.g. ReadAttribute(1, [ 1 ] ) -- case 4 above. ReadAttribute(1, [
+Clusters.BasicInformation ] ) -- case 5 above. ReadAttribute(1, [ (1,
+Clusters.BasicInformation.Attributes.Location ] ) -- case 1 above.
+
+returnClusterObject: This returns the data as consolidated cluster objects, with
+all attributes for a cluster inside a single cluster-wide cluster object.
+
+reportInterval: A tuple of two int-s for (MinIntervalFloor, MaxIntervalCeiling).
+Used by establishing subscriptions. When not provided, a read request will be
+sent.
+
+**Returns**:
+
+- subscription request: ClusterAttribute.SubscriptionTransaction To get
+ notified on attribute change use SetAttributeUpdateCallback on the returned
+ SubscriptionTransaction. This is used to set a callback function, which is a
+ callable of type Callable[[TypedAttributePath, SubscriptionTransaction],
+ None] Get the attribute value from the change path using GetAttribute on the
+ SubscriptionTransaction You can await changes in the main loop using a
+ trigger mechanism from the callback. ex. queue.SimpleQueue
+
+- read request: AsyncReadTransaction.ReadResponse.attributes. This is of type
+ AttributeCache.attributeCache (Attribute.py), which is a dict mapping
+ endpoints to a list of Cluster (ClusterObjects.py) classes (dict[int,
+ List[Cluster]]) Access as
+ returned_object[endpoint_id][][] Ex. To
+ access the OnTime attribute from the OnOff cluster on endpoint 1
+ returned_object[1][clusters.onoff][Clusters.OnOff.Attributes.OnTime]
+
+**Raises**:
+
+- InteractionModelError (chip.interaction_model) on error
+
+
+
+#### ReadEvent
+
+```python
+async def ReadEvent(
+ nodeid: int,
+ events: typing.List[typing.Union[
+ None, # Empty tuple, all wildcard
+ typing.Tuple[str, int], # all wildcard with urgency set
+ typing.Tuple[int, int], # Endpoint,
+ # Wildcard endpoint, Cluster id present
+ typing.Tuple[typing.Type[ClusterObjects.Cluster], int],
+ # Wildcard endpoint, Cluster + Event present
+ typing.Tuple[typing.Type[ClusterObjects.ClusterEvent], int],
+ # Wildcard event id
+ typing.Tuple[int, typing.Type[ClusterObjects.Cluster], int],
+ # Concrete path
+ typing.Tuple[int, typing.Type[ClusterObjects.ClusterEvent], int]]],
+ eventNumberFilter: typing.Optional[int] = None,
+ fabricFiltered: bool = True,
+ reportInterval: typing.Tuple[int, int] = None,
+ keepSubscriptions: bool = False,
+ autoResubscribe: bool = True)
+```
+
+Read a list of events from a target node, this is a wrapper of
+DeviceController.Read()
+
+nodeId: Target's Node ID events: A list of tuples of varying types depending on
+the type of read being requested: (endpoint, Clusters.ClusterA.EventA, urgent):
+Endpoint = specific, Cluster = specific, Event = specific, Urgent = True/False
+(endpoint, Clusters.ClusterA, urgent): Endpoint = specific, Cluster = specific,
+Event = _, Urgent = True/False (Clusters.ClusterA.EventA, urgent): Endpoint = _,
+Cluster = specific, Event = specific, Urgent = True/False endpoint: Endpoint =
+specific, Cluster = _, Event = _, Urgent = True/False Clusters.ClusterA:
+Endpoint = _, Cluster = specific, Event = _, Urgent = True/False '_' or ():
+Endpoint = _, Cluster = _, Event = _, Urgent = True/False
+
+The cluster and events specified above are to be selected from the generated
+cluster objects.
+
+e.g. ReadEvent(1, [ 1 ] ) -- case 4 above. ReadEvent(1, [
+Clusters.BasicInformation ] ) -- case 5 above. ReadEvent(1, [ (1,
+Clusters.BasicInformation.Events.Location ] ) -- case 1 above.
+
+eventNumberFilter: Optional minimum event number filter. reportInterval: A tuple
+of two int-s for (MinIntervalFloor, MaxIntervalCeiling). Used by establishing
+subscriptions. When not provided, a read request will be sent.
+
+**Returns**:
+
+- subscription request: ClusterAttribute.SubscriptionTransaction To get
+ notified on event subscriptions, use the SetEventUpdateCallback function on
+ the returned SubscriptionTransaction. This is a callable of type
+ Callable[[EventReadResult, SubscriptionTransaction], None] You can await
+ events using a trigger mechanism in the callback. ex. queue.SimpleQueue
+
+- read request: AsyncReadTransaction.ReadResponse.events. This is a
+ List[ClusterEvent].
+
+**Raises**:
+
+- InteractionModelError (chip.interaction_model) on error
+
+
+
+#### ZCLSend
+
+```python
+def ZCLSend(cluster, command, nodeid, endpoint, groupid, args, blocking=False)
+```
+
+Wrapper over SendCommand that catches the exceptions Returns a tuple of
+(errorCode, CommandResponse)
+
+
+
+#### ZCLReadAttribute
+
+```python
+def ZCLReadAttribute(cluster,
+ attribute,
+ nodeid,
+ endpoint,
+ groupid,
+ blocking=True)
+```
+
+Wrapper over ReadAttribute for a single attribute Returns an AttributeReadResult
+
+
+
+#### ZCLWriteAttribute
+
+```python
+def ZCLWriteAttribute(cluster: str,
+ attribute: str,
+ nodeid,
+ endpoint,
+ groupid,
+ value,
+ dataVersion=0,
+ blocking=True)
+```
+
+Wrapper over WriteAttribute for a single attribute return PyChipError
+
+
+
+#### ZCLSubscribeAttribute
+
+```python
+def ZCLSubscribeAttribute(cluster,
+ attribute,
+ nodeid,
+ endpoint,
+ minInterval,
+ maxInterval,
+ blocking=True,
+ keepSubscriptions=False,
+ autoResubscribe=True)
+```
+
+Wrapper over ReadAttribute for a single attribute Returns a
+SubscriptionTransaction. See ReadAttribute for more information.
+
+
+
+#### InitGroupTestingData
+
+```python
+def InitGroupTestingData()
+```
+
+Populates the Device Controller's GroupDataProvider with known test group info
+and keys.
+
+
+
+## ChipDeviceController
+
+```python
+class ChipDeviceController(ChipDeviceControllerBase)
+```
+
+The ChipDeviceCommissioner binding, named as ChipDeviceController
+
+TODO: This class contains DEPRECATED functions, we should update the test
+scripts to avoid the usage of those functions.
+
+
+
+#### Commission
+
+```python
+def Commission(nodeid) -> PyChipError
+```
+
+Start the auto-commissioning process on a node after establishing a PASE
+connection. This function is intended to be used in conjunction with
+`EstablishPASESessionBLE` or `EstablishPASESessionIP`. It can be called either
+before or after the DevicePairingDelegate receives the OnPairingComplete call.
+Commissioners that want to perform simple auto-commissioning should use the
+supplied "PairDevice" functions above, which will establish the PASE connection
+and commission automatically.
+
+**Returns**:
+
+- `bool` - True if successful, False otherwise.
+
+
+
+#### CommissionThread
+
+```python
+def CommissionThread(discriminator, setupPinCode, nodeId,
+ threadOperationalDataset: bytes) -> PyChipError
+```
+
+Commissions a Thread device over BLE
+
+
+
+#### CommissionWiFi
+
+```python
+def CommissionWiFi(discriminator, setupPinCode, nodeId, ssid: str,
+ credentials: str) -> PyChipError
+```
+
+Commissions a Wi-Fi device over BLE.
+
+
+
+#### SetWiFiCredentials
+
+```python
+def SetWiFiCredentials(ssid: str, credentials: str)
+```
+
+Set the Wi-Fi credentials to set during commissioning.
+
+
+
+#### SetThreadOperationalDataset
+
+```python
+def SetThreadOperationalDataset(threadOperationalDataset)
+```
+
+Set the Thread operational dataset to set during commissioning.
+
+
+
+#### ResetCommissioningParameters
+
+```python
+def ResetCommissioningParameters()
+```
+
+Sets the commissioning parameters back to the default values.
+
+
+
+#### SetTimeZone
+
+```python
+def SetTimeZone(offset: int, validAt: int, name: str = "")
+```
+
+Set the time zone to set during commissioning. Currently only one time zone
+entry is supported
+
+
+
+#### SetDSTOffset
+
+```python
+def SetDSTOffset(offset: int, validStarting: int, validUntil: int)
+```
+
+Set the DST offset to set during commissioning. Currently only one DST entry is
+supported
+
+
+
+#### SetDefaultNTP
+
+```python
+def SetDefaultNTP(defaultNTP: str)
+```
+
+Set the DefaultNTP to set during commissioning
+
+
+
+#### SetTrustedTimeSource
+
+```python
+def SetTrustedTimeSource(nodeId: int, endpoint: int)
+```
+
+Set the trusted time source nodeId to set during commissioning. This must be a
+node on the commissioner fabric.
+
+
+
+#### SetCheckMatchingFabric
+
+```python
+def SetCheckMatchingFabric(check: bool)
+```
+
+Instructs the auto-commissioner to perform a matching fabric check before
+commissioning.
+
+
+
+#### GetFabricCheckResult
+
+```python
+def GetFabricCheckResult() -> int
+```
+
+Returns the fabric check result if SetCheckMatchingFabric was used.
+
+
+
+#### CommissionOnNetwork
+
+```python
+def CommissionOnNetwork(
+ nodeId: int,
+ setupPinCode: int,
+ filterType: DiscoveryFilterType = DiscoveryFilterType.NONE,
+ filter: typing.Any = None,
+ discoveryTimeoutMsec: int = 30000) -> PyChipError
+```
+
+Does the routine for OnNetworkCommissioning, with a filter for mDNS discovery.
+Supported filters are:
+
+ DiscoveryFilterType.NONE
+ DiscoveryFilterType.SHORT_DISCRIMINATOR
+ DiscoveryFilterType.LONG_DISCRIMINATOR
+ DiscoveryFilterType.VENDOR_ID
+ DiscoveryFilterType.DEVICE_TYPE
+ DiscoveryFilterType.COMMISSIONING_MODE
+ DiscoveryFilterType.INSTANCE_NAME
+ DiscoveryFilterType.COMMISSIONER
+ DiscoveryFilterType.COMPRESSED_FABRIC_ID
+
+The filter can be an integer, a string or None depending on the actual type of
+selected filter.
+
+
+
+#### CommissionWithCode
+
+```python
+def CommissionWithCode(
+ setupPayload: str,
+ nodeid: int,
+ discoveryType: DiscoveryType = DiscoveryType.DISCOVERY_ALL
+) -> PyChipError
+```
+
+Commission with the given nodeid from the setupPayload. setupPayload may be a QR
+or manual code.
+
+
+
+#### CommissionIP
+
+```python
+def CommissionIP(ipaddr: str, setupPinCode: int, nodeid: int) -> PyChipError
+```
+
+DEPRECATED, DO NOT USE! Use `CommissionOnNetwork` or `CommissionWithCode`
+
+
+
+#### IssueNOCChain
+
+```python
+def IssueNOCChain(csr: Clusters.OperationalCredentials.Commands.CSRResponse,
+ nodeId: int)
+```
+
+Issue an NOC chain using the associated OperationalCredentialsDelegate. The NOC
+chain will be provided in TLV cert format.
+
+
+
+## BareChipDeviceController
+
+```python
+class BareChipDeviceController(ChipDeviceControllerBase)
+```
+
+A bare device controller without AutoCommissioner support.
+
+
+
+#### \_\_init\_\_
+
+```python
+def __init__(operationalKey: p256keypair.P256Keypair,
+ noc: bytes,
+ icac: typing.Union[bytes, None],
+ rcac: bytes,
+ ipk: typing.Union[bytes, None],
+ adminVendorId: int,
+ name: str = None)
+```
+
+Creates a controller without AutoCommissioner.
+
+The allocated controller uses the noc, icac, rcac and ipk instead of the
+default, random generated certificates / keys. Which is suitable for creating a
+controller for manually signing certificates for testing.
+
+**Arguments**:
+
+- `operationalKey` - A P256Keypair object for the operational key of the
+ controller.
+- `noc` - The NOC for the controller, in bytes.
+- `icac` - The optional ICAC for the controller.
+- `rcac` - The RCAC for the controller.
+- `ipk` - The optional IPK for the controller, when None is provided, the
+ defaultIpk will be used.
+- `adminVendorId` - The adminVendorId of the controller.
+- `name` - The name of the controller, for debugging use only.
diff --git a/docs/testing/GenerateChipDeviceCtrlDoc.sh b/docs/testing/GenerateChipDeviceCtrlDoc.sh
new file mode 100755
index 00000000000000..f1d3f323c7a45c
--- /dev/null
+++ b/docs/testing/GenerateChipDeviceCtrlDoc.sh
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
+
+pydoc-markdown -m chip.ChipDeviceCtrl '{
+ renderer: {
+ type: markdown,
+ descriptive_class_title: false,
+ render_toc: true,
+ insert_header_anchors: true
+ }
+ }' >"$SCRIPT_DIR"/ChipDeviceCtrlAPI.md
diff --git a/docs/testing/python.md b/docs/testing/python.md
index 3af81e2394fe85..1f946a38333ecd 100644
--- a/docs/testing/python.md
+++ b/docs/testing/python.md
@@ -1,6 +1,500 @@
# Python framework tests
-This file is a placeholder for python framework test information.
+The python test framework is built on top of the ChipDeviceCtrl.py python
+controller API and the Mobly test framework. Python tests are interaction tests,
+and can be used for certification testing, and / or integration testing in the
+CI.
-NOTE: be sure to include information about how you need to commission with the
-python controller, not chip-tool and how to do that in the scripts
+Python tests located in src/python_testing
+
+## Resources for getting started
+
+- [src/python_testing/hello_test.py](https://github.com/project-chip/connectedhomeip/blob/master/src/python_testing/hello_test.py) -
+ sample test showing test setup and test harness integration
+- [https://github.com/google/mobly/blob/master/docs/tutorial.md](https://github.com/google/mobly/blob/master/docs/tutorial.md)
+- [ChipDeviceCtrl.py](https://github.com/project-chip/connectedhomeip/blob/master/src/controller/python/chip/ChipDeviceCtrl.py) -
+ Controller implementation - [API documentation](./ChipDeviceCtrlAPI.md)
+- [scripts/tests/run_python_test.py](https://github.com/project-chip/connectedhomeip/blob/master/scripts/tests/run_python_test.py)
+ to easily set up app and script for testing - used in CI
+
+## Writing Python tests
+
+- All test classes inherit from MatterBaseTest in
+ [matter_testing_support.py](https://github.com/project-chip/connectedhomeip/blob/master/src/python_testing/matter_testing_support.py)
+ - support for commissioning using the python controller
+ - default controller (self.default_controller) of type ChipDeviceCtrl
+ - MatterBaseTest inherits from the Mobly BaseTestClass
+- Test function(s) (start with test\_) and are all run automatically
+ - To run in the test harness, the test name must be test_TC_PICSCODE\_#\_#
+ - more information about integration with the test harness can be
+ found in [Test Harness helpers](#test-harness-helpers) section
+ - any tests that use async function (read / write / commands) should be
+ decorated with the @async_test_body decorator
+- Use ChipDeviceCtrl to interact with the DUT
+ - Controller API is in ChipDeviceCtrl.py (see API doc in file)
+ - some support functions in matter_testing_support.py
+- Use Mobly assertions for failing tests
+- self.step() along with a steps\_ function to mark test plan steps for cert
+ tests
+-
+
+### A simple test
+
+```
+class TC_MYTEST_1_1(MatterBaseTest):
+
+ @async_test_body
+ async def test_TC_MYTEST_1_1(self):
+
+ vendor_name = await self.read_single_attribute_check_success(
+ dev_ctrl=self.default_controller, # defaults to
+self.default_controlller
+ node_id = self.dut_node_id, # defaults to
+self.dut_node_id
+ cluster=Clusters.BasicInformation,
+ attribute=Clusters.BasicInformation.Attributes.VendorName,
+ endpoint = 0, #defaults to 0
+ )
+ asserts.assert_equal(vendor_name, “Test vendor name”, “Unexpected vendor name”)
+
+if __name__ == "__main__":
+default_matter_test_main()
+```
+
+---
+
+In this test, asserts.assert_equal is used to fail the test on condition failure
+(throws an exception).
+
+Because the test requires the use of the async function
+read_single_attribute_check_success, the test is decorated with the
+`@async_test_body` decorator
+
+The default_matter_test_main() function is used to run the test on the command
+line. These two lines should appear verbatim at the bottom of every python test
+file.
+
+## Cluster Codegen
+
+- [Objects.py](https://github.com/project-chip/connectedhomeip/blob/master/src/controller/python/chip/clusters/Objects.py)
+ for codegen,
+- [ClusterObjects.py](https://github.com/project-chip/connectedhomeip/blob/master/src/controller/python/chip/clusters/ClusterObjects.py)
+ for classes
+
+Common import used in test files: `import chip.clusters as Clusters`
+
+Each cluster is defined in the `Clusters.` namespace and contains
+always:
+
+- id
+- descriptor
+
+Each `Clusters.` will include the appropriate sub-classes (if
+defined for the cluster):
+
+- Enums
+- Bitmaps
+- Structs
+- Attributes
+- Commands
+- Events
+
+### Attributes
+
+Attributes derive from ClusterAttributeDescriptor
+
+Each `Clusters..Attributes.` class has:
+
+- cluster_id
+- attribute_id
+- attribute_type
+- value
+
+Example:
+
+- class - Clusters.OnOff.Attributes.OnTime
+ - used for Read commands
+- instance - Clusters.OnOff.Attributes.OnTime(5)
+ - sets the value to 5
+ - pass the instance to write commands to write the value
+
+### Commands
+
+Commands derive from ClusterCommand
+
+Each `Clusters..Commands.` class has:
+
+- cluster_id
+- command_id
+- is_client
+- response_type (None for status response)
+- descriptor
+- data members (if required)
+
+Example:
+
+- Clusters.OnOff.Commands.OnWithTimedOff(onOffControl=0, onTime=5,
+ offWaitTime=8)
+- Clusters.OnOff.Commands.OnWithTimedOff()
+ - command with no fields
+
+### Events
+
+Events derive from ClusterEvent
+
+Each `Clusters..Events.` class has:
+
+- cluster_id
+- event_id
+- descriptor
+- data members if required
+
+Example:
+
+- Clusters.AccessControl.Events.AccessControlEntryChanged.adminNodeID
+
+### Enums
+
+Enums derive from MatterIntEnum
+
+Each `Clusters..Enum.` has
+
+- k
+- kUnknownEnumValue (used for testing, do not transmit)
+
+Example:
+
+- Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister
+
+### Bitmaps
+
+Bitmaps derive from IntFlag
+
+Each `Clusters..Bitmaps.` has: - k
+
+Special class:
+
+- class Feature(IntFlag) - contains the feature map bitmaps
+
+Example:
+
+- Clusters.LaundryWasherControls.Bitmaps.Feature.kSpin
+
+### Structs
+
+Structs derive from ClusterObject
+
+Each `Clusters..Structs.` has:
+
+- descriptor
+- data members
+
+Example
+
+- Clusters.BasicInformation.Structs.ProductAppearanceStruct(
+- finish=Clusters.BasicInformation.Enums.ProductFinishEnum.kFabric,
+- primaryColor=Clusters.BasicInformation.Enums.ColorEnum.kBlack)
+
+## Accessing Clusters and Cluster Elements by ID
+
+[ClusterObjects.py](https://github.com/project-chip/connectedhomeip/blob/master/src/controller/python/chip/clusters/ClusterObjects.py)
+has a set of objects that map ID to the code generated object.
+
+`chip.clusters.ClusterObjects.ALL_CLUSTERS`
+
+- dict[int, Cluster] - maps cluster ID to Cluster class
+- cluster = chip.clusters.ClusterObjects.ALL_CLUSTERS[cluster_id]
+
+`chip.clusters.ClusterObjects.ALL_ATTRIBUTES`
+
+- dict[int, dict[int, ClusterAttributeDescriptor]] - maps cluster ID to a dict
+ of attribute ID to attribute class
+- attr = chip.clusters.ClusterObjects.ALL_ATTRIBUTES[cluster_id][attribute_id]
+
+`chip.clusters.ClusterObjects.ALL_ACCEPTED_COMMANDS/ALL_GENERATED_COMMANDS`
+
+- dict[int, dict[int, ClusterCommand]]
+- cmd = chip.clusters.ClusterObjects.ALL_ACCEPTED_COMMANDS[cluster_id][cmd_id]
+
+## ChipDeviceCtrl API
+
+The ChipDeviceCtrl API is implemented in
+[ChipDeviceCtrl.py](https://github.com/project-chip/connectedhomeip/blob/master/src/controller/python/chip/ChipDeviceCtrl.py).
+
+The ChipDeviceCtrl implements a python-based controller that can be used to
+commission and control devices. The API is documented here in the
+[ChipDeviceCtrl API documentation](./ChipDeviceCtrlAPI.md)
+
+The API doc gives full descriptions of the APIs being used. The most commonly
+used functions are linked below
+
+### [Read](./ChipDeviceCtrlAPI.md#read)
+
+- Read both attributes and events
+- Can handle wildcard or concrete path
+
+### [ReadAttribute](./ChipDeviceCtrlAPI.md#readattribute)
+
+- convenience wrapper for Read for attributes
+
+Examples: Wildcard read (all clusters, all endpoints):
+
+`await dev_ctrl.ReadAttribute(node_id, [()])`
+
+Wildcard read (single endpoint 0)
+
+`await dev_ctrl.ReadAttribute(node_id, [(0)])`
+
+Wildcard read (single cluster from single endpoint 0)
+
+`await dev_ctrl.ReadAttribute(node_id, [(1, Clusters.OnOff)])`
+
+Single attribute
+
+`await dev_ctrl.ReadAttribute(node_id, [(1, Clusters.OnOff.Attributes.OnTime)])`
+
+Multi-path
+
+`await dev_ctrl.ReadAttribute(node_id, [(1, Clusters.OnOff.Attributes.OnTime),(1, Clusters.OnOff.Attributes.OnOff)])`
+
+### [ReadEvent](./ChipDeviceCtrlAPI.md#readevent)
+
+- convenience wrapper for Read
+- Similar to ReadAttribute, but the tuple includes urgency as the last number
+
+Example:
+
+```
+urgent = 1
+
+await dev_ctrl ReadEvent(node_id, [(1,
+Clusters.TimeSynchronization.Events.MissingTrustedTimeSource, urgent)])
+```
+
+### Subscriptions
+
+Subscriptions are handled in the Read / ReadAttribute / ReadEvent APIs. To
+initiate a subscription, set the `reportInterval` tuple to set the floor and
+ceiling. The `keepSubscriptions` and `autoResubscribe` parameters also apply to
+subscriptions.
+
+Subscription return `ClusterAttribute.SubscriptionTransaction`. This can be used
+to set callbacks. The object is returned after the priming data read is
+complete, and the values there are used to populate the cache. The attribute
+callbacks are called on update.
+
+- SetAttributeUpdateCallback
+ - Callable[[TypedAttributePath, SubscriptionTransaction], None]
+- SetEventUpdateCallback
+ - Callable[[EventReadResult, SubscriptionTransaction], None]
+- await changes in the main loop using a trigger mechanism from the callback.
+
+Example for setting callbacks:
+
+```
+q = queue.Queue()
+cb = SimpleEventCallback("cb", cluster_id, event_id, q)
+
+urgent = 1
+subscription = await dev_ctrl.ReadEvent(nodeid=1, events=[(1, event, urgent)], reportInterval=[1, 3])
+subscription.SetEventUpdateCallback(callback=cb)
+
+try:
+ q.get(block=True, timeout=timeout)
+except queue.Empty:
+ asserts.assert_fail(“Timeout on event”)
+```
+
+### [WriteAttribute](./ChipDeviceCtrlAPI.md#writeattribute)
+
+Handles concrete paths only (per spec), can handle lists. Returns list of
+PyChipError
+
+- Instantiate the `ClusterAttributeDescriptor` class with the value you want
+ to send, tuple is (endpoint, attribute)
+ - use timedRequestTimeoutMs for timed request actions
+
+Example:
+
+```
+res = await devCtrl.WriteAttribute(nodeid=0, attributes=[(0,Clusters.BasicInformation.Attributes.NodeLabel("Test"))])
+asserts.assert_equal(ret[0].status, Status.Success, “write failed”)
+```
+
+### [SendCommand](./ChipDeviceCtrlAPI.md#sendcommand)
+
+- Instantiate the command with the values you need to populate
+- If there is a non-status return, it’s returned from the command
+- If there is a pure status return it will return nothing
+- Raises InteractionModelError on failure
+
+Example:
+
+```
+pai = await dev_ctrl.SendCommand(nodeid, 0, Clusters.OperationalCredentials.Commands.CertificateChainRequest(2))
+```
+
+## MatterBaseTest helpers
+
+- Because we tend to do a lot of single read / single commands in tests, we
+ added a couple of helpers in MatterBaseTest that use some of the default
+ values
+ - read_single_attribute_check_success
+ - read_single_attribute_expect_error
+ - send_single_cmd
+- step() function to mark step progress for the test harness
+- skip / skip_step / skip_remaining_steps functions for test harness
+ integration
+- check_pics / pics_guard to handle pics
+
+## Mobly helpers
+
+The test system is based on Mobly, and the
+[matter_testing_support.py](https://github.com/project-chip/connectedhomeip/blob/master/src/python_testing/matter_testing_support.py)
+class provides some helpers for Mobly integration
+
+- default_matter_test_main
+ - Sets up commissioning and finds all tests, parses command arguments
+
+use as:
+
+```
+if __name__ == "__main__":
+default_matter_test_main()
+```
+
+- Mobly will run all functions starting with test\_ by default
+ - use --tests command line argument to specify
+- Setup / teardown functions
+ - setup_class / teardown_class
+ - setup_test / teardown_test
+ - Don’t forget to call the super() if you override these
+
+## Test harness helpers
+
+The python testing system also includes several functions for integrations with
+the test harness. To integrate with the test harness, you can define the
+following functions on your class to allow the test harness UI to properly work
+through your tests.
+
+All of these functions are demonstrated in the
+[hello_example.py](https://github.com/project-chip/connectedhomeip/blob/master/src/python_testing/hello_test.py)
+reference.
+
+- step enumeration
+ - define a function called `steps_YourFunctionName` to allow the test
+ harness to display the steps
+ - use the self.step(``) function to walk through the steps
+- test description
+ - define a function called `desc_YourFunctionName` to send back a string
+ with the test description
+- top level PICS
+ - To guard your test on a top level PICS, define a function called
+ `pics_YourFunctionName` to send back a list of pics. If this function is
+ omitted, the test will be run for every endpoint on every device.
+- overriding the default timeout
+ - if the test is exceptionally long running, define a property function
+ `default_timeout` to adjust the timeout. The default is 90 seconds
+
+Deferred failures: For some tests, it makes sense to perform the entire test
+before failing and collect all the errors so the developers can address all the
+failures without needing to re-run the test multiple times. For example, tests
+that look at every attribute on the cluster and perform independent operations
+on them etc.
+
+For such tests, use the ProblemNotice format and the convenience functions:
+
+- self.record_error
+- self.record_warning
+
+These functions keep track of the problems, and will print them at the end of
+the test. The test will not be failed until the assert is called.
+
+A good example of this type of test can be found in the device basic composition
+tests, where all the test steps are independent and performed on a single read.
+See
+[Device Basic Composition tests](https://github.com/project-chip/connectedhomeip/blob/master/src/python_testing/TC_DeviceBasicComposition.py)
+
+## Command line arguments
+
+- Use help to get a full list
+- --commissioning-method
+ - need to re-commission to python controller as chip-tool and python
+ commissioner do not share a credentials
+- --discriminator, --passcode, --qr-code, --manual-code
+- --tests to select tests
+- --PICS
+- --int-arg, --bool-arg, --float-arg, --string-arg, --json-arg, --hex-arg
+ - specify as key:value ex --bool-arg pixit_name:False
+ - used for custom arguments to scripts (PIXITs)
+
+## PICS and PIXITS
+
+- PICS
+ - use --PICS on the command line to specify the PICS file
+ - use check_pics to gate steps in a file
+- have_whatever = check_pics(“PICS.S.WHATEVER”)
+- PIXITs
+ - use --int-arg, --bool-arg etc on the command line to specify PIXITs
+ - Warn users if they don’t set required values, add instructions in the
+ comments
+- pixit_value = self.user_params.get("pixit_name", default)
+
+## Support functions
+
+To create a controller on a new fabric:
+
+```
+new_CA = self.certificate_authority_manager.NewCertificateAuthority()
+
+new_fabric_admin = new_certificate_authority.NewFabricAdmin(vendorId=0xFFF1,
+fabricId=self.matter_test_config.fabric_id + 1)
+
+TH2 = new_fabric_admin.NewController(nodeId=112233)
+```
+
+Open a commissioning window (ECW):
+
+```
+params = self.OpenCommissioningWindow(dev_ctrl=self.default_controller, node_id=self.dut_node_id)
+```
+
+To create a new controller on the SAME fabric, allocate a new controller from
+the fabric admin
+
+Fabric admin for default controller:
+
+```
+fa=self.certificate_authority_manager.activeCaList[0].adminList[0]
+second_ctrl = fa.new_fabric_admin.NewController(nodeId=node_id)
+```
+
+## other support functions
+
+- basic_composition_support
+ - wildcard read, whole device analysis
+- CommissioningFlowBlocks
+ - various commissioning support for core tests
+- spec_parsing_support
+ - parsing data model XML into python readable format
+
+# Running tests locally
+
+You can run the python script as-is for local testing against an already-running
+DUT
+
+`./scripts/tests/run_python_test.py` is a convenient script to fire up an
+example DUT on the host, with factory reset support
+
+`./scripts/tests/run_python_test.py --factoryreset --app --app-args "whatever" --script --script-args "whatever"`
+
+Note that devices must be commissioned by the python test harness to run tests.
+chip-tool and the python test harness DO NOT share a fabric.
+
+# Running tests in CI
+
+- add to .github/workflows/tests.yaml repl_tests_linux
+- don’t forget to set the PICS file to the ci-pics-values
+- if there are things in your test that will fail on CI (ex. test vendor
+ checks), gate them on the PICS_SDK_CI_ONLY
+ - is_ci = self.check_pics('PICS_SDK_CI_ONLY')
diff --git a/examples/air-purifier-app/air-purifier-common/air-purifier-app.zap b/examples/air-purifier-app/air-purifier-common/air-purifier-app.zap
index b868916264f4ba..516cb763153e1f 100644
--- a/examples/air-purifier-app/air-purifier-common/air-purifier-app.zap
+++ b/examples/air-purifier-app/air-purifier-common/air-purifier-app.zap
@@ -1,6 +1,6 @@
{
"fileFormat": 2,
- "featureLevel": 99,
+ "featureLevel": 100,
"creator": "zap",
"keyValuePairs": [
{
@@ -1581,10 +1581,10 @@
"side": "server",
"type": "bitmap32",
"included": 1,
- "storageOption": "RAM",
+ "storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "0",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -1597,10 +1597,10 @@
"side": "server",
"type": "int16u",
"included": 1,
- "storageOption": "RAM",
+ "storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "0x0002",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 0,
"maxInterval": 65344,
@@ -2903,7 +2903,6 @@
"define": "FAN_CONTROL_CLUSTER",
"side": "server",
"enabled": 1,
- "apiMaturity": "provisional",
"commands": [
{
"name": "Step",
@@ -7610,7 +7609,7 @@
"singleton": 0,
"bounded": 0,
"defaultValue": "0x0",
- "reportable": 0,
+ "reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
@@ -7626,7 +7625,7 @@
"singleton": 0,
"bounded": 0,
"defaultValue": "0x00",
- "reportable": 0,
+ "reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
@@ -7641,7 +7640,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -7657,7 +7656,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -7673,7 +7672,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -7689,7 +7688,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -7747,7 +7746,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -7763,8 +7762,8 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
- "reportable": 0,
+ "defaultValue": null,
+ "reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
@@ -7779,8 +7778,8 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
- "reportable": 0,
+ "defaultValue": null,
+ "reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
@@ -7795,8 +7794,8 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
- "reportable": 0,
+ "defaultValue": null,
+ "reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
@@ -7811,7 +7810,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -7827,7 +7826,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -7843,7 +7842,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -7859,7 +7858,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -7875,7 +7874,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "0",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -7891,7 +7890,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "2",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -8039,7 +8038,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -8055,7 +8054,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -8071,7 +8070,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -8087,7 +8086,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -8136,43 +8135,48 @@
"endpointTypeIndex": 0,
"profileId": 259,
"endpointId": 0,
- "networkId": 0
+ "networkId": 0,
+ "parentEndpointIdentifier": null
},
{
"endpointTypeName": "Anonymous Endpoint Type",
"endpointTypeIndex": 1,
"profileId": 259,
"endpointId": 1,
- "networkId": 0
+ "networkId": 0,
+ "parentEndpointIdentifier": null
},
{
"endpointTypeName": "Anonymous Endpoint Type",
"endpointTypeIndex": 2,
"profileId": 259,
"endpointId": 2,
- "networkId": 0
+ "networkId": 0,
+ "parentEndpointIdentifier": null
},
{
"endpointTypeName": "Anonymous Endpoint Type",
"endpointTypeIndex": 3,
"profileId": 259,
"endpointId": 3,
- "networkId": 0
+ "networkId": 0,
+ "parentEndpointIdentifier": null
},
{
"endpointTypeName": "Anonymous Endpoint Type",
"endpointTypeIndex": 4,
"profileId": 259,
"endpointId": 4,
- "networkId": 0
+ "networkId": 0,
+ "parentEndpointIdentifier": null
},
{
"endpointTypeName": "Anonymous Endpoint Type",
"endpointTypeIndex": 5,
"profileId": 259,
"endpointId": 5,
- "networkId": 0
+ "networkId": 0,
+ "parentEndpointIdentifier": null
}
- ],
- "log": []
+ ]
}
\ No newline at end of file
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 1f165eecdcc27a..48db2c71b380bb 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
@@ -829,7 +829,7 @@ cluster SoftwareDiagnostics = 52 {
/** The Thread Network Diagnostics Cluster provides a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems */
cluster ThreadNetworkDiagnostics = 53 {
- revision 1; // NOTE: Default/not specifically set
+ revision 2;
enum ConnectionStatusEnum : enum8 {
kConnected = 0;
@@ -2203,7 +2203,7 @@ endpoint 0 {
callback attribute operationalDatasetComponents;
callback attribute activeNetworkFaultsList;
ram attribute featureMap default = 0x000F;
- ram attribute clusterRevision default = 1;
+ ram attribute clusterRevision default = 2;
handle command ResetCounts;
}
diff --git a/examples/air-quality-sensor-app/air-quality-sensor-common/air-quality-sensor-app.zap b/examples/air-quality-sensor-app/air-quality-sensor-common/air-quality-sensor-app.zap
index 06db369cc4e3b6..1ba46389e28a9e 100644
--- a/examples/air-quality-sensor-app/air-quality-sensor-common/air-quality-sensor-app.zap
+++ b/examples/air-quality-sensor-app/air-quality-sensor-common/air-quality-sensor-app.zap
@@ -1,6 +1,6 @@
{
"fileFormat": 2,
- "featureLevel": 99,
+ "featureLevel": 100,
"creator": "zap",
"keyValuePairs": [
{
@@ -1529,10 +1529,10 @@
"side": "server",
"type": "bitmap32",
"included": 1,
- "storageOption": "RAM",
+ "storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "0",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -1545,10 +1545,10 @@
"side": "server",
"type": "int16u",
"included": 1,
- "storageOption": "RAM",
+ "storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "0x0002",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 0,
"maxInterval": 65344,
@@ -2733,7 +2733,7 @@
"storageOption": "RAM",
"singleton": 0,
"bounded": 0,
- "defaultValue": "1",
+ "defaultValue": "2",
"reportable": 1,
"minInterval": 0,
"maxInterval": 65344,
@@ -6054,14 +6054,16 @@
"endpointTypeIndex": 0,
"profileId": 259,
"endpointId": 0,
- "networkId": 0
+ "networkId": 0,
+ "parentEndpointIdentifier": null
},
{
"endpointTypeName": "Anonymous Endpoint Type",
"endpointTypeIndex": 1,
"profileId": 259,
"endpointId": 1,
- "networkId": 0
+ "networkId": 0,
+ "parentEndpointIdentifier": null
}
]
}
\ No newline at end of file
diff --git a/examples/air-quality-sensor-app/linux/AirQualitySensorAppAttrUpdateDelegate.cpp b/examples/air-quality-sensor-app/linux/AirQualitySensorAppAttrUpdateDelegate.cpp
index 8be44e55cc9e17..41a53d4fd94c7d 100644
--- a/examples/air-quality-sensor-app/linux/AirQualitySensorAppAttrUpdateDelegate.cpp
+++ b/examples/air-quality-sensor-app/linux/AirQualitySensorAppAttrUpdateDelegate.cpp
@@ -19,11 +19,11 @@
#include "AirQualitySensorAppAttrUpdateDelegate.h"
#include
-#include
#include
#include
#include
#include
+#include
#include
#include
diff --git a/examples/air-quality-sensor-app/linux/README.md b/examples/air-quality-sensor-app/linux/README.md
index 73139ef4aeeacb..38a0adfb2fe7bf 100644
--- a/examples/air-quality-sensor-app/linux/README.md
+++ b/examples/air-quality-sensor-app/linux/README.md
@@ -165,3 +165,21 @@ value.
```
$ echo '{"Name":"NitrogenDioxideConcentrationMeasurement","NewValue":1}' > /tmp/chip_air_quality_fifo_
```
+
+Generate event `Pm1ConcentrationMeasurement`, to change the PM1 value.
+
+```
+echo '{"Name":"Pm1ConcentrationMeasurement","NewValue":1}' > /tmp/chip_air_quality_fifo_
+```
+
+Generate event `Pm25ConcentrationMeasurement`, to change the PM2.5 value.
+
+```
+echo '{"Name":"Pm25ConcentrationMeasurement","NewValue":2.5}' > /tmp/chip_air_quality_fifo_
+```
+
+Generate event `Pm10ConcentrationMeasurement`, to change the PM10 value.
+
+```
+echo '{"Name":"Pm10ConcentrationMeasurement","NewValue":10}' > /tmp/chip_air_quality_fifo_
+```
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 5a7b510b05b0c8..2c54d75c7e6b06 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
@@ -1814,7 +1814,7 @@ cluster SoftwareDiagnostics = 52 {
/** The Thread Network Diagnostics Cluster provides a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems */
cluster ThreadNetworkDiagnostics = 53 {
- revision 1; // NOTE: Default/not specifically set
+ revision 2;
enum ConnectionStatusEnum : enum8 {
kConnected = 0;
@@ -5869,7 +5869,7 @@ cluster RelativeHumidityMeasurement = 1029 {
/** Attributes and commands for configuring occupancy sensing, and reporting occupancy status. */
cluster OccupancySensing = 1030 {
- revision 3;
+ revision 4;
enum OccupancySensorTypeEnum : enum8 {
kPIR = 0;
@@ -7538,7 +7538,7 @@ endpoint 0 {
callback attribute operationalDatasetComponents;
callback attribute activeNetworkFaultsList;
ram attribute featureMap default = 0x000F;
- ram attribute clusterRevision default = 1;
+ ram attribute clusterRevision default = 2;
handle command ResetCounts;
}
@@ -7761,7 +7761,7 @@ endpoint 1 {
callback attribute eventList;
callback attribute attributeList;
ram attribute featureMap default = 0x0001;
- ram attribute clusterRevision default = 5;
+ ram attribute clusterRevision default = 6;
handle command Off;
handle command On;
@@ -8740,7 +8740,7 @@ endpoint 1 {
ram attribute occupancySensorType;
ram attribute occupancySensorTypeBitmap;
ram attribute featureMap default = 0;
- ram attribute clusterRevision default = 3;
+ ram attribute clusterRevision default = 4;
}
server cluster CarbonMonoxideConcentrationMeasurement {
@@ -9134,7 +9134,7 @@ endpoint 2 {
callback attribute eventList;
callback attribute attributeList;
ram attribute featureMap default = 0x0001;
- ram attribute clusterRevision default = 5;
+ ram attribute clusterRevision default = 6;
handle command Off;
handle command On;
@@ -9207,7 +9207,7 @@ endpoint 2 {
ram attribute occupancySensorType;
ram attribute occupancySensorTypeBitmap;
ram attribute featureMap default = 0;
- ram attribute clusterRevision default = 3;
+ ram attribute clusterRevision default = 4;
}
}
endpoint 65534 {
diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap
index 21bcfee37b5e0d..683f2dd75658ba 100644
--- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap
+++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap
@@ -1,6 +1,6 @@
{
"fileFormat": 2,
- "featureLevel": 99,
+ "featureLevel": 100,
"creator": "zap",
"keyValuePairs": [
{
@@ -17,12 +17,6 @@
}
],
"package": [
- {
- "pathRelativity": "relativeToZap",
- "path": "../../../src/app/zap-templates/app-templates.json",
- "type": "gen-templates-json",
- "version": "chip-v1"
- },
{
"pathRelativity": "relativeToZap",
"path": "../../../src/app/zap-templates/zcl/zcl-with-test-extensions.json",
@@ -30,6 +24,12 @@
"category": "matter",
"version": 1,
"description": "Matter SDK ZCL data with some extensions"
+ },
+ {
+ "pathRelativity": "relativeToZap",
+ "path": "../../../src/app/zap-templates/app-templates.json",
+ "type": "gen-templates-json",
+ "version": "chip-v1"
}
],
"endpointTypes": [
@@ -4331,7 +4331,7 @@
"storageOption": "RAM",
"singleton": 0,
"bounded": 0,
- "defaultValue": "1",
+ "defaultValue": "2",
"reportable": 1,
"minInterval": 0,
"maxInterval": 65344,
@@ -6659,7 +6659,7 @@
"storageOption": "RAM",
"singleton": 0,
"bounded": 0,
- "defaultValue": "5",
+ "defaultValue": "6",
"reportable": 1,
"minInterval": 0,
"maxInterval": 65344,
@@ -6895,7 +6895,7 @@
"storageOption": "RAM",
"singleton": 0,
"bounded": 0,
- "defaultValue": "5",
+ "defaultValue": "6",
"reportable": 1,
"minInterval": 0,
"maxInterval": 65344,
@@ -8312,7 +8312,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -14241,15 +14241,16 @@
]
},
{
- "name": "Power Topology",
- "code": 156,
+ "name": "Energy Preference",
+ "code": 155,
"mfgCode": null,
- "define": "POWER_TOPOLOGY_CLUSTER",
+ "define": "ENERGY_PREFERENCE_CLUSTER",
"side": "server",
"enabled": 1,
+ "apiMaturity": "provisional",
"attributes": [
{
- "name": "AvailableEndpoints",
+ "name": "EnergyBalances",
"code": 0,
"mfgCode": null,
"side": "server",
@@ -14265,10 +14266,26 @@
"reportableChange": 0
},
{
- "name": "ActiveEndpoints",
+ "name": "CurrentEnergyBalance",
"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": "EnergyPriorities",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
"type": "array",
"included": 1,
"storageOption": "External",
@@ -14280,6 +14297,38 @@
"maxInterval": 65534,
"reportableChange": 0
},
+ {
+ "name": "LowPowerModeSensitivities",
+ "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": "CurrentLowPowerModeSensitivity",
+ "code": 4,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
{
"name": "GeneratedCommandList",
"code": 65528,
@@ -14351,10 +14400,10 @@
"side": "server",
"type": "bitmap32",
"included": 1,
- "storageOption": "External",
+ "storageOption": "RAM",
"singleton": 0,
"bounded": 0,
- "defaultValue": null,
+ "defaultValue": "3",
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -14372,41 +14421,23 @@
"bounded": 0,
"defaultValue": "1",
"reportable": 1,
- "minInterval": 1,
- "maxInterval": 65534,
+ "minInterval": 0,
+ "maxInterval": 65344,
"reportableChange": 0
}
]
},
{
- "name": "Energy EVSE Mode",
- "code": 157,
+ "name": "Power Topology",
+ "code": 156,
"mfgCode": null,
- "define": "ENERGY_EVSE_MODE_CLUSTER",
+ "define": "POWER_TOPOLOGY_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",
+ "name": "AvailableEndpoints",
"code": 0,
"mfgCode": null,
"side": "server",
@@ -14422,11 +14453,11 @@
"reportableChange": 0
},
{
- "name": "CurrentMode",
+ "name": "ActiveEndpoints",
"code": 1,
"mfgCode": null,
"side": "server",
- "type": "int8u",
+ "type": "array",
"included": 1,
"storageOption": "External",
"singleton": 0,
@@ -14536,10 +14567,10 @@
]
},
{
- "name": "Device Energy Management Mode",
- "code": 159,
+ "name": "Energy EVSE Mode",
+ "code": 157,
"mfgCode": null,
- "define": "DEVICE_ENERGY_MANAGEMENT_MODE_CLUSTER",
+ "define": "ENERGY_EVSE_MODE_CLUSTER",
"side": "server",
"enabled": 1,
"apiMaturity": "provisional",
@@ -14693,48 +14724,35 @@
]
},
{
- "name": "Energy Preference",
- "code": 155,
+ "name": "Device Energy Management Mode",
+ "code": 159,
"mfgCode": null,
- "define": "ENERGY_PREFERENCE_CLUSTER",
+ "define": "DEVICE_ENERGY_MANAGEMENT_MODE_CLUSTER",
"side": "server",
"enabled": 1,
- "attributes": [
+ "apiMaturity": "provisional",
+ "commands": [
{
- "name": "EnergyBalances",
+ "name": "ChangeToMode",
"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
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
},
{
- "name": "CurrentEnergyBalance",
+ "name": "ChangeToModeResponse",
"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
- },
+ "source": "server",
+ "isIncoming": 0,
+ "isEnabled": 1
+ }
+ ],
+ "attributes": [
{
- "name": "EnergyPriorities",
- "code": 2,
+ "name": "SupportedModes",
+ "code": 0,
"mfgCode": null,
"side": "server",
"type": "array",
@@ -14749,11 +14767,11 @@
"reportableChange": 0
},
{
- "name": "LowPowerModeSensitivities",
- "code": 3,
+ "name": "CurrentMode",
+ "code": 1,
"mfgCode": null,
"side": "server",
- "type": "array",
+ "type": "int8u",
"included": 1,
"storageOption": "External",
"singleton": 0,
@@ -14764,22 +14782,6 @@
"maxInterval": 65534,
"reportableChange": 0
},
- {
- "name": "CurrentLowPowerModeSensitivity",
- "code": 4,
- "mfgCode": null,
- "side": "server",
- "type": "int8u",
- "included": 1,
- "storageOption": "RAM",
- "singleton": 0,
- "bounded": 0,
- "defaultValue": "",
- "reportable": 1,
- "minInterval": 1,
- "maxInterval": 65534,
- "reportableChange": 0
- },
{
"name": "GeneratedCommandList",
"code": 65528,
@@ -14851,10 +14853,10 @@
"side": "server",
"type": "bitmap32",
"included": 1,
- "storageOption": "RAM",
+ "storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "3",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -14872,8 +14874,8 @@
"bounded": 0,
"defaultValue": "1",
"reportable": 1,
- "minInterval": 0,
- "maxInterval": 65344,
+ "minInterval": 1,
+ "maxInterval": 65534,
"reportableChange": 0
}
]
@@ -16468,7 +16470,6 @@
"define": "FAN_CONTROL_CLUSTER",
"side": "server",
"enabled": 1,
- "apiMaturity": "provisional",
"commands": [
{
"name": "Step",
@@ -18751,7 +18752,7 @@
"storageOption": "RAM",
"singleton": 0,
"bounded": 0,
- "defaultValue": "3",
+ "defaultValue": "4",
"reportable": 1,
"minInterval": 0,
"maxInterval": 65344,
@@ -23993,7 +23994,7 @@
"storageOption": "RAM",
"singleton": 0,
"bounded": 0,
- "defaultValue": "5",
+ "defaultValue": "6",
"reportable": 1,
"minInterval": 0,
"maxInterval": 65344,
@@ -24764,7 +24765,7 @@
"storageOption": "RAM",
"singleton": 0,
"bounded": 0,
- "defaultValue": "3",
+ "defaultValue": "4",
"reportable": 1,
"minInterval": 0,
"maxInterval": 65344,
@@ -25288,28 +25289,32 @@
"endpointTypeIndex": 0,
"profileId": 259,
"endpointId": 0,
- "networkId": 0
+ "networkId": 0,
+ "parentEndpointIdentifier": null
},
{
"endpointTypeName": "MA-onofflight",
"endpointTypeIndex": 1,
"profileId": 259,
"endpointId": 1,
- "networkId": 0
+ "networkId": 0,
+ "parentEndpointIdentifier": null
},
{
"endpointTypeName": "MA-onofflight",
"endpointTypeIndex": 2,
"profileId": 259,
"endpointId": 2,
- "networkId": 0
+ "networkId": 0,
+ "parentEndpointIdentifier": null
},
{
"endpointTypeName": "Anonymous Endpoint Type",
"endpointTypeIndex": 3,
"profileId": 259,
"endpointId": 65534,
- "networkId": 0
+ "networkId": 0,
+ "parentEndpointIdentifier": null
}
]
}
\ No newline at end of file
diff --git a/examples/all-clusters-app/ameba/chip_main.cmake b/examples/all-clusters-app/ameba/chip_main.cmake
index c4572063508ac0..2afdd4e8d70942 100755
--- a/examples/all-clusters-app/ameba/chip_main.cmake
+++ b/examples/all-clusters-app/ameba/chip_main.cmake
@@ -153,6 +153,8 @@ endif (matter_enable_ota_requestor)
list(
APPEND ${list_chip_main_sources}
+ ${chip_dir}/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp
+
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/air-quality-instance.cpp
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/concentration-measurement-instances.cpp
@@ -161,6 +163,7 @@ list(
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/energy-preference-delegate.cpp
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/oven-modes.cpp
+ ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/laundry-dryer-controls-delegate-impl.cpp
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/laundry-washer-controls-delegate-impl.cpp
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/resource-monitoring-delegates.cpp
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/rvc-modes.cpp
@@ -169,6 +172,10 @@ list(
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/rvc-operational-state-delegate-impl.cpp
+ ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/microwave-oven-mode.cpp
+ ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/oven-modes.cpp
+ ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/oven-operational-state-delegate.cpp
+
${chip_dir}/examples/all-clusters-app/ameba/main/chipinterface.cpp
${chip_dir}/examples/all-clusters-app/ameba/main/BindingHandler.cpp
${chip_dir}/examples/all-clusters-app/ameba/main/DeviceCallbacks.cpp
@@ -178,6 +185,8 @@ list(
${chip_dir}/examples/all-clusters-app/ameba/main/ManualOperationCommand.cpp
${chip_dir}/examples/all-clusters-app/ameba/main/SmokeCOAlarmManager.cpp
+ ${chip_dir}/examples/microwave-oven-app/microwave-oven-common/src/microwave-oven-device.cpp
+
${chip_dir}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp
${chip_dir}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp
${chip_dir}/examples/energy-management-app/energy-management-common/src/ElectricalPowerMeasurementDelegate.cpp
@@ -228,6 +237,8 @@ target_include_directories(
${chip_dir}/zzz_generated/app-common
${chip_dir}/examples/all-clusters-app/all-clusters-common
${chip_dir}/examples/all-clusters-app/all-clusters-common/include
+ ${chip_dir}/examples/microwave-oven-app/microwave-oven-common
+ ${chip_dir}/examples/microwave-oven-app/microwave-oven-common/include
${chip_dir}/examples/energy-management-app/energy-management-common/include
${chip_dir}/examples/all-clusters-app/ameba/main/include
${chip_dir}/examples/platform/ameba
diff --git a/examples/all-clusters-app/ameba/main/ManualOperationCommand.cpp b/examples/all-clusters-app/ameba/main/ManualOperationCommand.cpp
index feb346b892f6bb..d03dbcd42ae0bd 100644
--- a/examples/all-clusters-app/ameba/main/ManualOperationCommand.cpp
+++ b/examples/all-clusters-app/ameba/main/ManualOperationCommand.cpp
@@ -79,6 +79,7 @@ static void RegisterManualOperationCommands()
{ &ManualRVCCommandHandler, "rvc", " Usage: manual rvc " },
{ &ManualRefrigeratorAlarmCommandHandler, "refalm", " Usage: manual refalm " },
{ &ManualDishWasherAlarmCommandHandler, "dishalm", " Usage: manual dishalm " },
+ { &ManualOvenCavityOperationalStateCommandHandler, "oven-opstate", " Usage: manual dishalm " },
};
static const shell_command_t sManualOperationalStateSubCommands[] = {
@@ -123,6 +124,14 @@ static void RegisterManualOperationCommands()
{ &ManualDishWasherAlarmSetLowerCommandHandler, "lower", "lower Usage: manual dishalm lower" },
};
+ static const shell_command_t sManualOvenCavityOperationalStateSubCommands[] = {
+ { &ManualOvenCavityOperationalStateCommandHelpHandler, "help", "Usage: manual oven-opstate " },
+ { &ManualOvenCavityOperationalStateSetStateCommandHandler, "set-state",
+ "set-state Usage: manual oven-opstate set-state " },
+ { &ManualOvenCavityOperationalStateSetErrorCommandHandler, "set-error",
+ "set-error Usage: manual oven-opstate set-error " },
+ };
+
static const shell_command_t sManualOperationCommand = { &ManualOperationCommandHandler, "manual",
"Manual Operation commands. Usage: manual " };
@@ -139,6 +148,8 @@ static void RegisterManualOperationCommands()
ArraySize(sManualRefrigeratorAlarmStateSubCommands));
sShellManualDishWasherAlarmStateSubCommands.RegisterCommands(sManualDishWasherAlarmSubCommands,
ArraySize(sManualDishWasherAlarmSubCommands));
+ sShellManualOvenCavityOperationalStateSubCommands.RegisterCommands(sManualOvenCavityOperationalStateSubCommands,
+ ArraySize(sManualOvenCavityOperationalStateSubCommands));
Engine::Root().RegisterCommands(&sManualOperationCommand, 1);
}
diff --git a/examples/all-clusters-app/ameba/main/chipinterface.cpp b/examples/all-clusters-app/ameba/main/chipinterface.cpp
index 20de9cd1ff0124..c9547136035f81 100644
--- a/examples/all-clusters-app/ameba/main/chipinterface.cpp
+++ b/examples/all-clusters-app/ameba/main/chipinterface.cpp
@@ -17,6 +17,7 @@
#include
+#include "AmebaObserver.h"
#include "BindingHandler.h"
#include "CHIPDeviceManager.h"
#include "DeviceCallbacks.h"
@@ -28,13 +29,16 @@
#include
#include
+#include
#include
#include
#include
#include
#include
+#include
#include
#include
+#include
#include
#include
#include
@@ -43,6 +47,7 @@
#include
#include
#if CONFIG_ENABLE_AMEBA_TEST_EVENT_TRIGGER
+#include
#include
#endif
@@ -140,11 +145,11 @@ static void InitServer(intptr_t context)
static chip::CommonCaseDeviceServerInitParams initParams;
#if CONFIG_ENABLE_AMEBA_TEST_EVENT_TRIGGER
- // TODO(#31723): Show to customers that they can do `Server::GetInstance().GetTestEventTriggerDelegate().AddHandler(xxx)`
- // to add custom handlers during their app init, after InitServer.
static AmebaTestEventTriggerDelegate sTestEventTriggerDelegate{ ByteSpan(sTestEventTriggerEnableKey) };
initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate;
#endif
+ static AmebaObserver sAmebaObserver;
+ initParams.appDelegate = &sAmebaObserver;
initParams.InitializeStaticResourcesBeforeServerInit();
@@ -166,6 +171,12 @@ static void InitServer(intptr_t context)
InitManualOperation();
#endif
app::Clusters::TemperatureControl::SetInstance(&sAppSupportedTemperatureLevelsDelegate);
+ MatterMicrowaveOvenServerInit();
+#if CONFIG_ENABLE_AMEBA_TEST_EVENT_TRIGGER
+ static SmokeCOTestEventTriggerHandler sSmokeCOTestEventTriggerHandler;
+ Server::GetInstance().GetTestEventTriggerDelegate()->AddHandler(&sSmokeCOTestEventTriggerHandler);
+#endif
+ chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(&sAmebaObserver);
}
extern "C" void ChipTest(void)
@@ -213,3 +224,9 @@ void emberAfLaundryWasherControlsClusterInitCallback(EndpointId endpoint)
{
LaundryWasherControlsServer::SetDefaultDelegate(endpoint, &LaundryWasherControlDelegate::getLaundryWasherControlDelegate());
}
+
+using namespace chip::app::Clusters::LaundryDryerControls;
+void emberAfLaundryDryerControlsClusterInitCallback(EndpointId endpoint)
+{
+ LaundryDryerControlsServer::SetDefaultDelegate(endpoint, &LaundryDryerControlDelegate::getLaundryDryerControlDelegate());
+}
diff --git a/examples/all-clusters-app/ameba/main/include/AmebaObserver.h b/examples/all-clusters-app/ameba/main/include/AmebaObserver.h
new file mode 100644
index 00000000000000..a19c9c99954def
--- /dev/null
+++ b/examples/all-clusters-app/ameba/main/include/AmebaObserver.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+
+namespace chip {
+
+class AmebaObserver : public AppDelegate, public FabricTable::Delegate
+{
+public:
+ // Commissioning Observer
+ void OnCommissioningSessionEstablishmentError(CHIP_ERROR err) override
+ {
+ ChipLogProgress(DeviceLayer, "Ameba Observer: Commissioning error (0x%x)", err);
+ // Handle commissioning errror here
+ }
+ // Fabric Observer
+ void OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) override
+ {
+ ChipLogProgress(DeviceLayer, "Ameba Observer: Fabric 0x%x has been Removed", fabricIndex);
+ if (chip::Server::GetInstance().GetFabricTable().FabricCount() == 0)
+ {
+ // Customer code
+ }
+ }
+};
+
+} // namespace chip
diff --git a/examples/all-clusters-app/ameba/main/include/ManualOperationalStateCommand.h b/examples/all-clusters-app/ameba/main/include/ManualOperationalStateCommand.h
index fc2825576e6b72..31e186ae77d2a8 100644
--- a/examples/all-clusters-app/ameba/main/include/ManualOperationalStateCommand.h
+++ b/examples/all-clusters-app/ameba/main/include/ManualOperationalStateCommand.h
@@ -19,6 +19,7 @@
#include "controller/InvokeInteraction.h"
#include "controller/ReadInteraction.h"
#include "operational-state-delegate-impl.h"
+#include "oven-operational-state-delegate.h"
#include "rvc-operational-state-delegate-impl.h"
#if CONFIG_ENABLE_CHIP_SHELL
@@ -39,6 +40,7 @@ using Shell::streamer_printf;
Engine sShellManualOperationalStateSubCommands;
Engine sShellManualRVCOperationalStateSubCommands;
+Engine sShellManualOvenCavityOperationalStateSubCommands;
#endif // defined(ENABLE_CHIP_SHELL)
#if CONFIG_ENABLE_CHIP_SHELL
@@ -183,4 +185,71 @@ CHIP_ERROR ManualRVCOperationalStateSetErrorCommandHandler(int argc, char ** arg
return CHIP_NO_ERROR;
}
+
+/********************************************************
+ * Oven Cavity Operational State Functions
+ *********************************************************/
+
+CHIP_ERROR ManualOvenCavityOperationalStateCommandHelpHandler(int argc, char ** argv)
+{
+ sShellManualOvenCavityOperationalStateSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ManualOvenCavityOperationalStateCommandHandler(int argc, char ** argv)
+{
+ if (argc == 0)
+ {
+ return ManualOvenCavityOperationalStateCommandHelpHandler(argc, argv);
+ }
+
+ return sShellManualOvenCavityOperationalStateSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR ManualOvenCavityOperationalStateSetStateCommandHandler(int argc, char ** argv)
+{
+ if (argc != 1)
+ {
+ return ManualOvenCavityOperationalStateCommandHelpHandler(argc, argv);
+ }
+ uint32_t state = atoi(argv[0]);
+
+ CHIP_ERROR err;
+ err = OvenCavityOperationalState::GetOperationalStateInstance()->SetOperationalState(state);
+
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(DeviceLayer, "ManualOvenCavityOperationalStateSetStateCommandHandler Failed!\r\n");
+ }
+
+ return err;
+}
+
+CHIP_ERROR ManualOvenCavityOperationalStateSetErrorCommandHandler(int argc, char ** argv)
+{
+ if (argc != 1)
+ {
+ return ManualOvenCavityOperationalStateCommandHelpHandler(argc, argv);
+ }
+
+ GenericOperationalError err(to_underlying(ErrorStateEnum::kNoError));
+ uint32_t error = atoi(argv[0]);
+
+ switch (error)
+ {
+ case to_underlying(OvenCavityOperationalState::ErrorStateEnum::kNoError): // 0x00, 0
+ case to_underlying(OvenCavityOperationalState::ErrorStateEnum::kUnableToStartOrResume): // 0x01, 1
+ case to_underlying(OvenCavityOperationalState::ErrorStateEnum::kUnableToCompleteOperation): // 0x02, 2
+ case to_underlying(OvenCavityOperationalState::ErrorStateEnum::kCommandInvalidInState): // 0x03, 3
+ err.errorStateID = error;
+ break;
+ default:
+ err.errorStateID = to_underlying(OvenCavityOperationalState::ErrorStateEnum::kUnknownEnumValue); // 0x04, 4
+ break;
+ }
+
+ OvenCavityOperationalState::GetOperationalStateInstance()->OnOperationalErrorDetected(err);
+
+ return CHIP_NO_ERROR;
+}
#endif // CONFIG_ENABLE_CHIP_SHELL
diff --git a/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp b/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp
index b2fe3a90b59f3f..d1bab3649f0b67 100644
--- a/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp
+++ b/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp
@@ -19,12 +19,12 @@
#include "AllClustersCommandDelegate.h"
#include
-#include
#include
#include
#include
#include
#include
+#include
#include
#include
diff --git a/examples/all-clusters-app/linux/main-common.cpp b/examples/all-clusters-app/linux/main-common.cpp
index 775f4a1c0f324c..8760bcb92d456c 100644
--- a/examples/all-clusters-app/linux/main-common.cpp
+++ b/examples/all-clusters-app/linux/main-common.cpp
@@ -40,7 +40,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -50,6 +49,7 @@
#include
#include
#include
+#include
#include
#include
#include
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 dbb244cf6265b3..0c9569504c7846 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
@@ -1694,7 +1694,7 @@ cluster SoftwareDiagnostics = 52 {
/** The Thread Network Diagnostics Cluster provides a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems */
cluster ThreadNetworkDiagnostics = 53 {
- revision 1; // NOTE: Default/not specifically set
+ revision 2;
enum ConnectionStatusEnum : enum8 {
kConnected = 0;
@@ -4428,7 +4428,7 @@ cluster RelativeHumidityMeasurement = 1029 {
/** Attributes and commands for configuring occupancy sensing, and reporting occupancy status. */
cluster OccupancySensing = 1030 {
- revision 3;
+ revision 4;
enum OccupancySensorTypeEnum : enum8 {
kPIR = 0;
@@ -6120,7 +6120,7 @@ endpoint 0 {
callback attribute operationalDatasetComponents;
callback attribute activeNetworkFaultsList;
ram attribute featureMap default = 0;
- ram attribute clusterRevision default = 1;
+ ram attribute clusterRevision default = 2;
}
server cluster WiFiNetworkDiagnostics {
@@ -6571,7 +6571,7 @@ endpoint 1 {
ram attribute occupancySensorType;
ram attribute occupancySensorTypeBitmap;
ram attribute featureMap default = 0;
- ram attribute clusterRevision default = 3;
+ ram attribute clusterRevision default = 4;
}
server cluster WakeOnLan {
@@ -6916,7 +6916,7 @@ endpoint 2 {
ram attribute occupancySensorType;
ram attribute occupancySensorTypeBitmap;
ram attribute featureMap default = 0;
- ram attribute clusterRevision default = 3;
+ ram attribute clusterRevision default = 4;
}
}
endpoint 65534 {
diff --git a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.zap b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.zap
index 2d64015215a5ce..3294f430a3e337 100644
--- a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.zap
+++ b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.zap
@@ -1,6 +1,6 @@
{
"fileFormat": 2,
- "featureLevel": 99,
+ "featureLevel": 100,
"creator": "zap",
"keyValuePairs": [
{
@@ -2618,10 +2618,10 @@
"side": "server",
"type": "bitmap32",
"included": 1,
- "storageOption": "RAM",
+ "storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "0",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -2634,10 +2634,10 @@
"side": "server",
"type": "int16u",
"included": 1,
- "storageOption": "RAM",
+ "storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "0x0002",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 0,
"maxInterval": 65344,
@@ -2993,7 +2993,7 @@
"storageOption": "RAM",
"singleton": 0,
"bounded": 0,
- "defaultValue": "1",
+ "defaultValue": "2",
"reportable": 1,
"minInterval": 0,
"maxInterval": 65344,
@@ -6999,7 +6999,6 @@
"define": "FAN_CONTROL_CLUSTER",
"side": "server",
"enabled": 1,
- "apiMaturity": "provisional",
"attributes": [
{
"name": "FanMode",
@@ -7998,7 +7997,7 @@
"storageOption": "RAM",
"singleton": 0,
"bounded": 0,
- "defaultValue": "3",
+ "defaultValue": "4",
"reportable": 1,
"minInterval": 0,
"maxInterval": 65344,
@@ -11824,7 +11823,7 @@
"storageOption": "RAM",
"singleton": 0,
"bounded": 0,
- "defaultValue": "3",
+ "defaultValue": "4",
"reportable": 1,
"minInterval": 0,
"maxInterval": 65344,
@@ -12348,28 +12347,32 @@
"endpointTypeIndex": 0,
"profileId": 259,
"endpointId": 0,
- "networkId": 0
+ "networkId": 0,
+ "parentEndpointIdentifier": null
},
{
"endpointTypeName": "MA-onofflight",
"endpointTypeIndex": 1,
"profileId": 259,
"endpointId": 1,
- "networkId": 0
+ "networkId": 0,
+ "parentEndpointIdentifier": null
},
{
"endpointTypeName": "MA-onofflight",
"endpointTypeIndex": 2,
"profileId": 259,
"endpointId": 2,
- "networkId": 0
+ "networkId": 0,
+ "parentEndpointIdentifier": null
},
{
"endpointTypeName": "Anonymous Endpoint Type",
"endpointTypeIndex": 3,
"profileId": 259,
"endpointId": 65534,
- "networkId": 0
+ "networkId": 0,
+ "parentEndpointIdentifier": null
}
]
}
\ No newline at end of file
diff --git a/examples/all-clusters-minimal-app/linux/main-common.cpp b/examples/all-clusters-minimal-app/linux/main-common.cpp
index a6fd0a9866220e..d9f0a51cd747cf 100644
--- a/examples/all-clusters-minimal-app/linux/main-common.cpp
+++ b/examples/all-clusters-minimal-app/linux/main-common.cpp
@@ -19,10 +19,10 @@
#include "include/tv-callbacks.h"
#include
#include
-#include
#include
#include
#include
+#include
#include
#include
#include
diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt
index 5b49a6d9ab05ab..2ffbec50c746a2 100644
--- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt
+++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt
@@ -16,7 +16,7 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import chip.devicecontroller.ChipDeviceController
import chip.devicecontroller.ChipIdLookup
-import chip.devicecontroller.InvokeCallback
+import chip.devicecontroller.ExtendableInvokeCallback
import chip.devicecontroller.ReportCallback
import chip.devicecontroller.ResubscriptionAttemptCallback
import chip.devicecontroller.SubscriptionEstablishedCallback
@@ -26,6 +26,8 @@ import chip.devicecontroller.model.ChipAttributePath
import chip.devicecontroller.model.ChipEventPath
import chip.devicecontroller.model.ChipPathId
import chip.devicecontroller.model.InvokeElement
+import chip.devicecontroller.model.InvokeResponseData
+import chip.devicecontroller.model.NoInvokeResponseData
import chip.devicecontroller.model.NodeState
import chip.devicecontroller.model.Status
import com.google.chip.chiptool.ChipClient
@@ -57,6 +59,8 @@ class WildcardFragment : Fragment() {
private val attributePath = ArrayList()
private val eventPath = ArrayList()
+ private val writePath = ArrayList()
+ private val invokePath = ArrayList()
private val subscribeIdList = ArrayList()
private val reportCallback =
@@ -89,29 +93,47 @@ class WildcardFragment : Fragment() {
private val writeAttributeCallback =
object : WriteAttributesCallback {
+ var viewText = ""
+
override fun onError(attributePath: ChipAttributePath?, ex: Exception?) {
Log.e(TAG, "Report error for $attributePath: $ex")
+ viewText += "onError : $attributePath - $ex\n"
}
override fun onResponse(attributePath: ChipAttributePath, status: Status) {
- val text = "$attributePath : Write response: $status"
- requireActivity().runOnUiThread { binding.outputTv.text = text }
+ viewText += "$attributePath : Write response: $status\n"
}
override fun onDone() {
- Log.i(TAG, "write attribute Done")
+ requireActivity().runOnUiThread {
+ binding.outputTv.text = viewText
+ viewText = ""
+ }
}
}
- private val invokeCallback =
- object : InvokeCallback {
+ private val extendableInvokeCallback =
+ object : ExtendableInvokeCallback {
+ var viewText = ""
+
override fun onError(e: java.lang.Exception?) {
+ viewText += "Invoke onError : $e\n"
Log.e(TAG, "Report error", e)
}
- override fun onResponse(invokeElement: InvokeElement?, successCode: Long) {
- val text = "Invoke Response : $invokeElement, $successCode"
- requireActivity().runOnUiThread { binding.outputTv.text = text }
+ override fun onResponse(invokeResponseData: InvokeResponseData?) {
+ viewText += "Invoke Response : $invokeResponseData\n"
+ }
+
+ override fun onNoResponse(noInvokeResponseData: NoInvokeResponseData?) {
+ viewText += "Invoke onNoResponse : $noInvokeResponseData\n"
+ }
+
+ override fun onDone() {
+ requireActivity().runOnUiThread {
+ binding.outputTv.text = viewText
+ viewText = ""
+ }
}
}
@@ -123,41 +145,27 @@ class WildcardFragment : Fragment() {
_binding = WildcardFragmentBinding.inflate(inflater, container, false)
scope = viewLifecycleOwner.lifecycleScope
- binding.selectTypeRadioGroup.setOnCheckedChangeListener { _, i ->
- val readBtnOn = (i == R.id.readRadioBtn)
- val subscribeBtnOn = (i == R.id.subscribeRadioBtn)
- val writeBtnOn = (i == R.id.writeRadioBtn)
- val invokeBtnOn = (i == R.id.invokeRadioBtn)
-
- binding.addLayout.visibility = getVisibility(readBtnOn || subscribeBtnOn)
- binding.attributeIdLabel.visibility = getVisibility(readBtnOn || subscribeBtnOn || writeBtnOn)
- binding.attributeIdEd.visibility = getVisibility(readBtnOn || subscribeBtnOn || writeBtnOn)
- binding.eventIdLabel.visibility = getVisibility(readBtnOn || subscribeBtnOn)
- binding.eventIdEd.visibility = getVisibility(readBtnOn || subscribeBtnOn)
- binding.commandIdLabel.visibility = getVisibility(invokeBtnOn)
- binding.commandIdEd.visibility = getVisibility(invokeBtnOn)
- binding.isUrgentLabel.visibility = getVisibility(subscribeBtnOn)
- binding.isUrgentSp.visibility = getVisibility(subscribeBtnOn)
- binding.shutdownSubscriptionBtn.visibility = getVisibility(subscribeBtnOn)
- }
+ val writeTypeSpinnerAdapter =
+ ArrayAdapter(
+ requireActivity(),
+ android.R.layout.simple_spinner_dropdown_item,
+ TLV_MAP.keys.toList()
+ )
+ binding.writeValueTypeSp.adapter = writeTypeSpinnerAdapter
- binding.sendBtn.setOnClickListener {
- if (binding.readRadioBtn.isChecked) {
- showReadDialog()
- } else if (binding.subscribeRadioBtn.isChecked) {
- showSubscribeDialog()
- } else if (binding.writeRadioBtn.isChecked) {
- showWriteDialog()
- } else if (binding.invokeRadioBtn.isChecked) {
- showInvokeDialog()
- }
+ binding.selectTypeRadioGroup.setOnCheckedChangeListener { _, radioBtnId ->
+ setVisibilityEachView(radioBtnId)
}
+ binding.sendBtn.setOnClickListener { showDialog() }
+
binding.shutdownSubscriptionBtn.setOnClickListener { showShutdownSubscriptionDialog() }
- binding.addAttributeBtn.setOnClickListener { addPathList(ATTRIBUTE) }
- binding.addEventBtn.setOnClickListener { addPathList(EVENT) }
+ binding.addAttributeBtn.setOnClickListener { addPathList(SendType.ATTRIBUTE) }
+ binding.addEventBtn.setOnClickListener { addPathList(SendType.EVENT) }
+ binding.addListBtn.setOnClickListener { addRequest() }
binding.resetBtn.setOnClickListener { resetPath() }
+ binding.writeInvokeresetBtn.setOnClickListener { resetPath() }
addressUpdateFragment =
childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment
@@ -165,6 +173,58 @@ class WildcardFragment : Fragment() {
return binding.root
}
+ private fun setVisibilityEachView(radioBtnId: Int) {
+ val readBtnOn = (radioBtnId == R.id.readRadioBtn)
+ val subscribeBtnOn = (radioBtnId == R.id.subscribeRadioBtn)
+ val writeBtnOn = (radioBtnId == R.id.writeRadioBtn)
+ val invokeBtnOn = (radioBtnId == R.id.invokeRadioBtn)
+
+ binding.addAttributeBtn.visibility = getVisibility(readBtnOn || subscribeBtnOn)
+ binding.addEventBtn.visibility = getVisibility(readBtnOn || subscribeBtnOn)
+ binding.resetBtn.visibility = getVisibility(readBtnOn || subscribeBtnOn)
+ binding.attributeIdLabel.visibility = getVisibility(readBtnOn || subscribeBtnOn || writeBtnOn)
+ binding.attributeIdEd.visibility = getVisibility(readBtnOn || subscribeBtnOn || writeBtnOn)
+ binding.eventIdLabel.visibility = getVisibility(readBtnOn || subscribeBtnOn)
+ binding.eventIdEd.visibility = getVisibility(readBtnOn || subscribeBtnOn)
+ binding.addListBtn.visibility = getVisibility(writeBtnOn || invokeBtnOn)
+ binding.commandIdLabel.visibility = getVisibility(invokeBtnOn)
+ binding.commandIdEd.visibility = getVisibility(invokeBtnOn)
+ binding.isUrgentLabel.visibility = getVisibility(subscribeBtnOn)
+ binding.isUrgentSp.visibility = getVisibility(subscribeBtnOn)
+ binding.writeValueLabel.visibility = getVisibility(writeBtnOn)
+ binding.writeValueEd.visibility = getVisibility(writeBtnOn)
+ binding.writeValueTypeLabel.visibility = getVisibility(writeBtnOn)
+ binding.writeValueTypeSp.visibility = getVisibility(writeBtnOn)
+ binding.dataVersionLabel.visibility = getVisibility(writeBtnOn)
+ binding.dataVersionEd.visibility = getVisibility(writeBtnOn)
+ binding.invokeValueLabel.visibility = getVisibility(invokeBtnOn)
+ binding.invokeValueEd.visibility = getVisibility(invokeBtnOn)
+ binding.shutdownSubscriptionBtn.visibility = getVisibility(subscribeBtnOn)
+ binding.writeInvokeresetBtn.visibility = getVisibility(writeBtnOn || invokeBtnOn)
+
+ resetPath()
+ }
+
+ private fun showDialog() {
+ if (binding.readRadioBtn.isChecked) {
+ showReadDialog()
+ } else if (binding.subscribeRadioBtn.isChecked) {
+ showSubscribeDialog()
+ } else if (binding.writeRadioBtn.isChecked) {
+ showWriteDialog()
+ } else if (binding.invokeRadioBtn.isChecked) {
+ showInvokeDialog()
+ }
+ }
+
+ private fun addRequest() {
+ if (binding.writeRadioBtn.isChecked) {
+ addWriteRequest()
+ } else {
+ addInvokeRequest()
+ }
+ }
+
private fun getVisibility(isShowing: Boolean): Int {
return if (isShowing) {
View.VISIBLE
@@ -173,7 +233,7 @@ class WildcardFragment : Fragment() {
}
}
- private fun addPathList(type: Int) {
+ private fun addPathList(type: SendType) {
val endpointId = getChipPathIdForText(binding.endpointIdEd.text.toString())
val clusterId = getChipPathIdForText(binding.clusterIdEd.text.toString())
val attributeId = getChipPathIdForText(binding.attributeIdEd.text.toString())
@@ -183,9 +243,9 @@ class WildcardFragment : Fragment() {
(binding.subscribeRadioBtn.isChecked) &&
(binding.isUrgentSp.selectedItem.toString().toBoolean())
- if (type == ATTRIBUTE) {
+ if (type == SendType.ATTRIBUTE) {
attributePath.add(ChipAttributePath.newInstance(endpointId, clusterId, attributeId))
- } else if (type == EVENT) {
+ } else if (type == SendType.EVENT) {
eventPath.add(ChipEventPath.newInstance(endpointId, clusterId, eventId, isUrgent))
}
updateAddListView()
@@ -194,6 +254,8 @@ class WildcardFragment : Fragment() {
private fun resetPath() {
attributePath.clear()
eventPath.clear()
+ writePath.clear()
+ invokePath.clear()
updateAddListView()
}
@@ -205,6 +267,12 @@ class WildcardFragment : Fragment() {
for (event in eventPath) {
builder.append("event($event)\n")
}
+ for (write in writePath) {
+ builder.append("WritePath($write)\n")
+ }
+ for (invoke in invokePath) {
+ builder.append("InvokePath($invoke)\n")
+ }
binding.sendListView.text = builder.toString()
}
@@ -312,13 +380,11 @@ class WildcardFragment : Fragment() {
)
}
- private suspend fun write(
- writeValueType: String,
- writeValue: String,
- dataVersion: Int?,
- timedRequestTimeoutMs: Int,
- imTimeoutMs: Int
- ) {
+ private fun addWriteRequest() {
+ val writeValue = binding.writeValueEd.text.toString()
+ val writeValueType = binding.writeValueTypeSp.selectedItem.toString()
+ val dataVersion = binding.dataVersionEd.text.toString()
+
val endpointId =
if (!addressUpdateFragment.isGroupId()) {
getChipPathIdForText(binding.endpointIdEd.text.toString())
@@ -329,10 +395,10 @@ class WildcardFragment : Fragment() {
val attributeId = getChipPathIdForText(binding.attributeIdEd.text.toString())
val version =
- if (dataVersion == null) {
+ if (dataVersion.isEmpty()) {
Optional.empty()
} else {
- Optional.of(dataVersion)
+ Optional.of(dataVersion.toInt())
}
lateinit var writeRequest: AttributeWriteRequest
@@ -364,26 +430,15 @@ class WildcardFragment : Fragment() {
version
)
}
- val devicePtr =
- try {
- addressUpdateFragment.getDevicePointer(requireContext())
- } catch (e: IllegalStateException) {
- Log.d(TAG, "getDevicePointer exception", e)
- return
- }
- deviceController.write(
- writeAttributeCallback,
- devicePtr,
- listOf(writeRequest),
- timedRequestTimeoutMs,
- imTimeoutMs
- )
+ writePath.add(writeRequest)
+ updateAddListView()
}
- private suspend fun invoke(invokeJson: String, timedRequestTimeoutMs: Int, imTimeoutMs: Int) {
+ private fun addInvokeRequest() {
val endpointId = getChipPathIdForText(binding.endpointIdEd.text.toString())
val clusterId = getChipPathIdForText(binding.clusterIdEd.text.toString())
val commandId = getChipPathIdForText(binding.commandIdEd.text.toString())
+ val invokeJson = binding.invokeValueEd.text.toString()
val jsonString = invokeJson.ifEmpty { "{}" }
val invokeElement =
@@ -398,6 +453,28 @@ class WildcardFragment : Fragment() {
} else {
InvokeElement.newInstance(endpointId, clusterId, commandId, null, jsonString)
}
+ invokePath.add(invokeElement)
+ updateAddListView()
+ }
+
+ private suspend fun write(timedRequestTimeoutMs: Int, imTimeoutMs: Int) {
+ val devicePtr =
+ try {
+ addressUpdateFragment.getDevicePointer(requireContext())
+ } catch (e: IllegalStateException) {
+ Log.d(TAG, "getDevicePointer exception", e)
+ return
+ }
+ deviceController.write(
+ writeAttributeCallback,
+ devicePtr,
+ writePath,
+ timedRequestTimeoutMs,
+ imTimeoutMs
+ )
+ }
+
+ private suspend fun invoke(timedRequestTimeoutMs: Int, imTimeoutMs: Int) {
val devicePtr =
try {
addressUpdateFragment.getDevicePointer(requireContext())
@@ -405,10 +482,10 @@ class WildcardFragment : Fragment() {
Log.d(TAG, "getDevicePointer exception", e)
return
}
- deviceController.invoke(
- invokeCallback,
+ deviceController.extendableInvoke(
+ extendableInvokeCallback,
devicePtr,
- invokeElement,
+ invokePath,
timedRequestTimeoutMs,
imTimeoutMs
)
@@ -453,31 +530,14 @@ class WildcardFragment : Fragment() {
private fun showWriteDialog() {
binding.outputTv.text = ""
val dialogView = requireActivity().layoutInflater.inflate(R.layout.write_dialog, null)
- val writeValueTypeSp = dialogView.findViewById(R.id.writeValueTypeSp)
- val spinnerAdapter =
- ArrayAdapter(
- requireActivity(),
- android.R.layout.simple_spinner_dropdown_item,
- TLV_MAP.keys.toList()
- )
- writeValueTypeSp.adapter = spinnerAdapter
val dialog = AlertDialog.Builder(requireContext()).apply { setView(dialogView) }.create()
dialogView.findViewById