diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 3d2c6295f88f0c..d3c222df06c380 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -40,7 +40,11 @@ RUN apt-get update \ icecc \ && : -RUN groupadd -g $USER_GID $USERNAME \ +RUN (getent passwd $USER_UID && userdel -f $(getent passwd $USER_UID | cut -d: -f1) || true) \ + && (getent group $USER_GID && groupdel -f $(getent group $USER_GID | cut -d: -f1) || true) \ + && (getent passwd $USERNAME && userdel -f $USERNAME || true) \ + && (getent group $USERNAME && groupdel -f $USERNAME || true) \ + && groupadd -g $USER_GID $USERNAME \ && useradd --no-log-init -s /bin/bash -u $USER_UID -g $USER_GID -G docker,sudo -m $USERNAME \ && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ && chmod 0440 /etc/sudoers.d/$USERNAME \ diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index a5dee8881fec76..c43d780c0f2a60 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -41,6 +41,9 @@ AFL AIDL algs alloc +allocator +allocators +Ambrose Ameba amebad amebaiot @@ -317,6 +320,7 @@ cryptographic CSA csg csrrequest +cstdint csu csv ctl @@ -440,6 +444,7 @@ DNSStubListener docbuild Dockerfile Dockerfiles +docstrings Don'ts DoorLock DoorState @@ -565,6 +570,8 @@ FlowMeasurement FluorideConcentrationMeasurement focusable forkpty +formatter +formatters FOTA FreeRTOS FreeRTOSConfig @@ -731,6 +738,7 @@ IPython ISCAN isHexString isLowerCase +isort isUpperCase itemName iterable @@ -878,6 +886,7 @@ MediaPlayback MediaTek MEI mem +memcpy memdf MemMonitoring menuconfig @@ -933,6 +942,7 @@ mv MX mydir MyPASSWORD +mypy MySSID NAMESERVER NAMESPACE @@ -1442,6 +1452,7 @@ toJson tokenization tokenized tokenizer +toml toolchain toolchains topologies diff --git a/.github/workflows/bloat_check.yaml b/.github/workflows/bloat_check.yaml index 43a3993eee6a91..be423b04c039d7 100644 --- a/.github/workflows/bloat_check.yaml +++ b/.github/workflows/bloat_check.yaml @@ -34,7 +34,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 steps: - name: Checkout diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 92acd73acef165..2539edcf6a82fa 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -43,7 +43,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" @@ -139,7 +139,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" @@ -308,7 +308,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" @@ -371,7 +371,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" @@ -490,7 +490,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/chef.yaml b/.github/workflows/chef.yaml index d7360f6cc4876d..c897952d45107c 100644 --- a/.github/workflows/chef.yaml +++ b/.github/workflows/chef.yaml @@ -36,7 +36,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 options: --user root steps: @@ -57,7 +57,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-esp32:90 + image: ghcr.io/project-chip/chip-build-esp32:93 options: --user root steps: @@ -78,7 +78,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nrf-platform:90 + image: ghcr.io/project-chip/chip-build-nrf-platform:93 options: --user root steps: @@ -99,7 +99,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-telink:90 + image: ghcr.io/project-chip/chip-build-telink:93 options: --user root steps: @@ -111,7 +111,7 @@ jobs: platform: telink # - name: Update Zephyr to specific revision (for developers purpose) # shell: bash - # run: scripts/run_in_build_env.sh "python3 scripts/tools/telink/update_zephyr.py f762f1a1027284e63e338e6d83deeade62f355b0" + # run: scripts/run_in_build_env.sh "python3 scripts/tools/telink/update_zephyr.py 8b29ee6b118ebe6eeec3224dbe343474e11403d8" - name: CI Examples Telink shell: bash run: | diff --git a/.github/workflows/doxygen.yaml b/.github/workflows/doxygen.yaml index e345ff2a75a70e..eb45f76f389779 100644 --- a/.github/workflows/doxygen.yaml +++ b/.github/workflows/doxygen.yaml @@ -84,7 +84,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-doxygen:90 + image: ghcr.io/project-chip/chip-build-doxygen:93 if: github.actor != 'restyled-io[bot]' diff --git a/.github/workflows/examples-ameba.yaml b/.github/workflows/examples-ameba.yaml index a4b40a19339507..2c1c2555e797e2 100644 --- a/.github/workflows/examples-ameba.yaml +++ b/.github/workflows/examples-ameba.yaml @@ -39,7 +39,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-ameba:90 + image: ghcr.io/project-chip/chip-build-ameba:93 options: --user root steps: diff --git a/.github/workflows/examples-asr.yaml b/.github/workflows/examples-asr.yaml index 143ce3364fafad..61ac888ad415a6 100644 --- a/.github/workflows/examples-asr.yaml +++ b/.github/workflows/examples-asr.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-asr:90 + image: ghcr.io/project-chip/chip-build-asr:93 options: --user root steps: diff --git a/.github/workflows/examples-bouffalolab.yaml b/.github/workflows/examples-bouffalolab.yaml index 2e9cf4a8849edd..c0178a04c2cb48 100644 --- a/.github/workflows/examples-bouffalolab.yaml +++ b/.github/workflows/examples-bouffalolab.yaml @@ -38,7 +38,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-bouffalolab:90 + image: ghcr.io/project-chip/chip-build-bouffalolab:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-cc13xx_26xx.yaml b/.github/workflows/examples-cc13xx_26xx.yaml index 097a7d103eac95..0aaec6d6cc3bf3 100644 --- a/.github/workflows/examples-cc13xx_26xx.yaml +++ b/.github/workflows/examples-cc13xx_26xx.yaml @@ -42,7 +42,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-ti:90 + image: ghcr.io/project-chip/chip-build-ti:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-cc32xx.yaml b/.github/workflows/examples-cc32xx.yaml index 25afa79903f12d..c7615bc27de48f 100644 --- a/.github/workflows/examples-cc32xx.yaml +++ b/.github/workflows/examples-cc32xx.yaml @@ -41,7 +41,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-ti:90 + image: ghcr.io/project-chip/chip-build-ti:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-efr32.yaml b/.github/workflows/examples-efr32.yaml index dd9fb120a365b2..8e40a0df999f4c 100644 --- a/.github/workflows/examples-efr32.yaml +++ b/.github/workflows/examples-efr32.yaml @@ -41,7 +41,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-efr32:90 + image: ghcr.io/project-chip/chip-build-efr32:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-esp32.yaml b/.github/workflows/examples-esp32.yaml index 9853c0df51885d..20ced0375b8f5d 100644 --- a/.github/workflows/examples-esp32.yaml +++ b/.github/workflows/examples-esp32.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-esp32:90 + image: ghcr.io/project-chip/chip-build-esp32:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" @@ -124,7 +124,7 @@ jobs: if: github.actor != 'restyled-io[bot]' && github.repository_owner == 'espressif' container: - image: ghcr.io/project-chip/chip-build-esp32:90 + image: ghcr.io/project-chip/chip-build-esp32:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-infineon.yaml b/.github/workflows/examples-infineon.yaml index 49c2097cd696e8..5b7ee30abe1828 100644 --- a/.github/workflows/examples-infineon.yaml +++ b/.github/workflows/examples-infineon.yaml @@ -38,7 +38,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-infineon:90 + image: ghcr.io/project-chip/chip-build-infineon:93 env: # TODO: this should probably be part of the dockerfile itself CY_TOOLS_PATHS: /opt/Tools/ModusToolbox/tools_3.2 diff --git a/.github/workflows/examples-linux-arm.yaml b/.github/workflows/examples-linux-arm.yaml index 46c2173530c6be..84a36addb83f94 100644 --- a/.github/workflows/examples-linux-arm.yaml +++ b/.github/workflows/examples-linux-arm.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-crosscompile:90 + image: ghcr.io/project-chip/chip-build-crosscompile:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-linux-imx.yaml b/.github/workflows/examples-linux-imx.yaml index e1d64f7a058f1e..33098465c1cdcb 100644 --- a/.github/workflows/examples-linux-imx.yaml +++ b/.github/workflows/examples-linux-imx.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-imx:90 + image: ghcr.io/project-chip/chip-build-imx:93 steps: - name: Checkout diff --git a/.github/workflows/examples-linux-standalone.yaml b/.github/workflows/examples-linux-standalone.yaml index 8c483cacd45651..b4ed1cd92d2d1d 100644 --- a/.github/workflows/examples-linux-standalone.yaml +++ b/.github/workflows/examples-linux-standalone.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-linux-tv-casting-app.yaml b/.github/workflows/examples-linux-tv-casting-app.yaml index 14bfb6fb91b17c..4bc173f7cc9e64 100644 --- a/.github/workflows/examples-linux-tv-casting-app.yaml +++ b/.github/workflows/examples-linux-tv-casting-app.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 steps: - name: Checkout diff --git a/.github/workflows/examples-mw320.yaml b/.github/workflows/examples-mw320.yaml index 077bdbbfb7f2b6..5b2d082ff5e6f7 100644 --- a/.github/workflows/examples-mw320.yaml +++ b/.github/workflows/examples-mw320.yaml @@ -40,7 +40,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-nrfconnect.yaml b/.github/workflows/examples-nrfconnect.yaml index 0db5e82e81d8e4..0aff592c543da4 100644 --- a/.github/workflows/examples-nrfconnect.yaml +++ b/.github/workflows/examples-nrfconnect.yaml @@ -40,7 +40,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nrf-platform:90 + image: ghcr.io/project-chip/chip-build-nrf-platform:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-nuttx.yaml b/.github/workflows/examples-nuttx.yaml index cccfa44557a4ba..63088ce8f78f53 100644 --- a/.github/workflows/examples-nuttx.yaml +++ b/.github/workflows/examples-nuttx.yaml @@ -38,7 +38,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nuttx:90 + image: ghcr.io/project-chip/chip-build-nuttx:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-nxp.yaml b/.github/workflows/examples-nxp.yaml index aa782544d2ae1d..267045cca4d99d 100644 --- a/.github/workflows/examples-nxp.yaml +++ b/.github/workflows/examples-nxp.yaml @@ -40,7 +40,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nxp:90 + image: ghcr.io/project-chip/chip-build-nxp:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: @@ -240,7 +240,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nxp-zephyr:90 + image: ghcr.io/project-chip/chip-build-nxp-zephyr:93 steps: - name: Checkout diff --git a/.github/workflows/examples-openiotsdk.yaml b/.github/workflows/examples-openiotsdk.yaml index 2d59643eeb3aac..2727b81b868621 100644 --- a/.github/workflows/examples-openiotsdk.yaml +++ b/.github/workflows/examples-openiotsdk.yaml @@ -36,7 +36,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-openiotsdk:90 + image: ghcr.io/project-chip/chip-build-openiotsdk:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" options: --privileged diff --git a/.github/workflows/examples-qpg.yaml b/.github/workflows/examples-qpg.yaml index 3287b281dc77ef..45e5b6a7436e68 100644 --- a/.github/workflows/examples-qpg.yaml +++ b/.github/workflows/examples-qpg.yaml @@ -40,7 +40,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-stm32.yaml b/.github/workflows/examples-stm32.yaml index d10c91a8e8ca6d..e2ec5288adf19f 100644 --- a/.github/workflows/examples-stm32.yaml +++ b/.github/workflows/examples-stm32.yaml @@ -41,7 +41,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-telink.yaml b/.github/workflows/examples-telink.yaml index 6c8b9bd5217f32..1b6fd20aa72260 100644 --- a/.github/workflows/examples-telink.yaml +++ b/.github/workflows/examples-telink.yaml @@ -39,7 +39,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-telink:90 + image: ghcr.io/project-chip/chip-build-telink:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" @@ -58,7 +58,7 @@ jobs: gh-context: ${{ toJson(github) }} # - name: Update Zephyr to specific revision (for developers purpose) - # run: scripts/run_in_build_env.sh "python3 scripts/tools/telink/update_zephyr.py f762f1a1027284e63e338e6d83deeade62f355b0" + # run: scripts/run_in_build_env.sh "python3 scripts/tools/telink/update_zephyr.py 8b29ee6b118ebe6eeec3224dbe343474e11403d8" - name: Build example Telink (B92 retention) Air Quality Sensor App # Run test for master and s07641069 PRs @@ -167,6 +167,19 @@ jobs: - name: clean out build output (keep tools) run: rm -rf ./out/telink* + - name: Build example Telink (tl321x) Lighting App with OTA (LZMA), Shell, Factory Data + # Run test for master and all PRs + run: | + ./scripts/run_in_build_env.sh \ + "./scripts/build/build_examples.py --target 'telink-tl3218x-light-ota-compress-lzma-shell-factory-data' build" + .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ + telink tl3218x light-app-ota-compress-lzma-shell-factory-data \ + out/telink-tl3218x-light-ota-compress-lzma-shell-factory-data/zephyr/zephyr.elf \ + /tmp/bloat_reports/ + + - name: clean out build output (keep tools) + run: rm -rf ./out/telink* + - name: Build example Telink (B92) Light Switch App with OTA (LZMA), Shell, Factory Data # Run test for master and all PRs run: | diff --git a/.github/workflows/examples-tizen.yaml b/.github/workflows/examples-tizen.yaml index f465f3999f0f26..56a018d533bc0d 100644 --- a/.github/workflows/examples-tizen.yaml +++ b/.github/workflows/examples-tizen.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-tizen:90 + image: ghcr.io/project-chip/chip-build-tizen:93 options: --user root volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/full-android.yaml b/.github/workflows/full-android.yaml index 6acc150c03a111..4beb8d101e24cd 100644 --- a/.github/workflows/full-android.yaml +++ b/.github/workflows/full-android.yaml @@ -39,7 +39,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-android:90 + image: ghcr.io/project-chip/chip-build-android:93 volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/fuzzing-build.yaml b/.github/workflows/fuzzing-build.yaml index f36b370448fa66..2c8fa9d7f3d4c5 100644 --- a/.github/workflows/fuzzing-build.yaml +++ b/.github/workflows/fuzzing-build.yaml @@ -33,7 +33,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/java-tests.yaml b/.github/workflows/java-tests.yaml index f416be3a4d2998..504cb865a9cc0b 100644 --- a/.github/workflows/java-tests.yaml +++ b/.github/workflows/java-tests.yaml @@ -43,7 +43,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-java:90 + image: ghcr.io/project-chip/chip-build-java:93 options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=0 net.ipv6.conf.all.forwarding=0" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 590a2595ee6f96..731d047f288e6e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -36,7 +36,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 steps: - name: Checkout diff --git a/.github/workflows/minimal-build.yaml b/.github/workflows/minimal-build.yaml index da55158cc7c57f..f933cd69df5531 100644 --- a/.github/workflows/minimal-build.yaml +++ b/.github/workflows/minimal-build.yaml @@ -34,7 +34,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-minimal:90 + image: ghcr.io/project-chip/chip-build-minimal:93 steps: - name: Checkout @@ -56,7 +56,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-minimal:90 + image: ghcr.io/project-chip/chip-build-minimal:93 steps: - name: Checkout diff --git a/.github/workflows/qemu.yaml b/.github/workflows/qemu.yaml index 07b31eec0ddb11..2a2d52f23a8c6c 100644 --- a/.github/workflows/qemu.yaml +++ b/.github/workflows/qemu.yaml @@ -41,7 +41,7 @@ jobs: if: github.actor != 'restyled-io[bot]' && github.repository_owner == 'espressif' container: - image: ghcr.io/project-chip/chip-build-esp32-qemu:90 + image: ghcr.io/project-chip/chip-build-esp32-qemu:93 volumes: - "/tmp/log_output:/tmp/test_logs" @@ -79,7 +79,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-tizen-qemu:90 + image: ghcr.io/project-chip/chip-build-tizen-qemu:93 options: --user root volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/release_artifacts.yaml b/.github/workflows/release_artifacts.yaml index 14b2c327452194..161d123d9ec495 100644 --- a/.github/workflows/release_artifacts.yaml +++ b/.github/workflows/release_artifacts.yaml @@ -32,7 +32,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-esp32:90 + image: ghcr.io/project-chip/chip-build-esp32:93 steps: - name: Checkout @@ -64,7 +64,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-efr32:90 + image: ghcr.io/project-chip/chip-build-efr32:93 steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/smoketest-android.yaml b/.github/workflows/smoketest-android.yaml index 38a614e71246f5..114c072cbe30cd 100644 --- a/.github/workflows/smoketest-android.yaml +++ b/.github/workflows/smoketest-android.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-android:90 + image: ghcr.io/project-chip/chip-build-android:93 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 9a31e56ca8ef54..ceee20818defd8 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -50,7 +50,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" @@ -457,7 +457,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=0 net.ipv6.conf.all.forwarding=0" diff --git a/.github/workflows/unit_integration_test.yaml b/.github/workflows/unit_integration_test.yaml index b2fc345bda1a9d..449152bf21679c 100644 --- a/.github/workflows/unit_integration_test.yaml +++ b/.github/workflows/unit_integration_test.yaml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/zap_regeneration.yaml b/.github/workflows/zap_regeneration.yaml index 0d6d9b6db70ca8..0cba8cb97c2d17 100644 --- a/.github/workflows/zap_regeneration.yaml +++ b/.github/workflows/zap_regeneration.yaml @@ -30,7 +30,7 @@ jobs: runs-on: ubuntu-20.04 container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 defaults: run: shell: sh diff --git a/.github/workflows/zap_templates.yaml b/.github/workflows/zap_templates.yaml index c4edd57421ba6f..6900886aed06bb 100644 --- a/.github/workflows/zap_templates.yaml +++ b/.github/workflows/zap_templates.yaml @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-20.04 container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:93 defaults: run: shell: sh diff --git a/config/ameba/chip.cmake b/config/ameba/chip.cmake index 47444055f66733..9cd2ab5511b3fb 100644 --- a/config/ameba/chip.cmake +++ b/config/ameba/chip.cmake @@ -32,6 +32,7 @@ list( -DMBEDTLS_CONFIG_FILE= -D_POSIX_REALTIME_SIGNALS -DCHIP_SHELL_MAX_TOKENS=11 + -DCONFIG_ENABLE_AMEBA_SNTP=1 ) list( diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt index 40f5c0cea2936d..0047cfecc70a1c 100644 --- a/config/esp32/components/chip/CMakeLists.txt +++ b/config/esp32/components/chip/CMakeLists.txt @@ -389,7 +389,6 @@ externalproject_add( BUILD_COMMAND ninja "esp32" INSTALL_COMMAND "" BUILD_BYPRODUCTS ${chip_libraries} - WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} DEPENDS args_gn BUILD_ALWAYS 1 ) @@ -431,7 +430,13 @@ if(CONFIG_BT_ENABLED) if((target_name STREQUAL "esp32h2") OR (target_name STREQUAL "esp32c2") OR (target_name STREQUAL "esp32c6")) idf_component_get_property(bt_dir bt COMPONENT_DIR) list(APPEND chip_libraries $) - list(APPEND chip_libraries "${bt_dir}/controller/lib_${target_name}/${target_name}-bt-lib/libble_app.a") + if (EXISTS ${bt_dir}/controller/lib_${target_name}/${target_name}-bt-lib/libble_app.a) + list(APPEND chip_libraries "${bt_dir}/controller/lib_${target_name}/${target_name}-bt-lib/libble_app.a") + elseif(EXISTS ${bt_dir}/controller/lib_${target_name}/${target_name}-bt-lib/${target_name}/libble_app.a) + list(APPEND chip_libraries "${bt_dir}/controller/lib_${target_name}/${target_name}-bt-lib/${target_name}/libble_app.a") + else() + message(WARNING "There is no libble_app.a in the given path") + endif() elseif(target_name STREQUAL "esp32p4") list(APPEND chip_libraries $) else() diff --git a/config/telink/chip-module/CMakeLists.txt b/config/telink/chip-module/CMakeLists.txt index ade2bd310f8a02..0f925cdeffc904 100644 --- a/config/telink/chip-module/CMakeLists.txt +++ b/config/telink/chip-module/CMakeLists.txt @@ -174,7 +174,7 @@ add_dependencies(process_binaries ${ZEPHYR_FINAL_EXECUTABLE}) # Define 'build_mcuboot' target for building the MCUBoot bootloader # ============================================================================== -if (CONFIG_BOOTLOADER_MCUBOOT AND CONFIG_SOC_SERIES_RISCV_TELINK_B9X) +if (CONFIG_BOOTLOADER_MCUBOOT AND (CONFIG_SOC_SERIES_RISCV_TELINK_B9X OR CONFIG_SOC_SERIES_RISCV_TELINK_TLX)) add_custom_target(build_mcuboot ALL COMMAND west build -b ${BASE_BOARD} -d build_mcuboot ${ZEPHYR_BASE}/../bootloader/mcuboot/boot/zephyr diff --git a/config/telink/chip-module/Kconfig b/config/telink/chip-module/Kconfig index b06c7c855922d8..2937b2b0c66094 100644 --- a/config/telink/chip-module/Kconfig +++ b/config/telink/chip-module/Kconfig @@ -246,7 +246,8 @@ config CHIP_ENABLE_POWER_ON_FACTORY_RESET config CHIP_TASK_STACK_SIZE int - default 4864 if PM + default 6192 if SOC_RISCV_TELINK_TL321X + default 5352 if PM default 8192 config CHIP_USE_MARS_SENSOR diff --git a/config/telink/chip-module/Kconfig.defaults b/config/telink/chip-module/Kconfig.defaults index bb722e8a3ab8bc..3503aae4000f06 100644 --- a/config/telink/chip-module/Kconfig.defaults +++ b/config/telink/chip-module/Kconfig.defaults @@ -34,6 +34,7 @@ choice LOG_MODE endchoice choice MATTER_LOG_LEVEL_CHOICE + default MATTER_LOG_LEVEL_WRN if SOC_RISCV_TELINK_TL321X default MATTER_LOG_LEVEL_DBG endchoice @@ -61,17 +62,19 @@ config POSIX_MAX_FDS # Application stack size config MAIN_STACK_SIZE - default 3240 if PM + default 3240 if PM || SOC_RISCV_TELINK_TL321X default 4096 config INIT_STACKS default y config IDLE_STACK_SIZE - default 512 if PM + default 512 if PM || SOC_RISCV_TELINK_TL321X + config ISR_STACK_SIZE default 576 if PM + default 528 if SOC_RISCV_TELINK_TL321X config SYSTEM_WORKQUEUE_STACK_SIZE default 616 if PM @@ -79,7 +82,8 @@ config SYSTEM_WORKQUEUE_STACK_SIZE config HEAP_MEM_POOL_SIZE default 256 -config COMMON_LIBC_MALLOC_ARENA_SIZE +config COMMON_LIBC_MALLOC_ARENA_SIZE + default 20716 if SOC_RISCV_TELINK_TL321X || SOC_SERIES_RISCV_TELINK_B9X_RETENTION default 12288 config NET_IPV6_MLD @@ -92,19 +96,19 @@ config NET_IF_MCAST_IPV6_ADDR_COUNT # Network buffers config NET_PKT_RX_COUNT - default 4 if PM + default 4 if PM || SOC_RISCV_TELINK_TL321X default 8 config NET_PKT_TX_COUNT - default 4 if PM + default 4 if PM || SOC_RISCV_TELINK_TL321X default 8 config NET_BUF_RX_COUNT - default 16 if PM + default 12 if PM || SOC_RISCV_TELINK_TL321X default 32 config NET_BUF_TX_COUNT - default 16 if PM + default 12 if PM || SOC_RISCV_TELINK_TL321X default 32 config GPIO @@ -133,60 +137,91 @@ config BT_MAX_CONN default 1 config BT_L2CAP_TX_MTU + default 103 if SOC_RISCV_TELINK_TL321X default 247 config BT_BUF_ACL_RX_SIZE + default 107 if SOC_RISCV_TELINK_TL321X default 251 config BT_BUF_ACL_TX_SIZE + default 107 if SOC_RISCV_TELINK_TL321X default 251 + +#ifdef CONFIG_SOC_RISCV_TELINK_TL321X + +config BT_BUF_EVT_RX_COUNT + default 4 + +config BT_BUF_ACL_RX_COUNT + default 4 + +config BT_GATT_CACHING + bool + default n + + +#endif + config BT_RX_STACK_SIZE default 1352 if BT_B9X + default 1010 if BT_TLX default 2048 if BT_W91 config BT_HCI_TX_STACK_SIZE default 640 if BT_B9X + default 640 if BT_TLX default 2048 if BT_W91 config BT_DEVICE_NAME_GATT_WRITABLE bool default n -config B9X_BLE_CTRL_THREAD_STACK_SIZE +if SOC_SERIES_RISCV_TELINK_B9X || SOC_SERIES_RISCV_TELINK_TLX + +config TL_BLE_CTRL_THREAD_STACK_SIZE default 648 -config B9X_BLE_CTRL_MASTER_MAX_NUM +config TL_BLE_CTRL_MASTER_MAX_NUM default 0 -config B9X_BLE_CTRL_SLAVE_MAX_NUM +config TL_BLE_CTRL_SLAVE_MAX_NUM default 1 -config B9X_BLE_CTRL_RF_POWER +config TL_BLE_CTRL_RF_POWER default 3 if PM + default 8 if BT_TLX default 9 -choice B9X_BLE_CTRL_MAC_TYPE - default B9X_BLE_CTRL_MAC_TYPE_RANDOM_STATIC +choice TL_BLE_CTRL_MAC_TYPE + default TL_BLE_CTRL_MAC_TYPE_RANDOM_STATIC endchoice -endif +endif # SOC_SERIES_RISCV_TELINK_B9X || SOC_SERIES_RISCV_TELINK_TLX + + +endif # BT # Board retention config +# Cut down the ram cost by matter's change,it can keep ramcode (driver). +# No need load the ramcode every time in thread mode (retention mode). +# If the ram is not enough , can change it back , initial setting is n. if BOARD_TLSR9528A_RETENTION || BOARD_TLSR9258A_RETENTION || BOARD_TLSR9518ADK80D_RETENTION config SOC_SERIES_RISCV_TELINK_B9X_NON_RETENTION_RAM_CODE - default y if PM + default n if PM config TELINK_B9X_MATTER_RETENTION_LAYOUT default y if PM config PWM default n + endif # Board non-retention config if BOARD_TLSR9118BDK40D || BOARD_TLSR9118BDK40D_V1 || \ - BOARD_TLSR9528A || BOARD_TLSR9258A || BOARD_TLSR9518ADK80D + BOARD_TLSR9528A || BOARD_TLSR9258A || BOARD_TLSR9518ADK80D || BOARD_TL3218X config PWM default y endif @@ -222,6 +257,7 @@ config NVS_LOOKUP_CACHE default y config NVS_LOOKUP_CACHE_SIZE + default 400 if SOC_RISCV_TELINK_TL321X default 2048 if !PM # Set multiplicator of Name Value Storage (NVS) as 1 to reach NVS sector size 4KB @@ -261,7 +297,7 @@ config CHIP_ENABLE_ICD_SUPPORT default y if CHIP_THREAD_DEVICE_ROLE_SLEEPY_END_DEVICE config OPENTHREAD_THREAD_STACK_SIZE - default 2400 if PM + default 2400 if PM || SOC_RISCV_TELINK_TL321X config OPENTHREAD_RADIO_WORKQUEUE_STACK_SIZE default 432 if PM @@ -284,10 +320,10 @@ config OPENTHREAD_IP6_MAX_EXT_MCAST_ADDRS endif # NET_L2_OPENTHREAD config NET_TX_STACK_SIZE - default 554 if PM + default 554 if PM || SOC_RISCV_TELINK_TL321X config NET_RX_STACK_SIZE - default 554 if PM + default 554 if PM || SOC_RISCV_TELINK_TL321X # Disable certain parts of Zephyr IPv6 stack config NET_IPV6_NBR_CACHE diff --git a/docs/platforms/stm32/index.md b/docs/platforms/stm32/index.md index 7b0d56ce3e6004..dbe427e82ebe81 100644 --- a/docs/platforms/stm32/index.md +++ b/docs/platforms/stm32/index.md @@ -1,4 +1,4 @@ -# ESP32 +# STM32 ```{toctree} :glob: diff --git a/docs/style/CODING_STYLE_GUIDE.md b/docs/style/CODING_STYLE_GUIDE.md new file mode 100644 index 00000000000000..bba6ef4ffadbf5 --- /dev/null +++ b/docs/style/CODING_STYLE_GUIDE.md @@ -0,0 +1,172 @@ +# Coding Style Guide + +_Revision 6_ _2024-10-28_ + +This guide provides a small set of code guidelines used in the SDK. This guide +reflects the currently accepted style practices for the SDK and is subject to +change. + +The SDK was seeded from multiple different projects and contains contributions +from many different companies and the SDK code therefore uses several different +coding styles throughout the code base. Stylistically, code should attempt to +conform to the dominant style of the code being modified, while also adhering to +the guidelines below. + +## Language standard + +Code in the SDK conforms to the following standards. Changes to the C++ standard +happen relatively infrequently. Changes to the Python version are more frequent. + +| Language | Version | +| -------- | ------- | +| C++ | C++17 | +| Python | 3.10 | + +Product-specific software may elect to use later standards in their own work. + +## Coding Guidelines + +### Common + +#### When in Rome + +The most important convention and practice in the Matter SDK repo is "_When in +Rome..._", per the quote below. + +[quote, St. Ambrose] + +--- + +If you should be in Rome, live in the Roman manner; if you should be elsewhere, +live as they do there. + +--- + +Your extensions or fixes to existing code should match the prevailing style of +the original code. + +If you find the conventions so foreign or otherwise confusing, it may be best to +let whoever owns the file make the necessary changes or seek the counsel of +others in the group to find out what the right thing to do is. Never just start +changing code wholesale for personal reasons without consulting others first. + +#### Commenting Out or Disabling Code + +Unused code shall not be disabled by commenting it out with C- or C++-style +comments or with preprocessor `#if 0 ... #endif` semantics. Unused code should +be removed. + +#### Auto-formatters + +We use the following auto-formatters on code: + +| Language | Formatter | Style File | +| ----------- | ------------------ | ------------------------------------------------------------------------------------------ | +| C++ | clang-format | [.clang-format](https://github.com/project-chip/connectedhomeip/blob/master/.clang-format) | +| Objective-C | clang-format | [.clang-format](https://github.com/project-chip/connectedhomeip/blob/master/.clang-format) | +| java | google-java-format | N/A | +| Python | pep8, isort, ruff | [.restyled.yaml][restyle_link] (command line), [isort][isort_link], [ruff][ruff_link] | +| YAML | prettier | None | +| JSON | prettier | None | +| markdown | prettier | None | + +[restyle_link]: + https://github.com/project-chip/connectedhomeip/blob/master/.restyled.yaml +[isort_link]: + https://github.com/project-chip/connectedhomeip/blob/master/.isort.cfg +[ruff_link]: + https://github.com/project-chip/connectedhomeip/blob/master/ruff.toml + +All pull requests run formatting checks using these tools before merge is +allowed. Generated code is not run through restyle. + +### C++ + +#### Use C++ _cstdint_ for Plain Old Data Types + +Standard, scalar data types defined in _cstdint_ should be used for basic signed +and unsigned integer types, especially when size and serialization to +non-volatile storage or across a network is concerned. + +Examples of these are: `uint8_t`, `int8_t`, etc. + +#### Avoid top-level `using namespace` Statements in Headers + +By doing this, you are effectively forcing every other module that includes the +header to also be using the namespace. This causes namespace pollution and +generally defeats the purposes of namespaces. Fully-qualified symbols or +namespace blocks should be used instead. + +#### Classes / objects not exposed in a header should be in an anonymous namespace + +If a cpp class defines a class or instantiates a static object, it should be +enclosed in an anonymous namespace. + +``` +namespace { + // CPP internal defines go here +} // namespace +``` + +#### Singleton use + +The decision to use a singleton class should be considered with care. Do not +default to using a singleton for ease of writing code. + +If the class truly should be a singleton (ex. if it is controlling access to a +hardware resource) + +- The standard function name for accessing an SDK singleton is GetInstance(). +- Singleton classes should delete copy and move constructors + +#### Avoid Heap-based Resource Allocation and auto-resizing std containers + +Heap-based resource allocation should be avoided in the core SDK for common code +that may run on constrained embedded devices. This includes any container +element in std that automatically re-sizes itself at runtime (ex. vector, string +etc.) as these re-size operations are often large and can lead to memory +exhaustion and fragmentation on embedded systems. + +Heap-based allocation is allowed for controller code and is at the discretion of +platform vendors for platform-specific code. + +##### Alternatives + +In either case, recommended resource allocation alternatives are: + +- In-place allocation and initialization +- Pool-based allocators +- Platform-defined and -assigned allocators + +[CHIPMem.h](https://github.com/project-chip/connectedhomeip/blob/master/src/lib/support/CHIPMem.h) +provides support for platform defined allocators. + +[Pool.h](https://github.com/project-chip/connectedhomeip/blob/master/src/lib/support/Pool.h) +is the Matter SDK pool allocator implementation. + +#### Prefer CopySpanToMutableSpan over memcpy when using spans + +See +[Span.h](https://github.com/project-chip/connectedhomeip/blob/master/src/lib/support/Span.h) + +#### Prefer std::optional to CHIP implementation in newer code + +The Matter SDK Optional.h was implemented when the Matter SDK was C++14, but +newer code can use std::optional, which offers some benefits over the Matter SDK +implementation (ex. std::optional is trivially destructible if the underlying +type is also trivially destructible) + +### Python + +#### Type hints + +Use type hints on function definitions for public APIs. + +#### Docstrings + +Docstrings should be included for all public APIs. + +#### mypy + +The current python code does not yet pass mypy checks, but we are working +towards this goal. The more compliant new code is to mypy, the better. diff --git a/docs/style/coding/CODING_STYLE_GUIDE-figure1.png b/docs/style/coding/CODING_STYLE_GUIDE-figure1.png deleted file mode 100644 index d8603de93c6067..00000000000000 Binary files a/docs/style/coding/CODING_STYLE_GUIDE-figure1.png and /dev/null differ diff --git a/docs/style/coding/CODING_STYLE_GUIDE.adoc b/docs/style/coding/CODING_STYLE_GUIDE.adoc deleted file mode 100644 index d6436523d657a6..00000000000000 --- a/docs/style/coding/CODING_STYLE_GUIDE.adoc +++ /dev/null @@ -1,721 +0,0 @@ -[.text-center] -= Project Connected Home over IP Software -:listing-caption: *Listing* -:toc: macro -:toclevels: 7 -:sectnumlevels: 7 -:sectanchors: -:sectlinks: - -:plusplus: ++ - -:sectnums!: - -== Best Practices, Coding Conventions, and Style - -[.text-center] -_Revision 5_ + -_2020-09-22_ - -[.text-center] -*Status:* [red]*Approved* / [red]*Active* - -toc::[] - -== Typographic and Syntactic Conventions - -The following syntactic conventions are used throughout this document: - -_shall_:: - -is used to indicate a mandatory rule or guideline that must be adhered -to without exception to claim compliance with this specification. - -_should_:: - -is used to indicate a rule or guideline that serves as a strong -preference to suggested practice and is to be followed in the absence of -a compelling reason to do otherwise. - -_may_:: - -is used to indicate a rule or guideline that serves as a reference to -suggested practice. - -== Introduction - -There are likely as many unique combinations of software engineering and -development standards, conventions, and practices as there organizations -that do such work. This document pulls together those that Project -Connected Home over IP believes best for our organization, its efforts, -and products that consume those efforts, with a particular emphasis on -embedded systems with C or C{plusplus} language development and runtime -environments. - -This document and requirements should be considered canonical for all -Project Connected Home over IP shared infrastructure software, including -both RTOS-based and non-RTOS-based projects on both tightly- and -loosely-constrained system platforms. - -The document is broadly categorized at the highest level into: - -* Best Practices and Conventions -* Format and Style - -And, within conventions, further sub-categorized into those that apply -to: - -* Tightly-constrained -* Loosely-constrained - -system platforms. Applicability to tightly-constrained systems also -generally applies to shared infrastructure software that is used on both -tightly- and loosely-constrained systems. - -link:#id.jzphr1iiku89[Figure 1 below] attempts to illustrate both -qualitative and quantitative applicability of these guidelines to -Project Connected Home over IP software. - -Generally, product-specific applications have the greatest flexibility -and latitude in applying these guidelines to their software. Whereas, -shared infrastructure bears the least flexibility and bears the greatest -adherence to these guidelines. - -image:CODING_STYLE_GUIDE-figure1.png[Figure 1. Graphical summary of the -qualitative and quantitative applicability to Project CHIP software.] - -[[id.jzphr1iiku89]] - -[.text-center] -*Figure 1.* Graphical summary of the qualitative and quantitative -applicability to Project CHIP software. - -:sectnums: - -== Standards - -Project CHIP embedded software development adopts the minimum C and C{plusplus} -standards listed in Table 2.1 below. - -[[t.4d8bfeef046f29261fc72f1a903d6d10a909957a]][[t.2]] - -[cols=3,options="header"] -|=== -|Language |Minimum Standard |Aliases - -|C|ISO9899:1999|ISO C99, C99 -|C{plusplus}|ISO14882:2014|ISO C{plusplus}14, C{plusplus}14 -|=== -[.text-center] -*Table 2.1.* C and C{plusplus} language minimum standards adopted by Project CHIP -software. - -Product-specific software may elect to use later standards to the extent -their software is not broadly shared inside or outside Project CHIP. - -=== C - -Project CHIP embedded software development uses and enforces the -ISO9899:1999 (aka ISO C99, C99) C language standard as the minimum. - -Wherever possible, particularly in non-product-specific, -shared-infrastructure software, toolchain-specific (e.g GCC/GNU) -extensions or the use of later standards shall be avoided or shall be -leveraged through toolchain-compatibility preprocessor macros. - -==== Motivation and Rationale - -At the time of this writing, the C99 standard has been out for over 20 -years. Project CHIP and both the new and contributed source code that -comprise it have only existed for the last seven to eight of those -20-plus years. - -This is beyond more than adequate time for this standard to be pervasive -throughout any toolchain vendor’s C compiler and saves team members from -worrying about ISO9899:1990 (aka ISO C90, C90) portability issues that -have long-since been solved by C99. - -=== C{plusplus} - -Project CHIP embedded software development uses the ISO14882:2014 (aka -ISO C{plusplus}14) language standard as a baseline for source code -compatibility. Conformance with other standards, for example, ISO14882:1998 -(aka ISO C{plusplus}98), may be additionally required in cases where wider -portability is necessary, but in all cases, ISO C{plusplus}14 is the baseline -requirement. - -Wherever possible, particularly in non-product-specific, -shared-infrastructure software, toolchain-specific (e.g GCC/GNU) -extensions or the use of later standards shall be avoided or shall be -leveraged through toolchain-compatibility preprocessor macros. - -==== Motivation and Rationale - -CHIP strives to use the latest C++ functionality as long as existing compilers -support such standards. - -C{plusplus}14 is considered pervasive enough to be used. As compilers start -supporting standards such as C{plusplus}17, C{plusplus}20 and beyond, -CHIP may follow suit. - -== Conventions and Best Practices - -=== Common - -The following sections summarize those best practices that are -independent of particular nuances of either the C or C{plusplus} languages. - -==== When in Rome - -The most important convention and practice in the Project CHIP embedded -software is "_When in Rome..._", per the quote below. - -[quote, St. Ambrose] -____ -If you should be in Rome, live in the Roman manner; if you should be -elsewhere, live as they do there. -____ - -===== Motivation and Rationale - -At this stage in the work group’s and the team’s life cycle, it is rare -the project or subsystem that is entirely new and built from scratch. -More often than not, development will involve extending, enhancing, and -fixing existing code in existing projects. - -When in this situation, it is mandatory you observe how things are done -in this context and do the best that you can to follow the prevailing -conventions present. Not doing so can lead to readability and -maintenance problems down the line and will likely earn you the -disapprobation of the code’s _owner_ or other team members. - -Your extensions or fixes to existing code should be *indistinguishable*, -stylistically, from the original code such that the only way to -ascertain ownership and responsibility is to use the source code control -system’s change attribution (aka _blame_) feature. - -If you find the conventions so foreign or otherwise confusing, it may be -best to let whoever owns the file make the necessary changes or seek the -counsel of others in the group to find out what the right thing to do -is. Never just start changing code wholesale for personal reasons -without consulting others first. - -==== Language-independent - -===== Commenting Out or Disabling Code - -Unused code shall not be disabled by commenting it out with C- or -C{plusplus}-style comments or with preprocessor `#if 0 ... #endif` semantics. - -====== Motivation and Rationale - -Code should either be actively maintained and "in" the source base for a -purpose or removed entirely. Code that is disabled in this way is -generally sloppy and does not convey a sense of certainty and direction -in the code. - -Anyone who is interested in the history of a particular source code file -should use the source code control system to browse it. - -Code that is debug- or test-only should be moved to a conditionally -compiled test source file or conditionalized with an appropriate -`WITH_DEBUG`, `WANT_DEBUG`, `WITH_TESTS`, `WANT_TESTS`, or some similar such -preprocessor mnemonic that can be asserted from the build system. - -===== Use C _stdint.h_ or C{plusplus} _cstdint_ for Plain Old Data Types - -Standard, scalar data types defined in _stdint.h_ \(C) or _cstdint_ (C{plusplus}) -should be used for basic signed and unsigned integer types, especially -when size and serialization to non-volatile storage or across a network -is concerned. - -Examples of these are: `uint8_t`, `int8_t`, etc. - -====== Motivation and Rationale - -These types have been effectively standardized since C99 and should be -available on every platform and provide more neutral portability than -OS-specific types such as `u8`, `UInt8`, etc. Moreover, because these are -pervasive, you do not need to spend any time and energy as a developer -and engineer creating more such types on your own—the compiler vendors -have already done the hard work for you. - -Additionally, using traditional scalar types such as `char`, `int`, `short`, or -`long` have portability issues where data width is concerned because these -types are either signed- or sized-differently on different processor -architectures and and ABIs for those architectures. For example, a char is signed -on some architectures and unsigned on others and a long is 32-bits on some -architectures and 64-bits on others. - -==== Language-dependent - -===== C{plusplus} - -====== Avoid `using namespace` Statements in Headers - -By doing this, you are effectively forcing every other module that -includes the header to also be using the namespace. This causes -namespace pollution and generally defeats the purposes of namespaces. -Fully-qualified symbols should be used instead. - -=== Tightly-constrained Systems and Shared Infrastructure - -Applicability to tightly-constrained systems also generally applies to -shared infrastructure software that is used on both tightly- and -loosely-constrained systems. - -==== Avoid Heap-based Resource Allocation - -Heap-based resource allocation should be avoided. - -===== Motivation and Rationale - -As emphasized throughout this document, the software produced by Project -CHIP is consumed both inside and outside Project CHIP, across a variety -of platforms. The capabilities of these platforms are broad, spanning -soft real-time, deeply-embedded systems based on RTOSes that -may cover life safety and/or physical security applications to richer, -softly-embedded systems based on non-RTOS platforms such as Darwin or -Linux. While the latter are apt to have fully-functional heaps, the -former explicitly may not. - -Consequently, when planning new or extending existing Project CHIP code, -consider the platforms to which the code is targeted. If the platforms -include those deeply-embedded platforms absent functioning heaps, then -heap-based resource allocation is absolutely forbidden. If not, -consideration should be made to the cost / benefit trade-offs of -heap-based allocation and, if possible, it should be avoided using one -of the recommended techniques below. - -===== Alternatives - -In either case, recommended resource allocation alternatives are: - -* In Place Allocation and Initialization -* Pool-based Allocators -* Platform-defined and -assigned Allocators - -The interfaces in https://github.com/project-chip/connectedhomeip/blob/master/src/lib/support/CHIPMem.h[_src/lib/support/CHIPMem.h_] provide support for -the latter two alternatives. - -====== Use In Place Allocation and Initialization - -Regardless of whether the source code and runtime are C or C{plusplus}, the -first step is creating storage for the object being allocated and -initialized. For simple -https://en.wikipedia.org/wiki/Passive_data_structure[plain-old-data -(POD)] data structures, this can be done by just allocating the -structure at an appropriate scope. Alternatively, _raw_ storage can be -allocated and then cast. However, great care must be taken with the -latter approach to ensure that natural machine alignments and language -strict-aliasing rules are observed. With the simple data structure -declaration, the compiler does this on your behalf. With the raw -approach, you must do this. - -Once the storage has been allocated, then use symmetric initializers and -deinitializers such as those, for example, for `pthread_attr_t`. An -example is shown in the listing below. - -[source,C,caption='',title='{listing-caption} *{counter:refnum}*. Using in place allocation and initialization in C or C{plusplus}.'] ----- -#include -#include - -... - -// Preprocessor Definitions - -// Allocate the structure using "raw" storage. - -#if defined(__cplusplus) && (__cplusplus >= 201103L) -#include - -#define chipDEFINE_ALIGNED_VAR(name, size, align_type) \ - typename std::aligned_storage::type name; - -#else -#define chipDEFINE_ALIGNED_VAR(name, size, align_type) \ - align_type name[(((size) + (sizeof (align_type) - 1)) / sizeof (align_type))] - -#endif // defined(__cplusplus) && (__cplusplus >= 201103L) - -// Forward Declarations - -extern void * foobar_entry(void *aArgument); - -// Global Variables - -#if USE_STRUCT_STORAGE -// Allocate the structure directly. -static pthread_attr_t sThreadAttributes; - -#elif USE_RAW_STORAGE -static chipDEFINE_ALIGNED_VAR(sThreadAttributes, sizeof (pthread_attr_t), uint64_t); - -#endif // USE_STRUCT_STORAGE - -int foobar() -{ - int retval; - int status; - pthread_t thread; - pthread_attr_t * attrs = (pthread_attr_t *)&sThreadAttributes; - - // Now "construct" or initialize the storage. - retval = pthread_attr_init(attrs); - - if (retval == 0) - { - retval = pthread_create(&thread, attrs, foobar_entry, NULL); - - if (retval == 0) - { - status = pthread_join(thread, NULL); - - if (status != 0) - { - retval = status; - } - - status = pthread_attr_destroy(attrs); - - if (status != 0) - { - retval = status; - } - } - } - - return (retval); -} ----- - -For non-scalar types and objects such as C{plusplus} classes, this gets slightly -trickier since C{plusplus} constructors and destructors must be accounted for -and invoked. Fortunately, C{plusplus} has placement new which handles this. -The listing below modifies the listing above using C{plusplus} placement new -to ensure the class is properly constructed before initialization and -destructed after deinitialization. - -[source,C++,caption='',title='{listing-caption} *{counter:refnum}*. Using C{plusplus} placement new for in place allocation and initialization.'] ----- -#include - -#include -#include - -... - -// Preprocessor Definitions - -// Allocate the structure using "raw" storage. - -#if defined(__cplusplus) && (__cplusplus >= 201103L) -#include - -#define chipDEFINE_ALIGNED_VAR(name, size, align_type) \ - typename std::aligned_storage::type name; - -#else -#define chipDEFINE_ALIGNED_VAR(name, size, align_type) \ - align_type name[(((size) + (sizeof (align_type) - 1)) / sizeof (align_type))] - -#endif // defined(__cplusplus) && (__cplusplus >= 201103L) - -// Type Declarations - -class ThreadAttributes -{ -public: - ThreadAttributes() {}; - ~ThreadAttributes() {}; - - operator pthread_attr_t *() { return &mAttributes; } - -private: - pthread_attr_t mAttributes; -}; - -// Forward Declarations - -extern void * foobar_entry(void *aArgument); - -// Global Variables - -static chipDEFINE_ALIGNED_VAR(sThreadAttributes, sizeof (ThreadAttributes), uint64_t); - -int foobar() -{ - int retval = -1; - int status; - pthread_t thread; - ThreadAttributes * ta; - pthread_attr_t * attrs; - - ta = new (&sThreadAttributes) ThreadAttributes; - - if (ta != NULL) - { - attrs = static_cast(*ta); - - // Now "construct" or initialize the storage. - retval = pthread_attr_init(attrs); - - if (retval == 0) - { - retval = pthread_create(&thread, attrs, foobar_entry, NULL); - - if (retval == 0) - { - status = pthread_join(thread, NULL); - - if (status != 0) - { - retval = status; - } - - status = pthread_attr_destroy(attrs); - - if (status != 0) - { - retval = status; - } - } - } - - ta->~ThreadAttributes(); - } - - return retval; -} ----- - -====== Use Pool-based Allocators - -In place allocation allows the successful allocation, initialization, -deinitialization, and deallocation of a single object allocated from -preallocated storage. However, if the desire exists for a fixed, -configurable pool of objects where 0 to `n` of such objects can be -allocated at any one time, a pool allocator for that specific object -type must be created. - -As shown in the listing below, a pool allocator for a `Foo` class of -`CHIP_FOO_COUNT` objects is effected, assuming the existence of another -helper class, StaticAllocatorBitmap, which uses a bitmap to track the -storage of objects from a static array of storage. - -[source,C++,caption='',title='{listing-caption} *{counter:refnum}*. Using pool-based allocators.'] ----- - -#include - -// Preprocessor Definitions - -// Allocate the structure using "raw" storage. - -#if defined(__cplusplus) && (__cplusplus >= 201103L) -#include - -#define chipDEFINE_ALIGNED_VAR(name, size, align_type) \ - typename std::aligned_storage::type name; - -#else -#define chipDEFINE_ALIGNED_VAR(name, size, align_type) \ - align_type name[(((size) + (sizeof (align_type) - 1)) / sizeof (align_type))] - -#endif // defined(__cplusplus) && (__cplusplus >= 201103L) - -// Type Definitions - -class Foo -{ -public: - Foo(); - Foo(const Foo &inFoo); - ~Foo(); -}; - -// Global Variables - -static chipDEFINE_ALIGNED_VAR(sFooAllocatorBuffer, sizeof (StaticAllocatorBitmap), uint32_t); -static StaticAllocatorBitmap *sFooAllocator; - -static void CreateFooAllocator(void *inStorage, - const StaticAllocatorBitmap::size_type &inStorageSize, - const StaticAllocatorBitmap::size_type &inElementCount, - StaticAllocatorBitmap::InitializeFunction inInitialize, - StaticAllocatorBitmap::DestroyFunction inDestroy) -{ - sFooAllocator = new (sFooAllocatorBuffer) - StaticAllocatorBitmap(inStorage, - inStorageSize, - inElementCount, - inInitialize, - inDestroy); -} - -static StaticAllocatorBitmap &GetFooAllocator() -{ - return *sFooAllocator; -} - -static void *FooInitialize(AllocatorBase &inAllocator, void *inObject) -{ - memset(inObject, 0, sizeof(Foo)); - - return inObject; -} - -static void FooDestroy(AllocatorBase &inAllocator, void *inObject) -{ - return; -} - -int Init() -{ - static const size_t sFooCount = CHIP_FOO_COUNT; - static chipAllocatorStaticBitmapStorageDefine(sFooStorage, Foo, sFooCount, uint32_t, sizeof (void *)); - int retval = 0; - - CreateFooAllocator(sFooStorage, - sizeof (sFooStorage), - sFooCount, - FooInitialize, - FooDestroy); - - return retval; -} - -Foo * FooAllocate() -{ - Foo *foo; - - foo = static_cast(GetFooAllocator().allocate()); - - return foo; -} - -void FooDeallocate(Foo *inFoo) -{ - GetFooAllocator().deallocate(inFoo); -} ----- - -====== Use Platform-defined and -assigned Allocators - -This is a variation on both in place allocation and pool-based -allocation in that it completely delegates resource allocation to the -system integrator and the platform on which the particular software -subsystem is running. - -The advantage of this approach is that it allows the platform to decide -how resource allocation will be handled and allows the package to scale -independently of platform resource allocation. - -The package may define default implementations for a few types of -platform allocation strategies, such as heap-based allocators and -pool-based allocators. - -There are a range of granularities for achieving this type of -delegation, depending on the desired size of the API surface, as shown -in the listings below. - -[source,C++,caption='',title='{listing-caption} *{counter:refnum}*. Using a common allocator method pattern with unique allocators per object, accessed from a unique singleton access per allocator.'] ----- - -chipPlatformInitFooAllocator(); -chipPlatformInitBarAllocator(); -… -foo = chipPlatformGetFooAllocator().allocate(); -… -chipPlatformGetFooAllocator().deallocate(foo); -… -bar = chipPlatformGetBarAllocator().allocate(); -… -chipPlatformGetBarAllocator().deallocate(bar); ----- - -[source,C++,caption='',title='{listing-caption} *{counter:refnum}*. Using a common allocator method pattern with unique allocators per object, accessed from a common singleton access with type per allocator.'] ----- -chipPlatformInitAllocator(CHIP_FOO_T); -chipPlatformInitAllocator(CHIP_BAR_T); -… -foo = chipPlatformGetAllocator(CHIP_FOO_T).allocate(); -… -chipPlatformGetAllocator(CHIP_FOO_T).deallocate(foo); -… -bar = chipPlatformGetAllocator(CHIP_BAR_T).allocate(); -… -chipPlatformGetAllocator(CHIP_BAR_T).deallocate(bar); ----- - -[source,C,caption='',title='{listing-caption} *{counter:refnum}*. Using unique allocators per object.'] ----- -chipPlatformInitFooAllocator(); -chipPlatformInitBarAllocator(); -… -foo = chipPlatformFooAllocate(); -… -chipPlatformFooDeallocate(foo); -… -bar = chipPlatformBarAllocate(); -… -chipPlatformBarDeallocate(bar); ----- - -[source,C,caption='',title='{listing-caption} *{counter:refnum}*. Using a common allocator pattern with unique allocators per object, accessed from a common interface with type per allocator.'] ----- - -chipPlatformInitAllocator(CHIP_FOO_T); -chipPlatformInitAllocator(CHIP_BAR_T); -… -foo = chipPlatformAllocate(CHIP_FOO_T); -… -chipPlatformDeallocate(CHIP_FOO_T, foo); -… -bar = chipPlatformAllocate(CHIP_BAR_T); -… -chipPlatformBarDeallocate(CHIP_BAR_T, bar); ----- - -:sectnums!: - -== Recommended Reading - -While the following references and reading are not part of the formal -best practices, coding conventions, and style cannon, they are -informative and useful guides for improving the style and quality of the -code you write: - -. Jet Propulsion Laboratory. -http://lars-lab.jpl.nasa.gov/JPL_Coding_Standard_C.pdf[JPL -Institutional Coding Standard for the C Programming Language.] Version -1.0. March 3, 2009. -. Jet Propulsion Laboratory. -http://pixelscommander.com/wp-content/uploads/2014/12/P10.pdf[The -Power of Ten – Rules for Developing Safety Critical Code]. December -2014. -. Meyers, Scott. Effective C{plusplus}: 55 Specific Ways to Improve Your -Programs and Designs. Third Edition. 2005. -. Meyers, Scott. More Effective C{plusplus}: 35 New Ways to Improve Your -Programs and Designs. 1996. -. Meyers. Scott. https://www.artima.com/shop/effective_cpp_in_an_embedded_environment[Effective C{plusplus} in an Embedded Environment]. 2015. -. Motor Industry Software Reliability Association. Guidelines for the -Use of the C Language in Critical Systems. March 2013. -. Motor Industry Software Reliability Association. Guidelines for the -Use of the C{plusplus} Language in Critical Systems. June 2008. - -== Revision History - -[cols="^1,^1,<2,<3",options="header"] -|=== -|Revision |Date |Modified By |Description -|5 |2020-09-22 |Grant Erickson |Added Tightly-constrained Systems and Shared Infrastructure > Avoid Heap-based Resource Allocation -|4 |2020-09-15 |Grant Erickson |Added Common > Language-dependent > Avoid `using namespace` Statements in Headers -|3 |2020-09-01 |Grant Erickson |Added Common > Language-independent > Use C _stdint.h_ or C{plusplus} _cstdint_ for Plain Old Data Types -|2 |2020-07-09 |Grant Erickson |Added Common > Language-independent > Commenting Out or Disabling Code -|1 |2020-07-08 |Grant Erickson |Initial revision. -|=== - -[.text-center] -_Project Connect Home over IP Public Information_ diff --git a/docs/upgrading.md b/docs/upgrading.md index 5640c925aca5ec..517a83f6574dc9 100644 --- a/docs/upgrading.md +++ b/docs/upgrading.md @@ -92,3 +92,13 @@ Replacements for methods are: `chip::app::AttributeAccessInterfaceRegistry::Instance().UnregisterAllForEndpoint` - `chip::app::GetAttributeAccessOverride` replaced by `chip::app::AttributeAccessInterfaceRegistry::Instance().Get` + +### `ServerInitParams::dataModelProvider` in `Server::Init` and `FactoryInitParams` + +Server and controller initialization require a set data model provider to work +rather than auto-initializing ember-compatible code-generated data models. + +To preserve `codegen/zap` generated logic, use +`CodegenDataModelProviderInstance` (see changes in +[36558](https://github.com/project-chip/connectedhomeip/pull/36558) and +[36613](https://github.com/project-chip/connectedhomeip/pull/36613) ). diff --git a/examples/air-purifier-app/ameba/chip_main.cmake b/examples/air-purifier-app/ameba/chip_main.cmake index 22a325bf6eddec..4811bda0d88f0b 100755 --- a/examples/air-purifier-app/ameba/chip_main.cmake +++ b/examples/air-purifier-app/ameba/chip_main.cmake @@ -145,6 +145,11 @@ endif (matter_enable_ota_requestor) list( APPEND ${list_chip_main_sources} + ${chip_dir}/examples/air-purifier-app/air-purifier-common/src/air-purifier-manager.cpp + ${chip_dir}/examples/air-purifier-app/air-purifier-common/src/air-quality-sensor-manager.cpp + ${chip_dir}/examples/air-purifier-app/air-purifier-common/src/filter-delegates.cpp + ${chip_dir}/examples/air-purifier-app/air-purifier-common/src/thermostat-manager.cpp + ${chip_dir}/examples/air-purifier-app/ameba/main/chipinterface.cpp ${chip_dir}/examples/air-purifier-app/ameba/main/DeviceCallbacks.cpp ${chip_dir}/examples/air-purifier-app/ameba/main/CHIPDeviceManager.cpp @@ -192,6 +197,7 @@ target_include_directories( ${chip_dir}/examples/air-purifier-app/air-purifier-common/include ${chip_dir}/examples/air-purifier-app/ameba/main/include ${chip_dir}/examples/platform/ameba + ${chip_dir}/examples/platform/ameba/observer ${chip_dir}/examples/providers ${chip_dir_output}/gen/include ${chip_dir}/src/include/ diff --git a/examples/air-purifier-app/ameba/main/chipinterface.cpp b/examples/air-purifier-app/ameba/main/chipinterface.cpp index 0829bb041e4882..72563f987efdbe 100644 --- a/examples/air-purifier-app/ameba/main/chipinterface.cpp +++ b/examples/air-purifier-app/ameba/main/chipinterface.cpp @@ -17,6 +17,7 @@ #include +#include "AmebaObserver.h" #include "CHIPDeviceManager.h" #include "DeviceCallbacks.h" #include "Server.h" @@ -29,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -133,12 +135,15 @@ static void InitServer(intptr_t context) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); #if CONFIG_ENABLE_AMEBA_CRYPTO ChipLogProgress(DeviceLayer, "platform crypto enabled!"); static chip::AmebaPersistentStorageOperationalKeystore sAmebaPersistentStorageOpKeystore; VerifyOrDie((sAmebaPersistentStorageOpKeystore.Init(initParams.persistentStorageDelegate)) == CHIP_NO_ERROR); initParams.operationalKeystore = &sAmebaPersistentStorageOpKeystore; #endif + static AmebaObserver sAmebaObserver; + initParams.appDelegate = &sAmebaObserver; chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); @@ -151,6 +156,7 @@ static void InitServer(intptr_t context) PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); } + chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(&sAmebaObserver); InitAirPurifierManager(); } diff --git a/examples/air-purifier-app/cc32xx/main/AppTask.cpp b/examples/air-purifier-app/cc32xx/main/AppTask.cpp index 0b284254b0c80f..e7527ef338f05a 100644 --- a/examples/air-purifier-app/cc32xx/main/AppTask.cpp +++ b/examples/air-purifier-app/cc32xx/main/AppTask.cpp @@ -38,6 +38,7 @@ #include #include +#include #include #include @@ -164,6 +165,7 @@ int AppTask::Init() PLAT_LOG("Initialize Server"); static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // Initialize device attestation config diff --git a/examples/all-clusters-app/ameba/README.md b/examples/all-clusters-app/ameba/README.md index 5cf2c9aab87015..828dd567da7ee0 100644 --- a/examples/all-clusters-app/ameba/README.md +++ b/examples/all-clusters-app/ameba/README.md @@ -27,11 +27,11 @@ The CHIP demo application is supported on - Pull docker image: - $ docker pull ghcr.io/project-chip/chip-build-ameba:90 + $ docker pull ghcr.io/project-chip/chip-build-ameba:93 - Run docker container: - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:90 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:93 - Setup build environment: diff --git a/examples/all-clusters-app/ameba/chip_main.cmake b/examples/all-clusters-app/ameba/chip_main.cmake index 852673d07dd20c..cdcaab15651edf 100644 --- a/examples/all-clusters-app/ameba/chip_main.cmake +++ b/examples/all-clusters-app/ameba/chip_main.cmake @@ -248,6 +248,7 @@ target_include_directories( ${chip_dir}/examples/energy-management-app/energy-management-common/energy-reporting/include ${chip_dir}/examples/all-clusters-app/ameba/main/include ${chip_dir}/examples/platform/ameba + ${chip_dir}/examples/platform/ameba/observer ${chip_dir}/examples/platform/ameba/route_hook ${chip_dir}/examples/providers ${chip_dir_output}/gen/include diff --git a/examples/all-clusters-app/ameba/main/chipinterface.cpp b/examples/all-clusters-app/ameba/main/chipinterface.cpp index 7d06e72c094ecb..06ba9f01cd8256 100644 --- a/examples/all-clusters-app/ameba/main/chipinterface.cpp +++ b/examples/all-clusters-app/ameba/main/chipinterface.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -149,6 +150,7 @@ static void InitServer(intptr_t context) initParams.appDelegate = &sAmebaObserver; initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); #if CONFIG_ENABLE_AMEBA_CRYPTO ChipLogProgress(DeviceLayer, "platform crypto enabled!"); diff --git a/examples/all-clusters-app/infineon/psoc6/src/AppTask.cpp b/examples/all-clusters-app/infineon/psoc6/src/AppTask.cpp index bb499d20098abc..3b127091f13277 100644 --- a/examples/all-clusters-app/infineon/psoc6/src/AppTask.cpp +++ b/examples/all-clusters-app/infineon/psoc6/src/AppTask.cpp @@ -25,6 +25,7 @@ #include "LEDWidget.h" #include #include +#include #include #include #include @@ -129,6 +130,7 @@ static void InitServer(intptr_t context) // Init ZCL Data Model static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // We only have network commissioning on endpoint 0. diff --git a/examples/all-clusters-app/linux/fuzzing-main.cpp b/examples/all-clusters-app/linux/fuzzing-main.cpp index 2d8422d0d2eee6..5056f08cce65f4 100644 --- a/examples/all-clusters-app/linux/fuzzing-main.cpp +++ b/examples/all-clusters-app/linux/fuzzing-main.cpp @@ -16,6 +16,7 @@ */ #include "AppMain.h" +#include #include #include @@ -56,6 +57,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t * aData, size_t aSize) // ChipLinuxAppMainLoop blocks, and we don't want that here. static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); VerifyOrDie(Server::GetInstance().Init(initParams) == CHIP_NO_ERROR); ApplicationInit(); diff --git a/examples/all-clusters-app/mbed/main/AppTask.cpp b/examples/all-clusters-app/mbed/main/AppTask.cpp index f67876b1da5b57..98b8597ba43e5f 100644 --- a/examples/all-clusters-app/mbed/main/AppTask.cpp +++ b/examples/all-clusters-app/mbed/main/AppTask.cpp @@ -72,7 +72,8 @@ int AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); - error = Server::GetInstance().Init(initParams); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); + error = Server::GetInstance().Init(initParams); if (error != CHIP_NO_ERROR) { ChipLogError(NotSpecified, "Server initialization failed: %s", error.AsString()); diff --git a/examples/all-clusters-app/nrfconnect/main/AppTask.cpp b/examples/all-clusters-app/nrfconnect/main/AppTask.cpp index 067e8113c4138a..9dcd4238240111 100644 --- a/examples/all-clusters-app/nrfconnect/main/AppTask.cpp +++ b/examples/all-clusters-app/nrfconnect/main/AppTask.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -226,6 +227,7 @@ CHIP_ERROR AppTask::Init() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/examples/all-clusters-app/nxp/mw320/main.cpp b/examples/all-clusters-app/nxp/mw320/main.cpp index 82d335cccbb6b3..bf0d6a282e9373 100644 --- a/examples/all-clusters-app/nxp/mw320/main.cpp +++ b/examples/all-clusters-app/nxp/mw320/main.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -1068,6 +1069,7 @@ static void run_chip_srv(System::Layer * aSystemLayer, void * aAppState) static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); PRINTF("Done to call chip::Server() \r\n"); } diff --git a/examples/all-clusters-minimal-app/ameba/README.md b/examples/all-clusters-minimal-app/ameba/README.md index 447d950be39f86..947a9ed09f0eb0 100644 --- a/examples/all-clusters-minimal-app/ameba/README.md +++ b/examples/all-clusters-minimal-app/ameba/README.md @@ -27,13 +27,13 @@ The CHIP demo application is supported on - Pull docker image: ``` - $ docker pull ghcr.io/project-chip/chip-build-ameba:90 + $ docker pull ghcr.io/project-chip/chip-build-ameba:93 ``` - Run docker container: ``` - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:90 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:93 ``` - Setup build environment: diff --git a/examples/all-clusters-minimal-app/ameba/chip_main.cmake b/examples/all-clusters-minimal-app/ameba/chip_main.cmake index a2d1e364d63ee9..d60f4f58994951 100755 --- a/examples/all-clusters-minimal-app/ameba/chip_main.cmake +++ b/examples/all-clusters-minimal-app/ameba/chip_main.cmake @@ -128,9 +128,9 @@ endif (matter_enable_ota_requestor) list( APPEND ${list_chip_main_sources} - ${chip_dir}/examples/all-clusters-minimal-app/all-clusters-common/src/bridged-actions-stub.cpp - ${chip_dir}/examples/all-clusters-minimal-app/all-clusters-common/src/smco-stub.cpp - ${chip_dir}/examples/all-clusters-minimal-app/all-clusters-common/src/static-supported-modes-manager.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/smco-stub.cpp + ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp ${chip_dir}/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp ${chip_dir}/examples/all-clusters-minimal-app/ameba/main/DeviceCallbacks.cpp @@ -176,6 +176,7 @@ target_include_directories( ${chip_dir}/examples/all-clusters-app/all-clusters-common ${chip_dir}/examples/all-clusters-app/all-clusters-common/include ${chip_dir}/examples/all-clusters-minimal-app/ameba/main/include + ${chip_dir}/examples/platform/ameba/observer ${chip_dir_output}/gen/include ${chip_dir}/src/include/ ${chip_dir}/src/lib/ diff --git a/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp b/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp index 61f7db147f807d..cec1c457e04f04 100644 --- a/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp +++ b/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp @@ -17,6 +17,7 @@ #include +#include "AmebaObserver.h" #include "CHIPDeviceManager.h" #include "DeviceCallbacks.h" #include "Globals.h" @@ -26,6 +27,7 @@ #include #include +#include #include #include #include @@ -157,6 +159,11 @@ static void InitServer(intptr_t context) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); + + static AmebaObserver sAmebaObserver; + initParams.appDelegate = &sAmebaObserver; + chip::Server::GetInstance().Init(initParams); // Initialize device attestation config @@ -173,6 +180,7 @@ static void InitServer(intptr_t context) PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); } Clusters::ModeSelect::setSupportedModesManager(&sStaticSupportedModesManager); + chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(&sAmebaObserver); } extern "C" void ChipTest(void) diff --git a/examples/all-clusters-minimal-app/infineon/psoc6/src/AppTask.cpp b/examples/all-clusters-minimal-app/infineon/psoc6/src/AppTask.cpp index 56327c56dd9b94..29ad68b74241f1 100644 --- a/examples/all-clusters-minimal-app/infineon/psoc6/src/AppTask.cpp +++ b/examples/all-clusters-minimal-app/infineon/psoc6/src/AppTask.cpp @@ -25,6 +25,7 @@ #include "LEDWidget.h" #include #include +#include #include #include #include @@ -127,6 +128,7 @@ static void InitServer(intptr_t context) // Init ZCL Data Model static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // We only have network commissioning on endpoint 0. diff --git a/examples/all-clusters-minimal-app/linux/fuzzing-main.cpp b/examples/all-clusters-minimal-app/linux/fuzzing-main.cpp index b1736826ef335a..ccd2ffa782b4dd 100644 --- a/examples/all-clusters-minimal-app/linux/fuzzing-main.cpp +++ b/examples/all-clusters-minimal-app/linux/fuzzing-main.cpp @@ -16,6 +16,7 @@ */ #include "AppMain.h" +#include #include using namespace chip; @@ -43,6 +44,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t * aData, size_t aSize) // ChipLinuxAppMainLoop blocks, and we don't want that here. static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); VerifyOrDie(Server::GetInstance().Init(initParams) == CHIP_NO_ERROR); ApplicationInit(); diff --git a/examples/all-clusters-minimal-app/mbed/main/AppTask.cpp b/examples/all-clusters-minimal-app/mbed/main/AppTask.cpp index eb1188b93aa759..e516aee49e6e74 100644 --- a/examples/all-clusters-minimal-app/mbed/main/AppTask.cpp +++ b/examples/all-clusters-minimal-app/mbed/main/AppTask.cpp @@ -19,9 +19,10 @@ #include "AppTask.h" #include "LEDWidget.h" #include -#include +#include #include +#include #include #include #include @@ -67,7 +68,8 @@ int AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); - error = Server::GetInstance().Init(initParams); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); + error = Server::GetInstance().Init(initParams); if (error != CHIP_NO_ERROR) { ChipLogError(NotSpecified, "Server initialization failed: %s", error.AsString()); diff --git a/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp b/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp index be858eae561921..8d9771fa593204 100644 --- a/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp +++ b/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp @@ -22,6 +22,7 @@ #include "LEDUtil.h" #include "binding-handler.h" +#include #include #include @@ -173,6 +174,7 @@ CHIP_ERROR AppTask::Init() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OtaProviderClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OtaProviderClientFragment.kt index 13caa7b50ea09a..779ab2550e403d 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OtaProviderClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OtaProviderClientFragment.kt @@ -63,6 +63,9 @@ class OtaProviderClientFragment : Fragment() { private val vendorId: Int get() = binding.vendorIdEd.text.toString().toInt() + private val softwareVersion: Long + get() = binding.softwareVersionEd.text.toString().toLongOrNull() ?: 0L + private val otaProviderCallback = OtaProviderCallback() private val binding get() = _binding!! @@ -471,8 +474,8 @@ class OtaProviderClientFragment : Fragment() { } private fun updateOTAStatusBtnClick() { - val version = 2L - val versionString = "2.0" + val version = softwareVersion + val versionString = softwareVersion.toString() val filename = binding.firmwareFileTv.text.toString() Log.d(TAG, "updateOTAStatusBtnClick : $filename") @@ -648,6 +651,7 @@ class OtaProviderClientFragment : Fragment() { bufferedInputStream?.close() inputStream = null bufferedInputStream = null + showMessage("BDXTransfer End! - ErrorCode: $errorCode") } override fun handleBDXQuery( diff --git a/examples/android/CHIPTool/app/src/main/res/layout/ota_provider_client_fragment.xml b/examples/android/CHIPTool/app/src/main/res/layout/ota_provider_client_fragment.xml index 3d591f38b3435e..25ff9c252b56ef 100644 --- a/examples/android/CHIPTool/app/src/main/res/layout/ota_provider_client_fragment.xml +++ b/examples/android/CHIPTool/app/src/main/res/layout/ota_provider_client_fragment.xml @@ -153,11 +153,38 @@ android:padding="8dp" android:textSize="16sp" /> + + + + Read Write Vendor ID + SW Version + 1 Select Firmware Update OTA Status Start Firmware Update diff --git a/examples/chef/ameba/chip_main.cmake b/examples/chef/ameba/chip_main.cmake index 87c8aa158db8bb..cea3b85b4f813f 100755 --- a/examples/chef/ameba/chip_main.cmake +++ b/examples/chef/ameba/chip_main.cmake @@ -66,6 +66,7 @@ target_include_directories( ${chip_dir}/examples/all-clusters-app/all-clusters-common/include ${chip_dir}/examples/all-clusters-app/ameba/main/include ${chip_dir}/examples/platform/ameba + ${chip_dir}/examples/platform/ameba/observer ${chip_dir}/examples/providers ${chip_dir_output}/gen/include ${chip_dir}/src/include/ diff --git a/examples/chef/ameba/main/chipinterface.cpp b/examples/chef/ameba/main/chipinterface.cpp index f747cbbd886c42..6b772bdba6977b 100644 --- a/examples/chef/ameba/main/chipinterface.cpp +++ b/examples/chef/ameba/main/chipinterface.cpp @@ -17,6 +17,7 @@ #include +#include "AmebaObserver.h" #include "CHIPDeviceManager.h" #include "DeviceCallbacks.h" #include "Globals.h" @@ -27,6 +28,7 @@ #include #include +#include #include #include #include @@ -104,7 +106,13 @@ static void InitServer(intptr_t context) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); + + static AmebaObserver sAmebaObserver; + initParams.appDelegate = &sAmebaObserver; + chip::Server::GetInstance().Init(initParams); + gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); @@ -115,6 +123,7 @@ static void InitServer(intptr_t context) // QR code will be used with CHIP Tool PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); } + chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(&sAmebaObserver); } extern "C" void ChipTest(void) diff --git a/examples/chef/common/chef-operational-state-delegate-impl.h b/examples/chef/common/chef-operational-state-delegate-impl.h index 884a6f28c2828c..dcac2049d9abde 100644 --- a/examples/chef/common/chef-operational-state-delegate-impl.h +++ b/examples/chef/common/chef-operational-state-delegate-impl.h @@ -110,6 +110,7 @@ class OperationalStateDelegate : public GenericOperationalStateDelegateImpl GenericOperationalState(to_underlying(OperationalStateEnum::kPaused)), GenericOperationalState(to_underlying(OperationalStateEnum::kError)), }; + const CharSpan opPhaseList[3] = { "pre-soak"_span, "rinse"_span, "spin"_span }; public: const uint32_t kExampleCountDown = 30; @@ -117,6 +118,7 @@ class OperationalStateDelegate : public GenericOperationalStateDelegateImpl OperationalStateDelegate() { GenericOperationalStateDelegateImpl::mOperationalStateList = Span(opStateList); + GenericOperationalStateDelegateImpl::mOperationalPhaseList = Span(opPhaseList); } /** diff --git a/examples/chef/esp32/main/main.cpp b/examples/chef/esp32/main/main.cpp index b61fcf22bc1d19..ef5dd73dcabcf3 100644 --- a/examples/chef/esp32/main/main.cpp +++ b/examples/chef/esp32/main/main.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -159,6 +160,7 @@ void InitServer(intptr_t) // Start IM server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // Device Attestation & Onboarding codes diff --git a/examples/chef/nrfconnect/main.cpp b/examples/chef/nrfconnect/main.cpp index 1c7a3aa02aebf5..e7e706409ff421 100644 --- a/examples/chef/nrfconnect/main.cpp +++ b/examples/chef/nrfconnect/main.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -125,7 +126,8 @@ int main() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); - err = chip::Server::GetInstance().Init(initParams); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); + err = chip::Server::GetInstance().Init(initParams); if (err != CHIP_NO_ERROR) { return 1; diff --git a/examples/chip-tool/commands/common/CHIPCommand.cpp b/examples/chip-tool/commands/common/CHIPCommand.cpp index 4f14cb855e5af7..ffa873b49730f4 100644 --- a/examples/chip-tool/commands/common/CHIPCommand.cpp +++ b/examples/chip-tool/commands/common/CHIPCommand.cpp @@ -18,6 +18,7 @@ #include "CHIPCommand.h" +#include #include #include #include @@ -137,6 +138,7 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack() factoryInitParams.opCertStore = &mOpCertStore; factoryInitParams.enableServerInteractions = NeedsOperationalAdvertising(); factoryInitParams.sessionKeystore = &sSessionKeystore; + factoryInitParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); // Init group data provider that will be used for all group keys and IPKs for the // chip-tool-configured fabrics. This is OK to do once since the fabric tables diff --git a/examples/contact-sensor-app/nxp/k32w0/main/AppTask.cpp b/examples/contact-sensor-app/nxp/k32w0/main/AppTask.cpp index 40ffd9d8bff252..5eb7696fc69b7d 100644 --- a/examples/contact-sensor-app/nxp/k32w0/main/AppTask.cpp +++ b/examples/contact-sensor-app/nxp/k32w0/main/AppTask.cpp @@ -18,6 +18,7 @@ */ #include "AppTask.h" #include "AppEvent.h" +#include #include #include #include @@ -298,6 +299,7 @@ void AppTask::InitServer(intptr_t arg) { static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); auto & infoProvider = chip::DeviceLayer::DeviceInfoProviderImpl::GetDefaultInstance(); infoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); diff --git a/examples/contact-sensor-app/nxp/k32w1/args.gni b/examples/contact-sensor-app/nxp/k32w1/args.gni index 363718f1a8bbab..ee29002e00acec 100644 --- a/examples/contact-sensor-app/nxp/k32w1/args.gni +++ b/examples/contact-sensor-app/nxp/k32w1/args.gni @@ -42,3 +42,5 @@ chip_openthread_ftd = false nxp_enable_ot_cli = false chip_with_diag_logs_demo = true + +nxp_nvm_component = "nvs" diff --git a/examples/contact-sensor-app/nxp/mcxw71/args.gni b/examples/contact-sensor-app/nxp/mcxw71/args.gni index bf06f4e4948fb3..87a3b49632752a 100644 --- a/examples/contact-sensor-app/nxp/mcxw71/args.gni +++ b/examples/contact-sensor-app/nxp/mcxw71/args.gni @@ -40,3 +40,5 @@ chip_openthread_ftd = false nxp_enable_ot_cli = false chip_with_diag_logs_demo = true + +nxp_nvm_component = "nvs" diff --git a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter index dd5f9ab0616aa7..899dc159a0baaa 100644 --- a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter +++ b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter @@ -1724,6 +1724,7 @@ cluster IcdManagement = 70 { endpoint 0 { device type ma_rootdevice = 22, version 2; + device type ma_otarequestor = 18, version 1; binding cluster OtaSoftwareUpdateProvider; @@ -1732,6 +1733,9 @@ endpoint 0 { callback attribute serverList; callback attribute clientList; callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; } @@ -1740,7 +1744,6 @@ endpoint 0 { emits event AccessControlEntryChanged; emits event AccessControlExtensionChanged; callback attribute acl; - callback attribute extension; callback attribute subjectsPerAccessControlEntry; callback attribute targetsPerAccessControlEntry; callback attribute accessControlEntriesPerFabric; @@ -1774,7 +1777,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 3; + ram attribute clusterRevision default = 4; } server cluster OtaSoftwareUpdateRequestor { @@ -1785,6 +1788,9 @@ endpoint 0 { ram attribute updatePossible default = 1; ram attribute updateState default = 0; ram attribute updateStateProgress default = 0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -1801,7 +1807,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command ArmFailSafe; handle command ArmFailSafeResponse; @@ -1826,7 +1832,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 2; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; handle command ScanNetworks; handle command ScanNetworksResponse; @@ -1943,7 +1949,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0x000F; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; handle command ResetCounts; } @@ -1952,6 +1958,9 @@ endpoint 0 { callback attribute windowStatus; callback attribute adminFabricIndex; callback attribute adminVendorId; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -1966,6 +1975,9 @@ endpoint 0 { callback attribute commissionedFabrics; callback attribute trustedRootCertificates; callback attribute currentFabricIndex; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -1988,6 +2000,9 @@ endpoint 0 { callback attribute groupTable; callback attribute maxGroupsPerFabric; callback attribute maxGroupKeysPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; @@ -2034,7 +2049,7 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 4; + ram attribute clusterRevision default = 5; handle command Identify; handle command TriggerEffect; diff --git a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap index dfbd44ad6eb023..6658c278e98850 100644 --- a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap +++ b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap @@ -1,6 +1,6 @@ { "fileFormat": 2, - "featureLevel": 103, + "featureLevel": 104, "creator": "zap", "keyValuePairs": [ { @@ -41,21 +41,32 @@ "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 0 + }, + { + "code": 18, + "profileId": 259, + "label": "MA-otarequestor", + "name": "MA-otarequestor", + "deviceTypeOrder": 1 } ], "deviceVersions": [ - 2 + 2, + 1 ], "deviceIdentifiers": [ - 22 + 22, + 18 ], "deviceTypeName": "MA-rootdevice", "deviceTypeCode": 22, @@ -133,6 +144,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -191,22 +250,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "Extension", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "SubjectsPerAccessControlEntry", "code": 2, @@ -287,22 +330,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -649,22 +676,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -707,7 +718,7 @@ "storageOption": "RAM", "singleton": 1, "bounded": 0, - "defaultValue": "3", + "defaultValue": "4", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -870,6 +881,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -1097,22 +1156,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1155,7 +1198,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "2", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1429,22 +1472,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1487,7 +1514,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1553,22 +1580,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1765,22 +1776,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -2966,22 +2961,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3024,7 +3003,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -3106,6 +3085,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -3342,6 +3369,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -3498,6 +3573,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -3736,7 +3859,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3774,22 +3897,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3849,14 +3956,16 @@ "code": 21, "profileId": 259, "label": "MA-contactsensor", - "name": "MA-contactsensor" + "name": "MA-contactsensor", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 21, "profileId": 259, "label": "MA-contactsensor", - "name": "MA-contactsensor" + "name": "MA-contactsensor", + "deviceTypeOrder": 0 } ], "deviceVersions": [ @@ -4001,7 +4110,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "4", + "defaultValue": "5", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -4219,22 +4328,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, diff --git a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter index 1cd10f35718b3f..3c88ebe1202775 100644 --- a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter +++ b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter @@ -1724,6 +1724,7 @@ cluster IcdManagement = 70 { endpoint 0 { device type ma_rootdevice = 22, version 2; + device type ma_otarequestor = 18, version 1; binding cluster OtaSoftwareUpdateProvider; @@ -1732,6 +1733,9 @@ endpoint 0 { callback attribute serverList; callback attribute clientList; callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; } @@ -1740,7 +1744,6 @@ endpoint 0 { emits event AccessControlEntryChanged; emits event AccessControlExtensionChanged; callback attribute acl; - callback attribute extension; callback attribute subjectsPerAccessControlEntry; callback attribute targetsPerAccessControlEntry; callback attribute accessControlEntriesPerFabric; @@ -1774,7 +1777,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 3; + ram attribute clusterRevision default = 4; } server cluster OtaSoftwareUpdateRequestor { @@ -1785,6 +1788,9 @@ endpoint 0 { ram attribute updatePossible default = 1; ram attribute updateState default = 0; ram attribute updateStateProgress default = 0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -1801,7 +1807,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command ArmFailSafe; handle command ArmFailSafeResponse; @@ -1826,7 +1832,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 2; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; handle command ScanNetworks; handle command ScanNetworksResponse; @@ -1943,7 +1949,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0x000F; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; handle command ResetCounts; } @@ -1952,6 +1958,9 @@ endpoint 0 { callback attribute windowStatus; callback attribute adminFabricIndex; callback attribute adminVendorId; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -1966,6 +1975,9 @@ endpoint 0 { callback attribute commissionedFabrics; callback attribute trustedRootCertificates; callback attribute currentFabricIndex; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -1988,6 +2000,9 @@ endpoint 0 { callback attribute groupTable; callback attribute maxGroupsPerFabric; callback attribute maxGroupKeysPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; @@ -2021,7 +2036,7 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 4; + ram attribute clusterRevision default = 5; handle command Identify; handle command TriggerEffect; diff --git a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.zap b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.zap index 56717f4edfefcc..3110fe05f2eef0 100644 --- a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.zap +++ b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.zap @@ -1,6 +1,6 @@ { "fileFormat": 2, - "featureLevel": 103, + "featureLevel": 104, "creator": "zap", "keyValuePairs": [ { @@ -41,21 +41,32 @@ "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 0 + }, + { + "code": 18, + "profileId": 259, + "label": "MA-otarequestor", + "name": "MA-otarequestor", + "deviceTypeOrder": 1 } ], "deviceVersions": [ - 2 + 2, + 1 ], "deviceIdentifiers": [ - 22 + 22, + 18 ], "deviceTypeName": "MA-rootdevice", "deviceTypeCode": 22, @@ -133,6 +144,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -191,22 +250,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "Extension", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "SubjectsPerAccessControlEntry", "code": 2, @@ -287,22 +330,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -649,22 +676,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -707,7 +718,7 @@ "storageOption": "RAM", "singleton": 1, "bounded": 0, - "defaultValue": "3", + "defaultValue": "4", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -870,6 +881,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -1097,22 +1156,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1155,7 +1198,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "2", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1429,22 +1472,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1487,7 +1514,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1553,22 +1580,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1765,22 +1776,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -2966,22 +2961,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3024,7 +3003,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -3106,6 +3085,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -3342,6 +3369,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -3498,6 +3573,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -3620,22 +3743,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3695,14 +3802,16 @@ "code": 21, "profileId": 259, "label": "MA-contactsensor", - "name": "MA-contactsensor" + "name": "MA-contactsensor", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 21, "profileId": 259, "label": "MA-contactsensor", - "name": "MA-contactsensor" + "name": "MA-contactsensor", + "deviceTypeOrder": 0 } ], "deviceVersions": [ @@ -3847,7 +3956,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "4", + "defaultValue": "5", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -4065,22 +4174,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, diff --git a/examples/dishwasher-app/silabs/include/operational-state-delegate-impl.h b/examples/dishwasher-app/silabs/include/operational-state-delegate-impl.h index 8b8d24e11524d7..354dea9912873a 100644 --- a/examples/dishwasher-app/silabs/include/operational-state-delegate-impl.h +++ b/examples/dishwasher-app/silabs/include/operational-state-delegate-impl.h @@ -67,7 +67,7 @@ class OperationalStateDelegate : public Delegate void SetEndpointId(EndpointId endpointId); private: - const GenericOperationalState rvcOpStateList[4] = { + const GenericOperationalState dishwasherOpStateList[4] = { GenericOperationalState(to_underlying(OperationalStateEnum::kStopped)), GenericOperationalState(to_underlying(OperationalStateEnum::kRunning)), GenericOperationalState(to_underlying(OperationalStateEnum::kPaused)), @@ -76,7 +76,8 @@ class OperationalStateDelegate : public Delegate EndpointId mEndpointId; - DataModel::List mOperationalStateList = Span(rvcOpStateList); + DataModel::List mOperationalStateList = + Span(dishwasherOpStateList); const Span mOperationalPhaseList; }; diff --git a/examples/energy-management-app/linux/README.md b/examples/energy-management-app/linux/README.md index 87b6d9dd93db39..637b80f95de8f0 100644 --- a/examples/energy-management-app/linux/README.md +++ b/examples/energy-management-app/linux/README.md @@ -613,3 +613,19 @@ Step-by-step: [1730312762.703] [2153606:2153609] [TOO] TankVolume: 100 ``` + +1. Set boost state: + + - `durationIndicates` the time period in seconds for which the BOOST state + is activated before it automatically reverts to the previous mode (e.g. + OFF, MANUAL or TIMED). + + ``` + ./out/linux-x64-chip-tool-no-ble/chip-tool waterheatermanagement boost '{ "duration": 1800 }' 0x12344321 2 + ``` + +1. Cancel boost state: + + ``` + ./out/linux-x64-chip-tool-no-ble/chip-tool waterheatermanagement cancel-boost 0x12344321 2 + ``` diff --git a/examples/fabric-admin/README.md b/examples/fabric-admin/README.md index 92fdffda6b830f..3ec2cb99671eba 100644 --- a/examples/fabric-admin/README.md +++ b/examples/fabric-admin/README.md @@ -23,13 +23,13 @@ For Raspberry Pi 4 example: ### Pull Docker Images ``` -docker pull ghcr.io/project-chip/chip-build-crosscompile:90 +docker pull ghcr.io/project-chip/chip-build-crosscompile:93 ``` ### Run docker ``` -docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:90 /bin/bash +docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:93 /bin/bash ``` ### Build diff --git a/examples/fabric-admin/commands/common/CHIPCommand.cpp b/examples/fabric-admin/commands/common/CHIPCommand.cpp index e7f4071d122b31..1f761fcbbeff8f 100644 --- a/examples/fabric-admin/commands/common/CHIPCommand.cpp +++ b/examples/fabric-admin/commands/common/CHIPCommand.cpp @@ -19,6 +19,8 @@ #include "CHIPCommand.h" #include "IcdManager.h" + +#include #include #include #include @@ -121,6 +123,7 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack() factoryInitParams.opCertStore = &mOpCertStore; factoryInitParams.enableServerInteractions = NeedsOperationalAdvertising(); factoryInitParams.sessionKeystore = &sSessionKeystore; + factoryInitParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); // Init group data provider that will be used for all group keys and IPKs for the // fabric-admin-configured fabrics. This is OK to do once since the fabric tables diff --git a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp index e8296fa478d95d..59405786a8091f 100644 --- a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp +++ b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp @@ -32,6 +32,13 @@ using namespace ::chip; namespace admin { +namespace { + +constexpr uint32_t kDefaultSetupPinCode = 20202021; +constexpr uint16_t kDefaultLocalBridgePort = 5540; + +} // namespace + void FabricSyncAddBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) { if (mBridgeNodeId != deviceId) @@ -92,10 +99,8 @@ CHIP_ERROR FabricSyncAddBridgeCommand::RunCommand(NodeId remoteId) mBridgeNodeId = remoteId; - DeviceManager::Instance().PairRemoteFabricBridge(remoteId, mSetupPINCode, reinterpret_cast(mRemoteAddr.data()), - mRemotePort); - - return CHIP_NO_ERROR; + return PairingManager::Instance().PairDevice(remoteId, mSetupPINCode, reinterpret_cast(mRemoteAddr.data()), + mRemotePort); } void FabricSyncRemoveBridgeCommand::OnDeviceRemoved(NodeId deviceId, CHIP_ERROR err) @@ -135,9 +140,8 @@ CHIP_ERROR FabricSyncRemoveBridgeCommand::RunCommand() mBridgeNodeId = bridgeNodeId; PairingManager::Instance().SetPairingDelegate(this); - DeviceManager::Instance().UnpairRemoteFabricBridge(); - return CHIP_NO_ERROR; + return PairingManager::Instance().UnpairDevice(bridgeNodeId); } void FabricSyncAddLocalBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) @@ -185,18 +189,10 @@ CHIP_ERROR FabricSyncAddLocalBridgeCommand::RunCommand(NodeId deviceId) PairingManager::Instance().SetPairingDelegate(this); mLocalBridgeNodeId = deviceId; - if (mSetupPINCode.HasValue()) - { - DeviceManager::Instance().SetLocalBridgeSetupPinCode(mSetupPINCode.Value()); - } - if (mLocalPort.HasValue()) - { - DeviceManager::Instance().SetLocalBridgePort(mLocalPort.Value()); - } + uint16_t localBridgePort = mLocalPort.ValueOr(kDefaultLocalBridgePort); + uint32_t localBridgeSetupPinCode = mSetupPINCode.ValueOr(kDefaultSetupPinCode); - DeviceManager::Instance().PairLocalFabricBridge(deviceId); - - return CHIP_NO_ERROR; + return PairingManager::Instance().PairDevice(deviceId, localBridgeSetupPinCode, "::1", localBridgePort); } void FabricSyncRemoveLocalBridgeCommand::OnDeviceRemoved(NodeId deviceId, CHIP_ERROR err) @@ -236,9 +232,8 @@ CHIP_ERROR FabricSyncRemoveLocalBridgeCommand::RunCommand() mLocalBridgeNodeId = bridgeNodeId; PairingManager::Instance().SetPairingDelegate(this); - DeviceManager::Instance().UnpairLocalFabricBridge(); - return CHIP_NO_ERROR; + return PairingManager::Instance().UnpairDevice(mLocalBridgeNodeId); } void FabricSyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_ERROR err, SetupPayload payload) @@ -259,7 +254,10 @@ void FabricSyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_ usleep(kCommissionPrepareTimeMs * 1000); - DeviceManager::Instance().PairRemoteDevice(nodeId, payloadBuffer); + if (PairingManager::Instance().PairDeviceWithCode(nodeId, payloadBuffer) != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to sync device " ChipLogFormatX64, ChipLogValueX64(nodeId)); + } } else { diff --git a/examples/fabric-admin/device_manager/DeviceManager.cpp b/examples/fabric-admin/device_manager/DeviceManager.cpp index 7e40a8196555ea..67c634b440daf0 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.cpp +++ b/examples/fabric-admin/device_manager/DeviceManager.cpp @@ -39,6 +39,7 @@ constexpr EndpointId kAggregatorEndpointId = 1; constexpr uint16_t kWindowTimeout = 300; constexpr uint16_t kIteration = 1000; constexpr uint16_t kMaxDiscriminatorLength = 4095; +constexpr uint16_t kResponseTimeoutSeconds = 30; } // namespace @@ -177,47 +178,6 @@ void DeviceManager::OpenRemoteDeviceCommissioningWindow(EndpointId remoteEndpoin } } -void DeviceManager::PairRemoteFabricBridge(NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp, - uint16_t deviceRemotePort) -{ - if (PairingManager::Instance().PairDevice(nodeId, setupPINCode, deviceRemoteIp, deviceRemotePort) != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to pair remote fabric bridge " ChipLogFormatX64, ChipLogValueX64(nodeId)); - } -} - -void DeviceManager::PairRemoteDevice(NodeId nodeId, const char * payload) -{ - if (PairingManager::Instance().PairDeviceWithCode(nodeId, payload) != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to pair remote device " ChipLogFormatX64, ChipLogValueX64(nodeId)); - } -} - -void DeviceManager::PairLocalFabricBridge(NodeId nodeId) -{ - if (PairingManager::Instance().PairDevice(nodeId, mLocalBridgeSetupPinCode, "::1", mLocalBridgePort) != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to pair local fabric bridge " ChipLogFormatX64, ChipLogValueX64(nodeId)); - } -} - -void DeviceManager::UnpairRemoteFabricBridge() -{ - if (PairingManager::Instance().UnpairDevice(mRemoteBridgeNodeId) != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to unpair remote bridge device " ChipLogFormatX64, ChipLogValueX64(mRemoteBridgeNodeId)); - } -} - -void DeviceManager::UnpairLocalFabricBridge() -{ - if (PairingManager::Instance().UnpairDevice(mLocalBridgeNodeId) != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to unpair local bridge device " ChipLogFormatX64, ChipLogValueX64(mLocalBridgeNodeId)); - } -} - void DeviceManager::SubscribeRemoteFabricBridge() { ChipLogProgress(NotSpecified, "Start subscription to the remote bridge."); @@ -227,8 +187,9 @@ void DeviceManager::SubscribeRemoteFabricBridge() if (error != CHIP_NO_ERROR) { - ChipLogError(NotSpecified, "Failed to subscribe to the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, - mRemoteBridgeNodeId, error.Format()); + ChipLogError(NotSpecified, + "Failed to subscribe to the remote bridge (NodeId: " ChipLogFormatX64 "). Error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mRemoteBridgeNodeId), error.Format()); return; } } @@ -251,8 +212,9 @@ void DeviceManager::ReadSupportedDeviceCategories() if (error != CHIP_NO_ERROR) { ChipLogError(NotSpecified, - "Failed to read SupportedDeviceCategories from the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, - mRemoteBridgeNodeId, error.Format()); + "Failed to read SupportedDeviceCategories from the remote bridge (NodeId: " ChipLogFormatX64 + "). Error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mRemoteBridgeNodeId), error.Format()); } } @@ -293,8 +255,9 @@ void DeviceManager::RequestCommissioningApproval() if (error != CHIP_NO_ERROR) { ChipLogError(NotSpecified, - "Failed to request commissioning-approval to the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, - mRemoteBridgeNodeId, error.Format()); + "Failed to request commissioning-approval to the remote bridge (NodeId: " ChipLogFormatX64 + "). Error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mRemoteBridgeNodeId), error.Format()); return; } @@ -417,8 +380,9 @@ void DeviceManager::SendCommissionNodeRequest(uint64_t requestId, uint16_t respo if (error != CHIP_NO_ERROR) { ChipLogError(NotSpecified, - "Failed to send CommissionNode command to the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, - mRemoteBridgeNodeId, error.Format()); + "Failed to send CommissionNode command to the remote bridge (NodeId: " ChipLogFormatX64 + "). Error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mRemoteBridgeNodeId), error.Format()); return; } } diff --git a/examples/fabric-admin/device_manager/DeviceManager.h b/examples/fabric-admin/device_manager/DeviceManager.h index 8c273ee53d3af7..b326996bddb323 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.h +++ b/examples/fabric-admin/device_manager/DeviceManager.h @@ -28,10 +28,6 @@ namespace admin { -constexpr uint32_t kDefaultSetupPinCode = 20202021; -constexpr uint16_t kDefaultLocalBridgePort = 5540; -constexpr uint16_t kResponseTimeoutSeconds = 30; - class SyncedDevice { public: @@ -73,8 +69,6 @@ class DeviceManager void SetRemoteBridgeNodeId(chip::NodeId nodeId); - void SetLocalBridgePort(uint16_t port) { mLocalBridgePort = port; } - void SetLocalBridgeSetupPinCode(uint32_t pinCode) { mLocalBridgeSetupPinCode = pinCode; } void SetLocalBridgeNodeId(chip::NodeId nodeId) { mLocalBridgeNodeId = nodeId; } bool IsFabricSyncReady() const { return mRemoteBridgeNodeId != chip::kUndefinedNodeId; } @@ -133,45 +127,6 @@ class DeviceManager */ void OpenRemoteDeviceCommissioningWindow(chip::EndpointId remoteEndpointId); - /** - * @brief Pair a remote fabric bridge with a given node ID. - * - * This function initiates the pairing process for a remote fabric bridge using the specified parameters. - - * @param nodeId The user-defined ID for the node being commissioned. It doesn’t need to be the same ID, - * as for the first fabric. - * @param setupPINCode The setup PIN code used to authenticate the pairing process. - * @param deviceRemoteIp The IP address of the remote device that is being paired as part of the fabric bridge. - * @param deviceRemotePort The secured device port of the remote device that is being paired as part of the fabric bridge. - */ - void PairRemoteFabricBridge(chip::NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp, uint16_t deviceRemotePort); - - /** - * @brief Pair a remote Matter device to the current fabric. - * - * This function initiates the pairing process for a remote device using the specified parameters. - - * @param nodeId The user-defined ID for the node being commissioned. It doesn’t need to be the same ID, - * as for the first fabric. - * @param payload The the QR code payload or a manual pairing code generated by the first commissioner - * instance when opened commissioning window. - */ - void PairRemoteDevice(chip::NodeId nodeId, const char * payload); - - /** - * @brief Pair a local fabric bridge with a given node ID. - * - * This function initiates the pairing process for the local fabric bridge using the specified parameters. - - * @param nodeId The user-defined ID for the node being commissioned. It doesn’t need to be the same ID, - * as for the first fabric. - */ - void PairLocalFabricBridge(chip::NodeId nodeId); - - void UnpairRemoteFabricBridge(); - - void UnpairLocalFabricBridge(); - void SubscribeRemoteFabricBridge(); void ReadSupportedDeviceCategories(); @@ -204,8 +159,6 @@ class DeviceManager // This represents the bridge on the other ecosystem. chip::NodeId mRemoteBridgeNodeId = chip::kUndefinedNodeId; - uint16_t mLocalBridgePort = kDefaultLocalBridgePort; - uint32_t mLocalBridgeSetupPinCode = kDefaultSetupPinCode; // The Node ID of the local bridge used for Fabric-Sync // This represents the bridge within its own ecosystem. chip::NodeId mLocalBridgeNodeId = chip::kUndefinedNodeId; diff --git a/examples/fabric-admin/rpc/RpcServer.cpp b/examples/fabric-admin/rpc/RpcServer.cpp index f59a2729dbfa84..a7c9259dde140f 100644 --- a/examples/fabric-admin/rpc/RpcServer.cpp +++ b/examples/fabric-admin/rpc/RpcServer.cpp @@ -174,13 +174,16 @@ class FabricAdmin final : public rpc::FabricAdmin, public admin::PairingDelegate if (error == CHIP_NO_ERROR) { mNodeId = DeviceManager::Instance().GetNextAvailableNodeId(); - ; // After responding with RequestCommissioningApproval to the node where the client initiated the // RequestCommissioningApproval, you need to wait for it to open a commissioning window on its bridge. usleep(kCommissionPrepareTimeMs * 1000); PairingManager::Instance().SetPairingDelegate(this); - DeviceManager::Instance().PairRemoteDevice(mNodeId, code.c_str()); + + if (PairingManager::Instance().PairDeviceWithCode(mNodeId, code.c_str()) != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to commission device " ChipLogFormatX64, ChipLogValueX64(mNodeId)); + } } else { diff --git a/examples/fabric-bridge-app/linux/README.md b/examples/fabric-bridge-app/linux/README.md index 912bb32c01dafb..b8f1b4a68be295 100644 --- a/examples/fabric-bridge-app/linux/README.md +++ b/examples/fabric-bridge-app/linux/README.md @@ -100,13 +100,13 @@ defined: Pull Docker Images ``` - docker pull ghcr.io/project-chip/chip-build-crosscompile:90 + docker pull ghcr.io/project-chip/chip-build-crosscompile:93 ``` Run docker ``` - docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:90 /bin/bash + docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:93 /bin/bash ``` Build diff --git a/examples/fabric-sync/README.md b/examples/fabric-sync/README.md index 0fd4735c745552..2ef7949245f611 100644 --- a/examples/fabric-sync/README.md +++ b/examples/fabric-sync/README.md @@ -80,30 +80,30 @@ defined: ## Building - ### For Linux host example: +- For Linux host example: - ``` + ```sh source scripts/activate.sh ./scripts/build/build_examples.py --target linux-x64-fabric-sync-no-ble build ``` - ### For Raspberry Pi 4 example: +- For Raspberry Pi 4 example: Pull Docker Images - ``` - docker pull ghcr.io/project-chip/chip-build-crosscompile:90 + ```sh + docker pull ghcr.io/project-chip/chip-build-crosscompile:93 ``` Run docker - ``` - docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:90 /bin/bash + ```sh + docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:93 /bin/bash ``` Build - ``` + ```sh cd /var/connectedhomeip git config --global --add safe.directory /var/connectedhomeip @@ -116,7 +116,7 @@ defined: Transfer the fabric-bridge-app binary to a Raspberry Pi - ``` + ```sh scp ./fabric-sync ubuntu@xxx.xxx.xxx.xxx:/home/ubuntu ``` @@ -126,9 +126,60 @@ defined: Follow [Building](#building) section of this document. -- Run Linux Fabric Sync Example App +- Run Linux Fabric Sync Example App on two Linux machine E1 and E2 ```sh + sudo rm -rf /tmp/chip_* cd ~/connectedhomeip/ - sudo out/debug/fabric-sync + out/debug/fabric-sync + ``` + +- Initiate the FS Setup Process from E1 to E2 + + ```sh + > app add-bridge 1 20202021 192.168.86.246 5540 + Done + > New device with Node ID: 0000000000000001 has been successfully added. + A new device has been added on Endpoint: 2. + ``` + +- Verify Reverse Commissioning of the Fabric-Bridge from E1 on E2 + + ```sh + > New device with Node ID: 0000000000000002 has been successfully added. + ``` + +- Pair Light Example to E2 + + Since Fabric-Bridge also functions as a Matter server, running it alongside + the Light Example app on the same machine would cause conflicts. Therefore, + you need to run the Matter Light Example app on a separate physical machine + from the one hosting Fabric-Sync. + + ```sh + > app add-device 3 + ``` + + After the device is successfully added, you will observe the following + message on E2 with the newly assigned Node ID: + + ```sh + > New device with Node ID: 0x3 has been successfully added. + ``` + + Additionally, you should also get notified when a new device is added to E2 + from the E1: + + ```sh + > A new device is added on Endpoint 3. + ``` + +- Synchronize Light Example to E1 + + After the Light Example is successfully paired in E2, we can start to + synchronize the light device to E1 using the new assigned dynamic endpointid + on Ecosystem 2. + + ```sh + > app sync-device ``` diff --git a/examples/fabric-sync/admin/BUILD.gn b/examples/fabric-sync/admin/BUILD.gn index 2ccc30ca2f7976..e53590388e6f76 100644 --- a/examples/fabric-sync/admin/BUILD.gn +++ b/examples/fabric-sync/admin/BUILD.gn @@ -44,8 +44,12 @@ source_set("fabric-admin-lib") { "FabricAdmin.h", "FabricSyncGetter.cpp", "FabricSyncGetter.h", + "IcdManager.cpp", + "IcdManager.h", "PairingManager.cpp", "PairingManager.h", + "StayActiveSender.cpp", + "StayActiveSender.h", "UniqueIdGetter.cpp", "UniqueIdGetter.h", ] @@ -53,6 +57,8 @@ source_set("fabric-admin-lib") { deps = [ "${chip_root}/examples/fabric-sync/bridge:fabric-bridge-lib", "${chip_root}/examples/platform/linux:app-main", + "${chip_root}/src/app/icd/client:handler", + "${chip_root}/src/app/icd/client:manager", "${chip_root}/src/lib", ] } diff --git a/examples/fabric-sync/admin/DeviceManager.cpp b/examples/fabric-sync/admin/DeviceManager.cpp index f9685295e48ad2..f37ac4ac8fd5b5 100644 --- a/examples/fabric-sync/admin/DeviceManager.cpp +++ b/examples/fabric-sync/admin/DeviceManager.cpp @@ -72,11 +72,7 @@ void DeviceManager::UpdateLastUsedNodeId(NodeId nodeId) void DeviceManager::SetRemoteBridgeNodeId(chip::NodeId nodeId) { mRemoteBridgeNodeId = nodeId; - - if (mRemoteBridgeNodeId != kUndefinedNodeId) - { - mCommissionerControl.Init(PairingManager::Instance().CurrentCommissioner(), mRemoteBridgeNodeId, kAggregatorEndpointId); - } + ChipLogProgress(NotSpecified, "Set remote bridge NodeId:" ChipLogFormatX64, ChipLogValueX64(mRemoteBridgeNodeId)); } void DeviceManager::AddSyncedDevice(const SyncedDevice & device) @@ -131,6 +127,18 @@ void DeviceManager::RemoveSyncedDevice(chip::ScopedNodeId scopedNodeId) ChipLogValueX64(device->GetNodeId()), device->GetEndpointId()); } +void DeviceManager::InitCommissionerControl() +{ + if (mRemoteBridgeNodeId != kUndefinedNodeId) + { + mCommissionerControl.Init(PairingManager::Instance().CurrentCommissioner(), mRemoteBridgeNodeId, kAggregatorEndpointId); + } + else + { + ChipLogError(NotSpecified, "Failed to initialize the Commissioner Control delegate"); + } +} + void DeviceManager::OpenLocalBridgeCommissioningWindow(uint32_t iterations, uint16_t commissioningTimeoutSec, uint16_t discriminator, const ByteSpan & salt, const ByteSpan & verifier) { @@ -204,81 +212,6 @@ void DeviceManager::OpenRemoteDeviceCommissioningWindow(EndpointId remoteEndpoin } } -CHIP_ERROR DeviceManager::PairRemoteFabricBridge(NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp, - uint16_t deviceRemotePort) -{ - CHIP_ERROR err = PairingManager::Instance().PairDevice(nodeId, setupPINCode, deviceRemoteIp, deviceRemotePort); - - if (err != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, - "Failed to pair remote fabric bridge: Node ID " ChipLogFormatX64 " with error: %" CHIP_ERROR_FORMAT, - ChipLogValueX64(nodeId), err.Format()); - return err; - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR DeviceManager::PairRemoteDevice(NodeId nodeId, const char * payload) -{ - CHIP_ERROR err = PairingManager::Instance().PairDeviceWithCode(nodeId, payload); - - if (err != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to pair device: Node ID " ChipLogFormatX64 " with error: %" CHIP_ERROR_FORMAT, - ChipLogValueX64(nodeId), err.Format()); - return err; - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR DeviceManager::PairRemoteDevice(NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp, - uint16_t deviceRemotePort) -{ - CHIP_ERROR err = PairingManager::Instance().PairDevice(nodeId, setupPINCode, deviceRemoteIp, deviceRemotePort); - - if (err != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to pair device: Node ID " ChipLogFormatX64 " with error: %" CHIP_ERROR_FORMAT, - ChipLogValueX64(nodeId), err.Format()); - return err; - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR DeviceManager::UnpairRemoteFabricBridge() -{ - if (mRemoteBridgeNodeId == kUndefinedNodeId) - { - ChipLogError(NotSpecified, "Remote bridge node ID is undefined; cannot unpair device."); - return CHIP_ERROR_INCORRECT_STATE; - } - - CHIP_ERROR err = PairingManager::Instance().UnpairDevice(mRemoteBridgeNodeId); - if (err != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to unpair remote bridge device " ChipLogFormatX64, ChipLogValueX64(mRemoteBridgeNodeId)); - return err; - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR DeviceManager::UnpairRemoteDevice(NodeId nodeId) -{ - CHIP_ERROR err = PairingManager::Instance().UnpairDevice(nodeId); - if (err != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to unpair remote device " ChipLogFormatX64, ChipLogValueX64(nodeId)); - return err; - } - - return CHIP_NO_ERROR; -} - void DeviceManager::SubscribeRemoteFabricBridge() { ChipLogProgress(NotSpecified, "Start subscription to the remote bridge."); @@ -288,8 +221,9 @@ void DeviceManager::SubscribeRemoteFabricBridge() if (error != CHIP_NO_ERROR) { - ChipLogError(NotSpecified, "Failed to subscribe to the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, - mRemoteBridgeNodeId, error.Format()); + ChipLogError(NotSpecified, + "Failed to subscribe to the remote bridge (NodeId: " ChipLogFormatX64 "). Error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mRemoteBridgeNodeId), error.Format()); return; } } @@ -312,8 +246,9 @@ void DeviceManager::ReadSupportedDeviceCategories() if (error != CHIP_NO_ERROR) { ChipLogError(NotSpecified, - "Failed to read SupportedDeviceCategories from the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, - mRemoteBridgeNodeId, error.Format()); + "Failed to read SupportedDeviceCategories from the remote bridge (NodeId: " ChipLogFormatX64 + "). Error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mRemoteBridgeNodeId), error.Format()); } } @@ -354,8 +289,9 @@ void DeviceManager::RequestCommissioningApproval() if (error != CHIP_NO_ERROR) { ChipLogError(NotSpecified, - "Failed to request commissioning-approval to the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, - mRemoteBridgeNodeId, error.Format()); + "Failed to request commissioning-approval to the remote bridge (NodeId: " ChipLogFormatX64 + "). Error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mRemoteBridgeNodeId), error.Format()); return; } @@ -478,8 +414,9 @@ void DeviceManager::SendCommissionNodeRequest(uint64_t requestId, uint16_t respo if (error != CHIP_NO_ERROR) { ChipLogError(NotSpecified, - "Failed to send CommissionNode command to the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, - mRemoteBridgeNodeId, error.Format()); + "Failed to send CommissionNode command to the remote bridge (NodeId: " ChipLogFormatX64 + "). Error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mRemoteBridgeNodeId), error.Format()); return; } } diff --git a/examples/fabric-sync/admin/DeviceManager.h b/examples/fabric-sync/admin/DeviceManager.h index 9afb1eec7d033f..a8a012ce9c7d60 100644 --- a/examples/fabric-sync/admin/DeviceManager.h +++ b/examples/fabric-sync/admin/DeviceManager.h @@ -76,6 +76,11 @@ class DeviceManager void RemoveSyncedDevice(chip::ScopedNodeId scopedNodeId); + /** + * @brief Initializes the CommissionerControl for fabric sync setup process. + */ + void InitCommissionerControl(); + /** * @brief Determines whether a given nodeId corresponds to the remote bridge device. * @@ -135,71 +140,6 @@ class DeviceManager */ void OpenRemoteDeviceCommissioningWindow(chip::EndpointId remoteEndpointId); - /** - * @brief Pair a remote fabric bridge with a given node ID. - * - * This function initiates the pairing process for a remote fabric bridge using the specified parameters. - - * @param nodeId The user-defined ID for the node being commissioned. It doesn’t need to be the same ID, - * as for the first fabric. - * @param setupPINCode The setup PIN code used to authenticate the pairing process. - * @param deviceRemoteIp The IP address of the remote device that is being paired as part of the fabric bridge. - * @param deviceRemotePort The secured device port of the remote device that is being paired as part of the fabric bridge. - * - * @return CHIP_ERROR Returns CHIP_NO_ERROR on success or an appropriate error code on failure. - */ - CHIP_ERROR PairRemoteFabricBridge(chip::NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp, - uint16_t deviceRemotePort); - - /** - * @brief Pair a remote Matter device to the current fabric. - * - * This function initiates the pairing process for a remote device using the specified parameters. - - * @param nodeId The user-defined ID for the node being commissioned. It doesn’t need to be the same ID, - * as for the first fabric. - * @param payload The the QR code payload or a manual pairing code generated by the first commissioner - * instance when opened commissioning window. - * - * @return CHIP_ERROR Returns CHIP_NO_ERROR on success or an appropriate error code on failure. - */ - CHIP_ERROR PairRemoteDevice(chip::NodeId nodeId, const char * payload); - - /** - * @brief Pair a remote Matter device to the current fabric. - * - * This function initiates the pairing process for a remote device using the specified parameters. - - * @param nodeId The user-defined ID for the node being commissioned. It doesn’t need to be the same ID, - * as for the first fabric. - * @param setupPINCode The setup PIN code used to authenticate the pairing process. - * @param deviceRemoteIp The IP address of the remote device that is being paired as part of the fabric bridge. - * @param deviceRemotePort The secured device port of the remote device that is being paired as part of the fabric bridge. - * - * @return CHIP_ERROR Returns CHIP_NO_ERROR on success or an appropriate error code on failure. - */ - CHIP_ERROR PairRemoteDevice(chip::NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp, uint16_t deviceRemotePort); - - /** - * @brief Unpair the remote Matter fabric bridge. - * - * This function initiates the unpairing process for the remote Matter fabric bridge from the current fabric. - * - * @return CHIP_ERROR Returns CHIP_NO_ERROR on success or an appropriate error code on failure. - */ - CHIP_ERROR UnpairRemoteFabricBridge(); - - /** - * @brief Unpair a specific remote Matter device from the current fabric. - * - * This function removes a specific remote device, identified by the node ID, from the fabric. - * - * @param nodeId The user-defined ID of the node that is being unpaired. - * - * @return CHIP_ERROR Returns CHIP_NO_ERROR on success or an appropriate error code on failure. - */ - CHIP_ERROR UnpairRemoteDevice(chip::NodeId nodeId); - void SubscribeRemoteFabricBridge(); void ReadSupportedDeviceCategories(); diff --git a/examples/fabric-sync/admin/DeviceSynchronization.cpp b/examples/fabric-sync/admin/DeviceSynchronization.cpp index 05a4fa9db8f398..527ccfa631295a 100644 --- a/examples/fabric-sync/admin/DeviceSynchronization.cpp +++ b/examples/fabric-sync/admin/DeviceSynchronization.cpp @@ -262,7 +262,7 @@ void DeviceSynchronizer::GetUniqueId() } else { - ChipLogDetail(NotSpecified, "Failed to get UniqueId from remote Fabric Sync Aggregator") + ChipLogDetail(NotSpecified, "Failed to get UniqueId from remote Fabric Sync Aggregator"); } } diff --git a/examples/fabric-sync/admin/FabricAdmin.cpp b/examples/fabric-sync/admin/FabricAdmin.cpp index 4e170ce78db043..b4be20e0e296e6 100644 --- a/examples/fabric-sync/admin/FabricAdmin.cpp +++ b/examples/fabric-sync/admin/FabricAdmin.cpp @@ -16,6 +16,10 @@ */ #include "FabricAdmin.h" +#include +#include +#include +#include using namespace ::chip; @@ -28,16 +32,35 @@ constexpr uint32_t kCommissionPrepareTimeMs = 500; } // namespace FabricAdmin FabricAdmin::sInstance; +app::DefaultICDClientStorage FabricAdmin::sICDClientStorage; +app::CheckInHandler FabricAdmin::sCheckInHandler; FabricAdmin & FabricAdmin::Instance() { if (!sInstance.mInitialized) { - sInstance.Init(); + VerifyOrDie(sInstance.Init() == CHIP_NO_ERROR); } return sInstance; } +CHIP_ERROR FabricAdmin::Init() +{ + IcdManager::Instance().SetDelegate(&sInstance); + + ReturnLogErrorOnFailure(sICDClientStorage.Init(GetPersistentStorageDelegate(), GetSessionKeystore())); + + auto engine = chip::app::InteractionModelEngine::GetInstance(); + VerifyOrReturnError(engine != nullptr, CHIP_ERROR_INCORRECT_STATE); + ReturnLogErrorOnFailure(IcdManager::Instance().Init(&sICDClientStorage, engine)); + ReturnLogErrorOnFailure(sCheckInHandler.Init(Controller::DeviceControllerFactory::GetInstance().GetSystemState()->ExchangeMgr(), + &sICDClientStorage, &IcdManager::Instance(), engine)); + + mInitialized = true; + + return CHIP_NO_ERROR; +} + CHIP_ERROR FabricAdmin::OpenCommissioningWindow(Controller::CommissioningWindowVerifierParams params, FabricIndex fabricIndex) { ScopedNodeId scopedNodeId(params.GetNodeId(), fabricIndex); @@ -86,13 +109,20 @@ FabricAdmin::CommissionRemoteBridge(Controller::CommissioningWindowPasscodeParam if (err == CHIP_NO_ERROR) { - NodeId nodeId = DeviceManager::Instance().GetNextAvailableNodeId(); + mNodeId = DeviceManager::Instance().GetNextAvailableNodeId(); // After responding with RequestCommissioningApproval to the node where the client initiated the // RequestCommissioningApproval, you need to wait for it to open a commissioning window on its bridge. usleep(kCommissionPrepareTimeMs * 1000); - DeviceManager::Instance().PairRemoteDevice(nodeId, code.c_str()); + PairingManager::Instance().SetPairingDelegate(this); + err = PairingManager::Instance().PairDeviceWithCode(mNodeId, code.c_str()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, + "Failed to commission remote bridge device: Node ID " ChipLogFormatX64 " with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mNodeId), err.Format()); + } } else { @@ -115,6 +145,68 @@ CHIP_ERROR FabricAdmin::KeepActive(ScopedNodeId scopedNodeId, uint32_t stayActiv return CHIP_NO_ERROR; } +void FabricAdmin::OnCheckInCompleted(const app::ICDClientInfo & clientInfo) +{ + // Accessing mPendingCheckIn should only be done while holding ChipStackLock + assertChipStackLockedByCurrentThread(); + ScopedNodeId scopedNodeId = clientInfo.peer_node; + auto it = mPendingCheckIn.find(scopedNodeId); + VerifyOrReturn(it != mPendingCheckIn.end()); + + KeepActiveDataForCheckIn checkInData = it->second; + // Removed from pending map as check-in from this node has occured and we will handle the pending KeepActive + // request. + mPendingCheckIn.erase(scopedNodeId); + + auto timeNow = System::SystemClock().GetMonotonicTimestamp(); + if (timeNow > checkInData.mRequestExpiryTimestamp) + { + ChipLogError(NotSpecified, + "ICD check-in for device we have been waiting, came after KeepActive expiry. Request dropped for ID: " + "[%d:0x " ChipLogFormatX64 "]", + scopedNodeId.GetFabricIndex(), ChipLogValueX64(scopedNodeId.GetNodeId())); + return; + } + + // TODO https://github.com/CHIP-Specifications/connectedhomeip-spec/issues/10448. Spec does + // not define what to do if we fail to send the StayActiveRequest. We are assuming that any + // further attempts to send a StayActiveRequest will result in a similar failure. Because + // there is no mechanism for us to communicate with the client that sent out the KeepActive + // command that there was a failure, we simply fail silently. After spec issue is + // addressed, we can implement what spec defines here. + auto onDone = [=](uint32_t promisedActiveDuration) { + bridge::FabricBridge::Instance().ActiveChanged(scopedNodeId, promisedActiveDuration); + }; + CHIP_ERROR err = StayActiveSender::SendStayActiveCommand(checkInData.mStayActiveDurationMs, clientInfo.peer_node, + app::InteractionModelEngine::GetInstance(), onDone); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to send StayActive command %s", err.AsString()); + } +} + +void FabricAdmin::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) +{ + if (mNodeId != deviceId) + { + ChipLogError(NotSpecified, "Tried to pair a non-bridge device (0x:" ChipLogFormatX64 ") with result: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + return; + } + + if (err == CHIP_NO_ERROR) + { + DeviceManager::Instance().SetRemoteBridgeNodeId(deviceId); + } + else + { + ChipLogError(NotSpecified, "Failed to pair bridge device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + } + + mNodeId = kUndefinedNodeId; +} + void FabricAdmin::ScheduleSendingKeepActiveOnCheckIn(ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs, uint32_t timeoutMs) { // Accessing mPendingCheckIn should only be done while holding ChipStackLock diff --git a/examples/fabric-sync/admin/FabricAdmin.h b/examples/fabric-sync/admin/FabricAdmin.h index bec98dc4140183..85547373f1238b 100644 --- a/examples/fabric-sync/admin/FabricAdmin.h +++ b/examples/fabric-sync/admin/FabricAdmin.h @@ -18,7 +18,12 @@ #pragma once #include "DeviceManager.h" +#include "IcdManager.h" +#include "StayActiveSender.h" +#include +#include +#include #include #include #include @@ -37,10 +42,11 @@ struct ScopedNodeIdHasher } }; -class FabricAdmin final : public bridge::FabricAdminDelegate +class FabricAdmin final : public bridge::FabricAdminDelegate, public PairingDelegate, public IcdManager::Delegate { public: static FabricAdmin & Instance(); + static chip::app::DefaultICDClientStorage & GetDefaultICDClientStorage() { return sICDClientStorage; } CHIP_ERROR OpenCommissioningWindow(chip::Controller::CommissioningWindowVerifierParams params, chip::FabricIndex fabricIndex) override; @@ -51,6 +57,10 @@ class FabricAdmin final : public bridge::FabricAdminDelegate CHIP_ERROR KeepActive(chip::ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs, uint32_t timeoutMs) override; + void OnCheckInCompleted(const chip::app::ICDClientInfo & clientInfo) override; + + void OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR err) override; + void ScheduleSendingKeepActiveOnCheckIn(chip::ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs, uint32_t timeoutMs); private: @@ -87,10 +97,13 @@ class FabricAdmin final : public bridge::FabricAdminDelegate std::unordered_map mPendingCheckIn; static FabricAdmin sInstance; + static chip::app::DefaultICDClientStorage sICDClientStorage; + static chip::app::CheckInHandler sCheckInHandler; - bool mInitialized = false; + bool mInitialized = false; + chip::NodeId mNodeId = chip::kUndefinedNodeId; - void Init() { mInitialized = true; } + CHIP_ERROR Init(); }; } // namespace admin diff --git a/examples/fabric-sync/admin/IcdManager.cpp b/examples/fabric-sync/admin/IcdManager.cpp new file mode 100644 index 00000000000000..75c49a7fd9707b --- /dev/null +++ b/examples/fabric-sync/admin/IcdManager.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "IcdManager.h" + +namespace admin { + +IcdManager IcdManager::sInstance; + +IcdManager & IcdManager::Instance() +{ + return sInstance; +} + +void IcdManager::OnCheckInComplete(const chip::app::ICDClientInfo & clientInfo) +{ + DefaultCheckInDelegate::OnCheckInComplete(clientInfo); + if (mDelegate) + { + mDelegate->OnCheckInCompleted(clientInfo); + } +} + +void IcdManager::SetDelegate(Delegate * delegate) +{ + // To keep IcdManager simple, there is an assumption that there is only ever + // one delegate set and it's lifetime is identical to IcdManager. In the + // future this assumption can change should there be a need, but that will + // require code changes to IcdManager. For now we will crash if someone tries + // to call SetDelegate for a second time or if delegate is non-null. + VerifyOrDie(delegate); + VerifyOrDie(!mDelegate); + mDelegate = delegate; +} + +} // namespace admin diff --git a/examples/fabric-sync/admin/IcdManager.h b/examples/fabric-sync/admin/IcdManager.h new file mode 100644 index 00000000000000..0700363bf5b411 --- /dev/null +++ b/examples/fabric-sync/admin/IcdManager.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#pragma once + +#include + +namespace admin { + +/** + * @brief Manages check-ins from ICD devices. + * + * Intended to be used as a thin CheckInDelegate. This allows a delegate register + * themselves so they can be aware when ICD device checks-in allowing the + * delegate to interact with the ICD device during the short window that it is + * awake. + */ +class IcdManager : public chip::app::DefaultCheckInDelegate +{ +public: + class Delegate + { + public: + virtual ~Delegate() = default; + virtual void OnCheckInCompleted(const chip::app::ICDClientInfo & clientInfo) = 0; + }; + + static IcdManager & Instance(); + void OnCheckInComplete(const chip::app::ICDClientInfo & clientInfo) override; + + // There is an assumption delegate assigned only happens once and that it lives + // for the entirety of the lifetime of fabric admin. + void SetDelegate(Delegate * delegate); + +private: + static IcdManager sInstance; + Delegate * mDelegate = nullptr; +}; + +} // namespace admin diff --git a/examples/fabric-sync/admin/PairingManager.cpp b/examples/fabric-sync/admin/PairingManager.cpp index 954680fe176187..e7585ca6df0d2e 100644 --- a/examples/fabric-sync/admin/PairingManager.cpp +++ b/examples/fabric-sync/admin/PairingManager.cpp @@ -18,6 +18,7 @@ #include "PairingManager.h" #include "DeviceManager.h" #include "DeviceSynchronization.h" +#include "FabricAdmin.h" #include #include @@ -103,7 +104,7 @@ PairingManager::PairingManager() : CHIP_ERROR PairingManager::Init(Controller::DeviceCommissioner * commissioner) { VerifyOrReturnError(commissioner != nullptr, CHIP_ERROR_INCORRECT_STATE); - + FabricAdmin::Instance().GetDefaultICDClientStorage().UpdateFabricList(commissioner->GetFabricIndex()); mCommissioner = commissioner; return CHIP_NO_ERROR; @@ -281,6 +282,12 @@ void PairingManager::OnPairingDeleted(CHIP_ERROR err) void PairingManager::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err) { + if (mPairingDelegate) + { + mPairingDelegate->OnCommissioningComplete(nodeId, err); + SetPairingDelegate(nullptr); + } + if (err == CHIP_NO_ERROR) { // print to console @@ -288,18 +295,22 @@ void PairingManager::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err) // mCommissioner has a lifetime that is the entire life of the application itself // so it is safe to provide to StartDeviceSynchronization. - DeviceSynchronizer::Instance().StartDeviceSynchronization(mCommissioner, nodeId, false); + DeviceSynchronizer::Instance().StartDeviceSynchronization(mCommissioner, nodeId, mDeviceIsICD); } else { + // When ICD device commissioning fails, the ICDClientInfo stored in OnICDRegistrationComplete needs to be removed. + if (mDeviceIsICD) + { + CHIP_ERROR deleteEntryError = FabricAdmin::Instance().GetDefaultICDClientStorage().DeleteEntry( + ScopedNodeId(nodeId, mCommissioner->GetFabricIndex())); + if (deleteEntryError != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to delete ICD entry: %s", ErrorStr(err)); + } + } ChipLogProgress(NotSpecified, "Device commissioning Failure: %s", ErrorStr(err)); } - - if (mPairingDelegate) - { - mPairingDelegate->OnCommissioningComplete(nodeId, err); - SetPairingDelegate(nullptr); - } } void PairingManager::OnReadCommissioningInfo(const Controller::ReadCommissioningInfo & info) @@ -329,6 +340,49 @@ void PairingManager::OnReadCommissioningInfo(const Controller::ReadCommissioning info.icd.idleModeDuration, info.icd.activeModeDuration, info.icd.activeModeThreshold); } +void PairingManager::OnICDRegistrationComplete(ScopedNodeId nodeId, uint32_t icdCounter) +{ + char icdSymmetricKeyHex[Crypto::kAES_CCM128_Key_Length * 2 + 1]; + + Encoding::BytesToHex(mICDSymmetricKey.Value().data(), mICDSymmetricKey.Value().size(), icdSymmetricKeyHex, + sizeof(icdSymmetricKeyHex), Encoding::HexFlags::kNullTerminate); + + app::ICDClientInfo clientInfo; + clientInfo.peer_node = nodeId; + clientInfo.monitored_subject = mICDMonitoredSubject.Value(); + clientInfo.start_icd_counter = icdCounter; + auto & ICDClientStorage = FabricAdmin::Instance().GetDefaultICDClientStorage(); + + CHIP_ERROR err = ICDClientStorage.SetKey(clientInfo, mICDSymmetricKey.Value()); + if (err == CHIP_NO_ERROR) + { + err = ICDClientStorage.StoreEntry(clientInfo); + } + + if (err != CHIP_NO_ERROR) + { + ICDClientStorage.RemoveKey(clientInfo); + ChipLogError(NotSpecified, "Failed to persist symmetric key for " ChipLogFormatX64 ": %s", + ChipLogValueX64(nodeId.GetNodeId()), err.AsString()); + return; + } + + mDeviceIsICD = true; + + ChipLogProgress(NotSpecified, "Saved ICD Symmetric key for " ChipLogFormatX64, ChipLogValueX64(nodeId.GetNodeId())); + ChipLogProgress(NotSpecified, + "ICD Registration Complete for device " ChipLogFormatX64 " / Check-In NodeID: " ChipLogFormatX64 + " / Monitored Subject: " ChipLogFormatX64 " / Symmetric Key: %s / ICDCounter %u", + ChipLogValueX64(nodeId.GetNodeId()), ChipLogValueX64(mICDCheckInNodeId.Value()), + ChipLogValueX64(mICDMonitoredSubject.Value()), icdSymmetricKeyHex, icdCounter); +} + +void PairingManager::OnICDStayActiveComplete(ScopedNodeId deviceId, uint32_t promisedActiveDuration) +{ + ChipLogProgress(NotSpecified, "ICD Stay Active Complete for device " ChipLogFormatX64 " / promisedActiveDuration: %u", + ChipLogValueX64(deviceId.GetNodeId()), promisedActiveDuration); +} + void PairingManager::OnDiscoveredDevice(const Dnssd::CommissionNodeData & nodeData) { // Ignore nodes with closed commissioning window @@ -436,6 +490,39 @@ CommissioningParameters PairingManager::GetCommissioningParameters() params.SetSkipCommissioningComplete(false); params.SetDeviceAttestationDelegate(this); + if (mICDRegistration.ValueOr(false)) + { + params.SetICDRegistrationStrategy(ICDRegistrationStrategy::kBeforeComplete); + + if (!mICDSymmetricKey.HasValue()) + { + Crypto::DRBG_get_bytes(mRandomGeneratedICDSymmetricKey, sizeof(mRandomGeneratedICDSymmetricKey)); + mICDSymmetricKey.SetValue(ByteSpan(mRandomGeneratedICDSymmetricKey)); + } + if (!mICDCheckInNodeId.HasValue()) + { + mICDCheckInNodeId.SetValue(mCommissioner->GetNodeId()); + } + if (!mICDMonitoredSubject.HasValue()) + { + mICDMonitoredSubject.SetValue(mICDCheckInNodeId.Value()); + } + if (!mICDClientType.HasValue()) + { + mICDClientType.SetValue(app::Clusters::IcdManagement::ClientTypeEnum::kPermanent); + } + // These Optionals must have values now. + // The commissioner will verify these values. + params.SetICDSymmetricKey(mICDSymmetricKey.Value()); + if (mICDStayActiveDurationMsec.HasValue()) + { + params.SetICDStayActiveDurationMsec(mICDStayActiveDurationMsec.Value()); + } + params.SetICDCheckInNodeId(mICDCheckInNodeId.Value()); + params.SetICDMonitoredSubject(mICDMonitoredSubject.Value()); + params.SetICDClientType(mICDClientType.Value()); + } + return params; } @@ -482,6 +569,7 @@ void PairingManager::OnCurrentFabricRemove(void * context, NodeId nodeId, CHIP_E void PairingManager::InitPairingCommand() { mCommissioner->RegisterPairingDelegate(this); + mDeviceIsICD = false; } CHIP_ERROR PairingManager::PairDeviceWithCode(NodeId nodeId, const char * payload) @@ -548,6 +636,12 @@ CHIP_ERROR PairingManager::PairDevice(chip::NodeId nodeId, uint32_t setupPINCode CHIP_ERROR PairingManager::UnpairDevice(NodeId nodeId) { + if (nodeId == kUndefinedNodeId) + { + ChipLogError(NotSpecified, "node ID is undefined; cannot unpair device."); + return CHIP_ERROR_INCORRECT_STATE; + } + return DeviceLayer::SystemLayer().ScheduleLambda([nodeId]() { PairingManager & self = PairingManager::Instance(); diff --git a/examples/fabric-sync/admin/PairingManager.h b/examples/fabric-sync/admin/PairingManager.h index 9d109911e195df..37e9aedec65bdb 100644 --- a/examples/fabric-sync/admin/PairingManager.h +++ b/examples/fabric-sync/admin/PairingManager.h @@ -149,6 +149,8 @@ class PairingManager : public chip::Controller::DevicePairingDelegate, void OnPairingDeleted(CHIP_ERROR error) override; void OnReadCommissioningInfo(const chip::Controller::ReadCommissioningInfo & info) override; void OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR error) override; + void OnICDRegistrationComplete(chip::ScopedNodeId deviceId, uint32_t icdCounter) override; + void OnICDStayActiveComplete(chip::ScopedNodeId deviceId, uint32_t promisedActiveDuration) override; /////////// DeviceDiscoveryDelegate Interface ///////// void OnDiscoveredDevice(const chip::Dnssd::CommissionNodeData & nodeData) override; @@ -176,11 +178,20 @@ class PairingManager : public chip::Controller::DevicePairingDelegate, chip::ByteSpan mSalt; uint16_t mDiscriminator = 0; uint32_t mSetupPINCode = 0; + bool mDeviceIsICD = false; + uint8_t mRandomGeneratedICDSymmetricKey[chip::Crypto::kAES_CCM128_Key_Length]; uint8_t mVerifierBuffer[chip::Crypto::kSpake2p_VerifierSerialized_Length]; uint8_t mSaltBuffer[chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length]; char mRemoteIpAddr[chip::Inet::IPAddress::kMaxStringLength]; char mOnboardingPayload[kMaxManualCodeLength + 1]; + chip::Optional mICDRegistration; + chip::Optional mICDCheckInNodeId; + chip::Optional mICDClientType; + chip::Optional mICDSymmetricKey; + chip::Optional mICDMonitoredSubject; + chip::Optional mICDStayActiveDurationMsec; + /** * Holds the unique_ptr to the current CommissioningWindowOpener. * Only one commissioning window opener can be active at a time. diff --git a/examples/fabric-sync/admin/StayActiveSender.cpp b/examples/fabric-sync/admin/StayActiveSender.cpp new file mode 100644 index 00000000000000..51927c4d598999 --- /dev/null +++ b/examples/fabric-sync/admin/StayActiveSender.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "StayActiveSender.h" + +#include +#include +#include +#include + +namespace admin { + +CHIP_ERROR StayActiveSender::SendStayActiveCommand(uint32_t stayActiveDurationMs, const chip::ScopedNodeId & peerNode, + chip::app::InteractionModelEngine * engine, OnDoneCallbackType onDone) +{ + ConstructorOnlyInternallyCallable internal; + auto stayActiveSender = chip::Platform::New(internal, stayActiveDurationMs, peerNode, + chip::app::InteractionModelEngine::GetInstance(), onDone); + VerifyOrReturnError(stayActiveSender != nullptr, CHIP_ERROR_NO_MEMORY); + CHIP_ERROR err = stayActiveSender->EstablishSessionToPeer(); + if (CHIP_NO_ERROR != err) + { + chip::Platform::Delete(stayActiveSender); + } + return err; +} + +StayActiveSender::StayActiveSender(const ConstructorOnlyInternallyCallable & _, uint32_t stayActiveDurationMs, + const chip::ScopedNodeId & peerNode, chip::app::InteractionModelEngine * engine, + OnDoneCallbackType onDone) : + mStayActiveDurationMs(stayActiveDurationMs), + mPeerNode(peerNode), mpImEngine(engine), mOnDone(onDone), mOnConnectedCallback(HandleDeviceConnected, this), + mOnConnectionFailureCallback(HandleDeviceConnectionFailure, this) +{} + +CHIP_ERROR StayActiveSender::SendStayActiveCommand(chip::Messaging::ExchangeManager & exchangeMgr, + const chip::SessionHandle & sessionHandle) +{ + auto onSuccess = [&](const chip::app::ConcreteCommandPath & commandPath, const chip::app::StatusIB & status, + const auto & dataResponse) { + uint32_t promisedActiveDurationMs = dataResponse.promisedActiveDuration; + ChipLogProgress(ICD, "StayActive command succeeded with promised duration %u", promisedActiveDurationMs); + mOnDone(promisedActiveDurationMs); + chip::Platform::Delete(this); + }; + + auto onFailure = [&](CHIP_ERROR error) { + ChipLogError(ICD, "StayActive command failed: %" CHIP_ERROR_FORMAT, error.Format()); + chip::Platform::Delete(this); + }; + + chip::EndpointId endpointId = 0; + chip::app::Clusters::IcdManagement::Commands::StayActiveRequest::Type request; + request.stayActiveDuration = mStayActiveDurationMs; + return chip::Controller::InvokeCommandRequest(&exchangeMgr, sessionHandle, endpointId, request, onSuccess, onFailure); +} + +CHIP_ERROR StayActiveSender::EstablishSessionToPeer() +{ + ChipLogProgress(ICD, "Trying to establish a CASE session to extend the active period for lit icd device"); + auto * caseSessionManager = mpImEngine->GetCASESessionManager(); + VerifyOrReturnError(caseSessionManager != nullptr, CHIP_ERROR_INVALID_CASE_PARAMETER); + caseSessionManager->FindOrEstablishSession(mPeerNode, &mOnConnectedCallback, &mOnConnectionFailureCallback); + return CHIP_NO_ERROR; +} + +void StayActiveSender::HandleDeviceConnected(void * context, chip::Messaging::ExchangeManager & exchangeMgr, + const chip::SessionHandle & sessionHandle) +{ + StayActiveSender * const _this = static_cast(context); + VerifyOrDie(_this != nullptr); + + CHIP_ERROR err = _this->SendStayActiveCommand(exchangeMgr, sessionHandle); + if (CHIP_NO_ERROR != err) + { + ChipLogError(ICD, "Failed to send stay active command"); + chip::Platform::Delete(_this); + } +} + +void StayActiveSender::HandleDeviceConnectionFailure(void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR err) +{ + StayActiveSender * const _this = static_cast(context); + VerifyOrDie(_this != nullptr); + ChipLogError(ICD, "Failed to establish CASE for stay active command with error '%" CHIP_ERROR_FORMAT "'", err.Format()); + chip::Platform::Delete(_this); +} + +} // namespace admin diff --git a/examples/fabric-sync/admin/StayActiveSender.h b/examples/fabric-sync/admin/StayActiveSender.h new file mode 100644 index 00000000000000..dd4a66ddeda59e --- /dev/null +++ b/examples/fabric-sync/admin/StayActiveSender.h @@ -0,0 +1,111 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +#include +#include + +namespace admin { + +/** + * @brief StayActiveSender contains all the data and methods needed for active period extension of an ICD client. + * + * Lifetime of instance of StayActiveSender is entirely self managed. + */ +class StayActiveSender +{ +private: + // Ideally StayActiveSender would be a private constructor, unfortunately that is not possible as Platform::New + // does not have access to private constructors. As a workaround we have defined this private struct that can + // be forwarded by Platform::New that allows us to enforce that the only way StayActiveSender is constructed is + // if SendStayActiveCommand is called. + struct ConstructorOnlyInternallyCallable + { + }; + +public: + using OnDoneCallbackType = std::function; + + /** + * @brief Attempts to send a StayActiveRequest command + * + * @param[in] stayActiveDurationMs StayActiveRequest command parameter. + * @param[in] peerNode Peer node we sending StayActiveRequest command to + * @param[in] engine Interaction Model Engine instance for sending command. + * @param[in] onDone Upon this function returning success, it is expected that onDone will be called after we + * have successfully recieved a response + * + * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error code. + */ + static CHIP_ERROR SendStayActiveCommand(uint32_t stayActiveDurationMs, const chip::ScopedNodeId & peerNode, + chip::app::InteractionModelEngine * engine, OnDoneCallbackType onDone); + + // Ideally this would be a private constructor, unfortunately that is not possible as Platform::New does not + // have access to private constructors. As a workaround we have defined a private struct that can be forwarded + // by Platform::New that allows us to enforce that the only way this is constructed is if SendStayActiveCommand + // is called. + StayActiveSender(const ConstructorOnlyInternallyCallable & _, uint32_t stayActiveDurationMs, + const chip::ScopedNodeId & peerNode, chip::app::InteractionModelEngine * engine, OnDoneCallbackType onDone); + +private: + /** + * @brief Sets up a CASE session with the peer to extend the client's active period with that peer. + * Returns error if we did not even manage to kick off a CASE attempt. + */ + CHIP_ERROR EstablishSessionToPeer(); + + // CASE session callbacks + /** + *@brief Callback received on successfully establishing a CASE session in order to keep the 'lit icd device' active + * + * @param[in] context - context of the client establishing the CASE session + * @param[in] exchangeMgr - exchange manager to use for the re-registration + * @param[in] sessionHandle - session handle to use for the re-registration + */ + static void HandleDeviceConnected(void * context, chip::Messaging::ExchangeManager & exchangeMgr, + const chip::SessionHandle & sessionHandle); + /** + * @brief Callback received on failure to establish a CASE session + * + * @param[in] context - context of the client establishing the CASE session + * @param[in] peerId - Scoped Node ID of the peer node + * @param[in] err - failure reason + */ + static void HandleDeviceConnectionFailure(void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR err); + + /** + * @brief Used to send a stayActive command to the peer + * + * @param[in] exchangeMgr - exchange manager to use for the re-registration + * @param[in] sessionHandle - session handle to use for the re-registration + */ + CHIP_ERROR SendStayActiveCommand(chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle); + + uint32_t mStayActiveDurationMs = 0; + chip::ScopedNodeId mPeerNode; + chip::app::InteractionModelEngine * mpImEngine = nullptr; + OnDoneCallbackType mOnDone; + + chip::Callback::Callback mOnConnectedCallback; + chip::Callback::Callback mOnConnectionFailureCallback; +}; + +} // namespace admin diff --git a/examples/fabric-sync/bridge/include/FabricAdminDelegate.h b/examples/fabric-sync/bridge/include/FabricAdminDelegate.h index 1637c5294fb7a7..b37273aa7c5801 100644 --- a/examples/fabric-sync/bridge/include/FabricAdminDelegate.h +++ b/examples/fabric-sync/bridge/include/FabricAdminDelegate.h @@ -61,6 +61,19 @@ class FabricAdminDelegate virtual CHIP_ERROR CommissionRemoteBridge(chip::Controller::CommissioningWindowPasscodeParams params, chip::VendorId vendorId, uint16_t productId) = 0; + /** + * Sends a request to keep a device active for a specified duration. + * + * @param ScopedNodeId Identifies the target node within the fabric. + * @param StayActiveDurationMs The duration for which the device should stay active. + * @param TimeoutMs Timeout for the operation. + * + * @return CHIP_ERROR An error code indicating the success or failure of the + * operation. + * - CHIP_NO_ERROR: Request processed successfully. + * - CHIP_ERROR_INTERNAL: An internal error occurred during the preparation or sending + * of the command. + */ virtual CHIP_ERROR KeepActive(chip::ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs, uint32_t timeoutMs) = 0; }; diff --git a/examples/fabric-sync/main.cpp b/examples/fabric-sync/main.cpp index 8772400ff2ae16..a372760d3a2dfc 100644 --- a/examples/fabric-sync/main.cpp +++ b/examples/fabric-sync/main.cpp @@ -16,6 +16,7 @@ */ #include +#include #include #include #include diff --git a/examples/fabric-sync/shell/AddBridgeCommand.cpp b/examples/fabric-sync/shell/AddBridgeCommand.cpp index e6b9dd060351e6..eb8579c298e4f7 100644 --- a/examples/fabric-sync/shell/AddBridgeCommand.cpp +++ b/examples/fabric-sync/shell/AddBridgeCommand.cpp @@ -55,6 +55,7 @@ void AddBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) admin::DeviceManager::Instance().UpdateLastUsedNodeId(mBridgeNodeId); admin::DeviceManager::Instance().SubscribeRemoteFabricBridge(); + admin::DeviceManager::Instance().InitCommissionerControl(); // After successful commissioning of the Commissionee, initiate Reverse Commissioning // via the Commissioner Control Cluster. However, we must first verify that the @@ -84,10 +85,11 @@ CHIP_ERROR AddBridgeCommand::RunCommand() admin::PairingManager::Instance().SetPairingDelegate(this); - ChipLogProgress(NotSpecified, "Running AddBridgeCommand with Node ID: %lu, PIN Code: %u, Address: %s, Port: %u", mBridgeNodeId, - mSetupPINCode, mRemoteAddr, mRemotePort); + ChipLogProgress(NotSpecified, + "Running AddBridgeCommand with Node ID: " ChipLogFormatX64 ", PIN Code: %u, Address: %s, Port: %u", + ChipLogValueX64(mBridgeNodeId), mSetupPINCode, mRemoteAddr, mRemotePort); - return admin::DeviceManager::Instance().PairRemoteFabricBridge(mBridgeNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); + return admin::PairingManager::Instance().PairDevice(mBridgeNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); } } // namespace commands diff --git a/examples/fabric-sync/shell/AddDeviceCommand.cpp b/examples/fabric-sync/shell/AddDeviceCommand.cpp index a79e4696caaf4e..47bcc226564bc6 100644 --- a/examples/fabric-sync/shell/AddDeviceCommand.cpp +++ b/examples/fabric-sync/shell/AddDeviceCommand.cpp @@ -71,12 +71,13 @@ CHIP_ERROR AddDeviceCommand::RunCommand() return CHIP_ERROR_INVALID_ARGUMENT; } - ChipLogProgress(NotSpecified, "Running AddDeviceCommand with Node ID: %lu, PIN Code: %u, Address: %s, Port: %u", mNodeId, - mSetupPINCode, mRemoteAddr, mRemotePort); + ChipLogProgress(NotSpecified, + "Running AddDeviceCommand with Node ID: " ChipLogFormatX64 ", PIN Code: %u, Address: %s, Port: %u", + ChipLogValueX64(mNodeId), mSetupPINCode, mRemoteAddr, mRemotePort); admin::PairingManager::Instance().SetPairingDelegate(this); - return admin::DeviceManager::Instance().PairRemoteDevice(mNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); + return admin::PairingManager::Instance().PairDevice(mNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); } } // namespace commands diff --git a/examples/fabric-sync/shell/BUILD.gn b/examples/fabric-sync/shell/BUILD.gn index 3aa56122254a4a..d5545087c97414 100644 --- a/examples/fabric-sync/shell/BUILD.gn +++ b/examples/fabric-sync/shell/BUILD.gn @@ -33,6 +33,8 @@ source_set("shell") { "AddDeviceCommand.h", "CommandRegistry.cpp", "CommandRegistry.h", + "PairDeviceCommand.cpp", + "PairDeviceCommand.h", "RemoveBridgeCommand.cpp", "RemoveBridgeCommand.h", "RemoveDeviceCommand.cpp", diff --git a/examples/fabric-sync/shell/PairDeviceCommand.cpp b/examples/fabric-sync/shell/PairDeviceCommand.cpp new file mode 100644 index 00000000000000..bc06c80dfaeec8 --- /dev/null +++ b/examples/fabric-sync/shell/PairDeviceCommand.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "PairDeviceCommand.h" + +#include +#include + +using namespace ::chip; + +namespace commands { + +PairDeviceCommand::PairDeviceCommand(chip::NodeId nodeId, const char * payload) : mNodeId(nodeId), mPayload(payload) {} + +void PairDeviceCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) +{ + if (mNodeId != deviceId) + { + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, + "Failed to pair non-specified device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + } + else + { + ChipLogProgress(NotSpecified, "Commissioning complete for non-specified device: NodeId: " ChipLogFormatX64, + ChipLogValueX64(deviceId)); + } + return; + } + + if (err == CHIP_NO_ERROR) + { + ChipLogProgress(NotSpecified, "Successfully paired device: NodeId: " ChipLogFormatX64, ChipLogValueX64(mNodeId)); + + admin::DeviceManager::Instance().UpdateLastUsedNodeId(mNodeId); + } + else + { + ChipLogError(NotSpecified, "Failed to pair device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + } + + CommandRegistry::Instance().ResetActiveCommand(); +} + +CHIP_ERROR PairDeviceCommand::RunCommand() +{ + if (admin::DeviceManager::Instance().IsCurrentBridgeDevice(mNodeId)) + { + // print to console + fprintf(stderr, "The specified node ID has been reserved by the Fabric Bridge.\n"); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + ChipLogProgress(NotSpecified, "Running PairDeviceCommand with Node ID: " ChipLogFormatX64 ", Code: %s", + ChipLogValueX64(mNodeId), mPayload); + + admin::PairingManager::Instance().SetPairingDelegate(this); + + return admin::PairingManager::Instance().PairDeviceWithCode(mNodeId, mPayload); +} + +} // namespace commands diff --git a/examples/fabric-sync/shell/PairDeviceCommand.h b/examples/fabric-sync/shell/PairDeviceCommand.h new file mode 100644 index 00000000000000..d917b5103ff597 --- /dev/null +++ b/examples/fabric-sync/shell/PairDeviceCommand.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#pragma once + +#include +#include + +namespace commands { + +class PairDeviceCommand : public Command, public admin::PairingDelegate +{ +public: + PairDeviceCommand(chip::NodeId nodeId, const char * payload); + void OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR err) override; + CHIP_ERROR RunCommand() override; + +private: + chip::NodeId mNodeId; + const char * mPayload; +}; + +} // namespace commands diff --git a/examples/fabric-sync/shell/RemoveBridgeCommand.cpp b/examples/fabric-sync/shell/RemoveBridgeCommand.cpp index 9a33b0b11ba94e..4340a3d286fade 100644 --- a/examples/fabric-sync/shell/RemoveBridgeCommand.cpp +++ b/examples/fabric-sync/shell/RemoveBridgeCommand.cpp @@ -66,7 +66,7 @@ CHIP_ERROR RemoveBridgeCommand::RunCommand() admin::PairingManager::Instance().SetPairingDelegate(this); - return admin::DeviceManager::Instance().UnpairRemoteFabricBridge(); + return admin::PairingManager::Instance().UnpairDevice(bridgeNodeId); } } // namespace commands diff --git a/examples/fabric-sync/shell/RemoveDeviceCommand.cpp b/examples/fabric-sync/shell/RemoveDeviceCommand.cpp index 5e316658d5b303..27c2f3e851e5f2 100644 --- a/examples/fabric-sync/shell/RemoveDeviceCommand.cpp +++ b/examples/fabric-sync/shell/RemoveDeviceCommand.cpp @@ -61,9 +61,9 @@ CHIP_ERROR RemoveDeviceCommand::RunCommand() admin::PairingManager::Instance().SetPairingDelegate(this); - ChipLogProgress(NotSpecified, "Running RemoveDeviceCommand with Node ID: %lu", mNodeId); + ChipLogProgress(NotSpecified, "Running RemoveDeviceCommand with Node ID: " ChipLogFormatX64, ChipLogValueX64(mNodeId)); - return admin::DeviceManager::Instance().UnpairRemoteDevice(mNodeId); + return admin::PairingManager::Instance().UnpairDevice(mNodeId); } } // namespace commands diff --git a/examples/fabric-sync/shell/ShellCommands.cpp b/examples/fabric-sync/shell/ShellCommands.cpp index 4923823481635a..f117e9c7b99274 100644 --- a/examples/fabric-sync/shell/ShellCommands.cpp +++ b/examples/fabric-sync/shell/ShellCommands.cpp @@ -17,6 +17,7 @@ #include "ShellCommands.h" #include "AddBridgeCommand.h" #include "AddDeviceCommand.h" +#include "PairDeviceCommand.h" #include "RemoveBridgeCommand.h" #include "RemoveDeviceCommand.h" #include "SyncDeviceCommand.h" @@ -46,6 +47,7 @@ static CHIP_ERROR PrintAllCommands() streamer_printf(sout, " add-device Pair a device to local fabric. Usage: app add-device node-id setup-pin-code " "device-remote-ip device-remote-port\r\n"); + streamer_printf(sout, " pair-device Pair a device to local fabric. Usage: app pair-device node-id code\r\n"); streamer_printf(sout, " remove-device Remove a device from the local fabric. Usage: app remove-device node-id\r\n"); streamer_printf(sout, " sync-device Sync a device from other ecosystem. Usage: app sync-device endpointid\r\n"); streamer_printf(sout, "\r\n"); @@ -145,6 +147,36 @@ static CHIP_ERROR HandleAddDeviceCommand(int argc, char ** argv) return result; } +static CHIP_ERROR HandlePairDeviceCommand(int argc, char ** argv) +{ + if (argc != 3) + { + fprintf(stderr, "Invalid arguments. Usage: app pair-device node-id code\n"); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + // Check if there is already an active command + if (commands::CommandRegistry::Instance().IsCommandActive()) + { + fprintf(stderr, "Another command is currently active. Please wait until it completes.\n"); + return CHIP_ERROR_BUSY; + } + + // Parse arguments + chip::NodeId nodeId = static_cast(strtoull(argv[1], nullptr, 10)); + const char * setUpCode = argv[2]; + + auto command = std::make_unique(nodeId, setUpCode); + + CHIP_ERROR result = command->RunCommand(); + if (result == CHIP_NO_ERROR) + { + commands::CommandRegistry::Instance().SetActiveCommand(std::move(command)); + } + + return result; +} + static CHIP_ERROR HandleRemoveDeviceCommand(int argc, char ** argv) { if (argc != 2) @@ -227,6 +259,10 @@ static CHIP_ERROR AppPlatformHandler(int argc, char ** argv) { return HandleAddDeviceCommand(argc, argv); } + else if (strcmp(argv[0], "pair-device") == 0) + { + return HandlePairDeviceCommand(argc, argv); + } else if (strcmp(argv[0], "remove-device") == 0) { return HandleRemoveDeviceCommand(argc, argv); diff --git a/examples/fabric-sync/shell/SyncDeviceCommand.cpp b/examples/fabric-sync/shell/SyncDeviceCommand.cpp index 871c8d68feedb7..81c822dfa6b9ee 100644 --- a/examples/fabric-sync/shell/SyncDeviceCommand.cpp +++ b/examples/fabric-sync/shell/SyncDeviceCommand.cpp @@ -53,7 +53,12 @@ void SyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_ERROR usleep(kCommissionPrepareTimeMs * 1000); - admin::DeviceManager::Instance().PairRemoteDevice(nodeId, payloadBuffer); + error = admin::PairingManager::Instance().PairDeviceWithCode(nodeId, payloadBuffer); + if (error != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to sync device: Node ID " ChipLogFormatX64 " with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(nodeId), err.Format()); + } } else { diff --git a/examples/light-switch-app/ameba/README.md b/examples/light-switch-app/ameba/README.md index ea9304fe7ca4a9..9df4fd68612de7 100644 --- a/examples/light-switch-app/ameba/README.md +++ b/examples/light-switch-app/ameba/README.md @@ -26,11 +26,11 @@ The CHIP demo application is supported on - Pull docker image: - $ docker pull ghcr.io/project-chip/chip-build-ameba:90 + $ docker pull ghcr.io/project-chip/chip-build-ameba:93 - Run docker container: - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:90 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:93 - Setup build environment: diff --git a/examples/light-switch-app/ameba/chip_main.cmake b/examples/light-switch-app/ameba/chip_main.cmake index 629c423c0fe5ec..800f51a7040ec9 100755 --- a/examples/light-switch-app/ameba/chip_main.cmake +++ b/examples/light-switch-app/ameba/chip_main.cmake @@ -201,6 +201,7 @@ target_include_directories( ${chip_dir}/zzz_generated/app-common ${chip_dir}/examples/light-switch-app/ameba/main/include ${chip_dir}/examples/platform/ameba + ${chip_dir}/examples/platform/ameba/observer ${chip_dir}/examples/providers ${chip_dir_output}/gen/include ${chip_dir}/src/include/ diff --git a/examples/light-switch-app/ameba/main/chipinterface.cpp b/examples/light-switch-app/ameba/main/chipinterface.cpp index 35d11da6342ba5..84fd4f86e31209 100644 --- a/examples/light-switch-app/ameba/main/chipinterface.cpp +++ b/examples/light-switch-app/ameba/main/chipinterface.cpp @@ -17,6 +17,7 @@ #include +#include "AmebaObserver.h" #include "BindingHandler.h" #include "CHIPDeviceManager.h" #include "DeviceCallbacks.h" @@ -28,6 +29,7 @@ #include #include +#include #include #include #include @@ -103,12 +105,15 @@ static void InitServer(intptr_t context) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); #if CONFIG_ENABLE_AMEBA_CRYPTO ChipLogProgress(DeviceLayer, "platform crypto enabled!"); static chip::AmebaPersistentStorageOperationalKeystore sAmebaPersistentStorageOpKeystore; VerifyOrDie((sAmebaPersistentStorageOpKeystore.Init(initParams.persistentStorageDelegate)) == CHIP_NO_ERROR); initParams.operationalKeystore = &sAmebaPersistentStorageOpKeystore; #endif + static AmebaObserver sAmebaObserver; + initParams.appDelegate = &sAmebaObserver; chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); @@ -124,6 +129,7 @@ static void InitServer(intptr_t context) #if CONFIG_ENABLE_CHIP_SHELL InitBindingHandler(); #endif + chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(&sAmebaObserver); } extern "C" void ChipTest(void) diff --git a/examples/light-switch-app/cc13x4_26x4/src/AppTask.cpp b/examples/light-switch-app/cc13x4_26x4/src/AppTask.cpp index 7dedcac6477629..3e2865b7b4c54b 100644 --- a/examples/light-switch-app/cc13x4_26x4/src/AppTask.cpp +++ b/examples/light-switch-app/cc13x4_26x4/src/AppTask.cpp @@ -24,6 +24,7 @@ #include "FreeRTOS.h" +#include #include #include #include @@ -324,6 +325,7 @@ int AppTask::Init() static DefaultTestEventTriggerDelegate sTestEventTriggerDelegate{ ByteSpan(sTestEventTriggerEnableKey) }; initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); // Initialize info provider sExampleDeviceInfoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); diff --git a/examples/light-switch-app/genio/src/AppTask.cpp b/examples/light-switch-app/genio/src/AppTask.cpp index f820d05ef14b05..ed331c5c1c2fb1 100644 --- a/examples/light-switch-app/genio/src/AppTask.cpp +++ b/examples/light-switch-app/genio/src/AppTask.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -124,6 +125,7 @@ CHIP_ERROR AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // Initialize device attestation config diff --git a/examples/light-switch-app/nrfconnect/main/AppTask.cpp b/examples/light-switch-app/nrfconnect/main/AppTask.cpp index fc1c947150dd95..c10da5aba96f81 100644 --- a/examples/light-switch-app/nrfconnect/main/AppTask.cpp +++ b/examples/light-switch-app/nrfconnect/main/AppTask.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -235,6 +236,7 @@ CHIP_ERROR AppTask::Init() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/examples/light-switch-app/qpg/src/AppTask.cpp b/examples/light-switch-app/qpg/src/AppTask.cpp index 7cb0a41a452aca..2b1a49a51dd8a3 100644 --- a/examples/light-switch-app/qpg/src/AppTask.cpp +++ b/examples/light-switch-app/qpg/src/AppTask.cpp @@ -35,6 +35,7 @@ using namespace ::chip; #include #include #include +#include #include #include #include @@ -203,7 +204,6 @@ CHIP_ERROR AppTask::StartAppTask() void AppTask::InitServer(intptr_t arg) { static chip::CommonCaseDeviceServerInitParams initParams; - (void) initParams.InitializeStaticResourcesBeforeServerInit(); gExampleDeviceInfoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); @@ -220,6 +220,7 @@ void AppTask::InitServer(intptr_t arg) VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(sTestEventTriggerEnableKey)) == CHIP_NO_ERROR); VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sFaultTestEventTriggerHandler) == CHIP_NO_ERROR); (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; chip::Server::GetInstance().Init(initParams); diff --git a/examples/lighting-app/ameba/README.md b/examples/lighting-app/ameba/README.md index e91aec075b50c0..c4fe32b600c0c0 100644 --- a/examples/lighting-app/ameba/README.md +++ b/examples/lighting-app/ameba/README.md @@ -23,11 +23,11 @@ The CHIP demo application is supported on - Pull docker image: - $ docker pull ghcr.io/project-chip/chip-build-ameba:90 + $ docker pull ghcr.io/project-chip/chip-build-ameba:93 - Run docker container: - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:90 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:93 - Setup build environment: diff --git a/examples/lighting-app/ameba/chip_main.cmake b/examples/lighting-app/ameba/chip_main.cmake index 11590553cf327d..f8f1c6b158d967 100755 --- a/examples/lighting-app/ameba/chip_main.cmake +++ b/examples/lighting-app/ameba/chip_main.cmake @@ -196,6 +196,7 @@ target_include_directories( ${chip_dir}/examples/lighting-app/lighting-common/include ${chip_dir}/examples/lighting-app/ameba/main/include ${chip_dir}/examples/platform/ameba + ${chip_dir}/examples/platform/ameba/observer ${chip_dir}/examples/providers ${chip_dir_output}/gen/include ${chip_dir}/src/include/ diff --git a/examples/lighting-app/ameba/main/chipinterface.cpp b/examples/lighting-app/ameba/main/chipinterface.cpp index 76459b728a545b..c98545110e0acb 100644 --- a/examples/lighting-app/ameba/main/chipinterface.cpp +++ b/examples/lighting-app/ameba/main/chipinterface.cpp @@ -17,6 +17,7 @@ #include +#include "AmebaObserver.h" #include "CHIPDeviceManager.h" #include "DeviceCallbacks.h" #include "Globals.h" @@ -30,6 +31,7 @@ #include #include +#include #include #include #include @@ -123,12 +125,15 @@ static void InitServer(intptr_t context) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); #if CONFIG_ENABLE_AMEBA_CRYPTO ChipLogProgress(DeviceLayer, "platform crypto enabled!"); static chip::AmebaPersistentStorageOperationalKeystore sAmebaPersistentStorageOpKeystore; VerifyOrDie((sAmebaPersistentStorageOpKeystore.Init(initParams.persistentStorageDelegate)) == CHIP_NO_ERROR); initParams.operationalKeystore = &sAmebaPersistentStorageOpKeystore; #endif + static AmebaObserver sAmebaObserver; + initParams.appDelegate = &sAmebaObserver; chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); @@ -140,6 +145,7 @@ static void InitServer(intptr_t context) // QR code will be used with CHIP Tool PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); } + chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(&sAmebaObserver); } extern "C" void ChipTest(void) diff --git a/examples/lighting-app/cc13x4_26x4/src/AppTask.cpp b/examples/lighting-app/cc13x4_26x4/src/AppTask.cpp index 91aad59a9d1edd..da48f6545dc2d8 100644 --- a/examples/lighting-app/cc13x4_26x4/src/AppTask.cpp +++ b/examples/lighting-app/cc13x4_26x4/src/AppTask.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include #include @@ -315,6 +316,7 @@ int AppTask::Init() initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); // Initialize info provider sExampleDeviceInfoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); diff --git a/examples/lighting-app/genio/src/AppTask.cpp b/examples/lighting-app/genio/src/AppTask.cpp index d948087833c4dd..b07d4ee3d9a0b2 100644 --- a/examples/lighting-app/genio/src/AppTask.cpp +++ b/examples/lighting-app/genio/src/AppTask.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -324,6 +325,7 @@ CHIP_ERROR AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // Initialize device attestation config diff --git a/examples/lighting-app/infineon/psoc6/src/AppTask.cpp b/examples/lighting-app/infineon/psoc6/src/AppTask.cpp index 43a501ad7edb5c..0615b511888c3a 100644 --- a/examples/lighting-app/infineon/psoc6/src/AppTask.cpp +++ b/examples/lighting-app/infineon/psoc6/src/AppTask.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include /* OTA related includes */ @@ -143,6 +144,7 @@ static void InitServer(intptr_t context) // Init ZCL Data Model static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); diff --git a/examples/lighting-app/mbed/main/AppTask.cpp b/examples/lighting-app/mbed/main/AppTask.cpp index 26403bdb5e5b28..ce4d45a3aa9758 100644 --- a/examples/lighting-app/mbed/main/AppTask.cpp +++ b/examples/lighting-app/mbed/main/AppTask.cpp @@ -20,6 +20,7 @@ #include "LEDWidget.h" #include "LightingManager.h" +#include #include #include #include @@ -116,6 +117,7 @@ int AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); error = Server::GetInstance().Init(initParams); if (error != CHIP_NO_ERROR) diff --git a/examples/lighting-app/nxp/k32w0/main/AppTask.cpp b/examples/lighting-app/nxp/k32w0/main/AppTask.cpp index 2418ab85978eb2..191bfb9d0bf547 100644 --- a/examples/lighting-app/nxp/k32w0/main/AppTask.cpp +++ b/examples/lighting-app/nxp/k32w0/main/AppTask.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -282,6 +283,7 @@ void AppTask::InitServer(intptr_t arg) { static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); auto & infoProvider = chip::DeviceLayer::DeviceInfoProviderImpl::GetDefaultInstance(); infoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); diff --git a/examples/lighting-app/nxp/k32w1/args.gni b/examples/lighting-app/nxp/k32w1/args.gni index 3d026f1fb48e9d..078847b98268de 100644 --- a/examples/lighting-app/nxp/k32w1/args.gni +++ b/examples/lighting-app/nxp/k32w1/args.gni @@ -35,5 +35,7 @@ chip_system_config_provide_statistics = false chip_system_config_use_open_thread_inet_endpoints = true chip_with_lwip = false +nxp_nvm_component = "nvs" + nxp_use_smu2_static = true nxp_use_smu2_dynamic = true diff --git a/examples/lighting-app/nxp/mcxw71/args.gni b/examples/lighting-app/nxp/mcxw71/args.gni index 6be04211091da2..5e8897a0d718a6 100644 --- a/examples/lighting-app/nxp/mcxw71/args.gni +++ b/examples/lighting-app/nxp/mcxw71/args.gni @@ -35,5 +35,7 @@ chip_system_config_provide_statistics = false chip_system_config_use_open_thread_inet_endpoints = true chip_with_lwip = false +nxp_nvm_component = "nvs" + nxp_use_smu2_static = true nxp_use_smu2_dynamic = true diff --git a/examples/lighting-app/stm32/src/STM32WB5/AppTask.cpp b/examples/lighting-app/stm32/src/STM32WB5/AppTask.cpp index 5841f15264bad4..49649144b9666b 100644 --- a/examples/lighting-app/stm32/src/STM32WB5/AppTask.cpp +++ b/examples/lighting-app/stm32/src/STM32WB5/AppTask.cpp @@ -37,6 +37,7 @@ /*Matter includes*/ #include #include +#include #include #include #include @@ -152,6 +153,7 @@ CHIP_ERROR AppTask::Init() // Init ZCL Data Model static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); ReturnErrorOnFailure(mFactoryDataProvider.Init()); SetDeviceInstanceInfoProvider(&mFactoryDataProvider); SetCommissionableDataProvider(&mFactoryDataProvider); diff --git a/examples/lit-icd-app/nrfconnect/main/AppTask.cpp b/examples/lit-icd-app/nrfconnect/main/AppTask.cpp index 2fab2d91f83bb8..642947329579a5 100644 --- a/examples/lit-icd-app/nrfconnect/main/AppTask.cpp +++ b/examples/lit-icd-app/nrfconnect/main/AppTask.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -204,6 +205,7 @@ CHIP_ERROR AppTask::Init() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/examples/lock-app/cc13x4_26x4/src/AppTask.cpp b/examples/lock-app/cc13x4_26x4/src/AppTask.cpp index 43d8f61ef1ab52..fd99c0c0c6990b 100644 --- a/examples/lock-app/cc13x4_26x4/src/AppTask.cpp +++ b/examples/lock-app/cc13x4_26x4/src/AppTask.cpp @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -308,6 +309,7 @@ int AppTask::Init() initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); // Initialize info provider sExampleDeviceInfoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); diff --git a/examples/lock-app/cc32xx/main/AppTask.cpp b/examples/lock-app/cc32xx/main/AppTask.cpp index 28c0675b8c717a..d610325b54a3fe 100644 --- a/examples/lock-app/cc32xx/main/AppTask.cpp +++ b/examples/lock-app/cc32xx/main/AppTask.cpp @@ -38,6 +38,7 @@ #include #include +#include #include #include @@ -151,6 +152,7 @@ int AppTask::Init() PLAT_LOG("Initialize Server"); static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // Initialize device attestation config diff --git a/examples/lock-app/genio/src/AppTask.cpp b/examples/lock-app/genio/src/AppTask.cpp index 1c2f0719790196..fad169f9100abd 100644 --- a/examples/lock-app/genio/src/AppTask.cpp +++ b/examples/lock-app/genio/src/AppTask.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -137,6 +138,7 @@ CHIP_ERROR AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // Initialize device attestation config diff --git a/examples/lock-app/infineon/psoc6/src/AppTask.cpp b/examples/lock-app/infineon/psoc6/src/AppTask.cpp index 54178c21c98f65..65ea49e769f681 100644 --- a/examples/lock-app/infineon/psoc6/src/AppTask.cpp +++ b/examples/lock-app/infineon/psoc6/src/AppTask.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -155,6 +156,7 @@ static void InitServer(intptr_t context) // Init ZCL Data Model static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); diff --git a/examples/lock-app/mbed/main/AppTask.cpp b/examples/lock-app/mbed/main/AppTask.cpp index 2dd5a4463dcf74..bfa4ae73c0b258 100644 --- a/examples/lock-app/mbed/main/AppTask.cpp +++ b/examples/lock-app/mbed/main/AppTask.cpp @@ -20,6 +20,7 @@ #include "BoltLockManager.h" #include +#include #include #include #include @@ -119,6 +120,7 @@ int AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); error = Server::GetInstance().Init(initParams); if (error != CHIP_NO_ERROR) diff --git a/examples/lock-app/nrfconnect/main/AppTask.cpp b/examples/lock-app/nrfconnect/main/AppTask.cpp index 1025a045184aee..a495ca68334d39 100644 --- a/examples/lock-app/nrfconnect/main/AppTask.cpp +++ b/examples/lock-app/nrfconnect/main/AppTask.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -229,6 +230,7 @@ CHIP_ERROR AppTask::Init() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp index 5880a6e07c784b..14e7128791b5db 100644 --- a/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp +++ b/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -191,6 +192,7 @@ void AppTask::InitServer(intptr_t arg) { static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); auto & infoProvider = chip::DeviceLayer::DeviceInfoProviderImpl::GetDefaultInstance(); infoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); diff --git a/examples/lock-app/qpg/src/AppTask.cpp b/examples/lock-app/qpg/src/AppTask.cpp index 8ae517dce2b7ad..74f6546f12ba04 100644 --- a/examples/lock-app/qpg/src/AppTask.cpp +++ b/examples/lock-app/qpg/src/AppTask.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -202,6 +203,7 @@ void AppTask::InitServer(intptr_t arg) { static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); gExampleDeviceInfoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); @@ -218,6 +220,7 @@ void AppTask::InitServer(intptr_t arg) VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(sTestEventTriggerEnableKey)) == CHIP_NO_ERROR); VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sFaultTestEventTriggerHandler) == CHIP_NO_ERROR); (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; chip::Server::GetInstance().Init(initParams); diff --git a/examples/log-source-app/linux/main.cpp b/examples/log-source-app/linux/main.cpp index d39e4431e86525..fc46923f682143 100644 --- a/examples/log-source-app/linux/main.cpp +++ b/examples/log-source-app/linux/main.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -105,6 +106,7 @@ int main(int argc, char * argv[]) chip::DeviceLayer::ConfigurationMgr().LogDeviceConfig(); static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // Initialize device attestation config diff --git a/examples/ota-requestor-app/ameba/README.md b/examples/ota-requestor-app/ameba/README.md index e748f41dc9b090..c97609b7eb5070 100644 --- a/examples/ota-requestor-app/ameba/README.md +++ b/examples/ota-requestor-app/ameba/README.md @@ -6,11 +6,11 @@ A prototype application that demonstrates OTA Requestor capabilities. - Pull docker image: - $ docker pull ghcr.io/project-chip/chip-build-ameba:90 + $ docker pull ghcr.io/project-chip/chip-build-ameba:93 - Run docker container: - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:90 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:93 - Setup build environment: diff --git a/examples/ota-requestor-app/ameba/chip_main.cmake b/examples/ota-requestor-app/ameba/chip_main.cmake index 28b2fb5d20431d..bc9b41c8fbe2d9 100644 --- a/examples/ota-requestor-app/ameba/chip_main.cmake +++ b/examples/ota-requestor-app/ameba/chip_main.cmake @@ -62,6 +62,7 @@ target_include_directories( ${chip_dir}/src/app/clusters/ota-requestor ${chip_dir}/examples/ota-requestor-app/ameba/main/include ${chip_dir}/examples/platform/ameba + ${chip_dir}/examples/platform/ameba/observer ${chip_dir}/examples/providers ${sdk_root}/component/soc/realtek/amebad/fwlib/include ) diff --git a/examples/ota-requestor-app/ameba/main/chipinterface.cpp b/examples/ota-requestor-app/ameba/main/chipinterface.cpp index dfac5c97f2ecf6..6d0af83d5c8daf 100644 --- a/examples/ota-requestor-app/ameba/main/chipinterface.cpp +++ b/examples/ota-requestor-app/ameba/main/chipinterface.cpp @@ -17,6 +17,7 @@ #include +#include "AmebaObserver.h" #include "CHIPDeviceManager.h" #include "DeviceCallbacks.h" #include "chip_porting.h" @@ -76,11 +77,14 @@ static void InitServer(intptr_t context) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + static AmebaObserver sAmebaObserver; + initParams.appDelegate = &sAmebaObserver; chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); NetWorkCommissioningInstInit(); + chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(&sAmebaObserver); } extern "C" void ChipTest(void) diff --git a/examples/ota-requestor-app/genio/src/AppTask.cpp b/examples/ota-requestor-app/genio/src/AppTask.cpp index ff78e703e4be81..424d7b20cb0694 100644 --- a/examples/ota-requestor-app/genio/src/AppTask.cpp +++ b/examples/ota-requestor-app/genio/src/AppTask.cpp @@ -18,6 +18,7 @@ */ #include #include +#include #include #include #include @@ -107,6 +108,7 @@ CHIP_ERROR AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // We only have network commissioning on endpoint 0. diff --git a/examples/ota-requestor-app/mbed/main/AppTask.cpp b/examples/ota-requestor-app/mbed/main/AppTask.cpp index 0fa7df26f8d19c..90436d57296acd 100644 --- a/examples/ota-requestor-app/mbed/main/AppTask.cpp +++ b/examples/ota-requestor-app/mbed/main/AppTask.cpp @@ -19,6 +19,7 @@ #include "AppTask.h" #include +#include #include #include #include @@ -106,6 +107,7 @@ int AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); error = Server::GetInstance().Init(initParams); if (error != CHIP_NO_ERROR) diff --git a/examples/pigweed-app/ameba/README.md b/examples/pigweed-app/ameba/README.md index 136a37a14caf41..1af7f586291b52 100644 --- a/examples/pigweed-app/ameba/README.md +++ b/examples/pigweed-app/ameba/README.md @@ -31,11 +31,11 @@ following features are available: - Pull docker image: - $ docker pull ghcr.io/project-chip/chip-build-ameba:90 + $ docker pull ghcr.io/project-chip/chip-build-ameba:93 - Run docker container: - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:90 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:93 - Setup build environment: diff --git a/examples/all-clusters-app/ameba/main/include/AmebaObserver.h b/examples/platform/ameba/observer/AmebaObserver.h similarity index 100% rename from examples/all-clusters-app/ameba/main/include/AmebaObserver.h rename to examples/platform/ameba/observer/AmebaObserver.h diff --git a/examples/platform/asr/init_Matter.cpp b/examples/platform/asr/init_Matter.cpp index a80fea5b4ea1bc..8280618c2668e1 100644 --- a/examples/platform/asr/init_Matter.cpp +++ b/examples/platform/asr/init_Matter.cpp @@ -18,6 +18,7 @@ #include "AppConfig.h" #include +#include #include #include #include @@ -100,6 +101,7 @@ CHIP_ERROR MatterInitializer::Init_Matter_Server(void) chip::DeviceLayer::PlatformMgr().LockChipStack(); static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); chip::Server::GetInstance().Init(initParams); diff --git a/examples/platform/beken/common/BekenAppServer.cpp b/examples/platform/beken/common/BekenAppServer.cpp index 50f68cf441b05f..7db986538189a7 100644 --- a/examples/platform/beken/common/BekenAppServer.cpp +++ b/examples/platform/beken/common/BekenAppServer.cpp @@ -19,6 +19,7 @@ #include "BekenAppServer.h" #include "CHIPDeviceManager.h" #include +#include #include #include #include @@ -38,6 +39,7 @@ void BekenAppServer::Init(AppDelegate * sAppDelegate) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); if (sAppDelegate != nullptr) { initParams.appDelegate = sAppDelegate; diff --git a/examples/platform/bouffalolab/common/plat/platform.cpp b/examples/platform/bouffalolab/common/plat/platform.cpp index 6a91567ab9b803..723df8fa0d59de 100644 --- a/examples/platform/bouffalolab/common/plat/platform.cpp +++ b/examples/platform/bouffalolab/common/plat/platform.cpp @@ -17,6 +17,7 @@ */ #include #include +#include #include #include #include @@ -245,6 +246,7 @@ CHIP_ERROR PlatformManagerImpl::PlatformInit(void) static CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); #if CHIP_DEVICE_CONFIG_ENABLE_THREAD chip::Inet::EndPointStateOpenThread::OpenThreadEndpointInitParam nativeParams; diff --git a/examples/platform/esp32/common/Esp32AppServer.cpp b/examples/platform/esp32/common/Esp32AppServer.cpp index 8740f39cdbc080..e05817bfe0676d 100644 --- a/examples/platform/esp32/common/Esp32AppServer.cpp +++ b/examples/platform/esp32/common/Esp32AppServer.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -151,6 +152,7 @@ void Esp32AppServer::Init(AppDelegate * sAppDelegate) initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; #endif // CONFIG_TEST_EVENT_TRIGGER_ENABLED && CONFIG_ENABLE_OTA_REQUESTOR (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); if (sAppDelegate != nullptr) { initParams.appDelegate = sAppDelegate; diff --git a/examples/platform/infineon/cyw30739/matter_config.cpp b/examples/platform/infineon/cyw30739/matter_config.cpp index c30d55e55bc623..42bc9f3d1dade5 100644 --- a/examples/platform/infineon/cyw30739/matter_config.cpp +++ b/examples/platform/infineon/cyw30739/matter_config.cpp @@ -37,6 +37,7 @@ #include "wiced_hal_i2c.h" #endif #include +#include #include #include #include @@ -216,6 +217,7 @@ void CYW30739MatterConfig::InitApp(void) // Create initParams with SDK example defaults here static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; sExampleDeviceInfoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); SetDeviceInfoProvider(&sExampleDeviceInfoProvider); diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp index e3b68e319e634e..65763dc12d3475 100644 --- a/examples/platform/linux/AppMain.cpp +++ b/examples/platform/linux/AppMain.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -32,8 +33,6 @@ #include #include -#include -#include #include #include @@ -50,10 +49,6 @@ #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE #include "CommissionerMain.h" #include -#include -#include -#include -#include #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE #if defined(ENABLE_CHIP_SHELL) @@ -532,6 +527,7 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl) static chip::CommonCaseDeviceServerInitParams initParams; VerifyOrDie(initParams.InitializeStaticResourcesBeforeServerInit() == CHIP_NO_ERROR); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); #if defined(ENABLE_CHIP_SHELL) Engine::Root().Init(); diff --git a/examples/platform/linux/AppMain.h b/examples/platform/linux/AppMain.h index 94bf4d3e609da1..dc4a5d5be200f3 100644 --- a/examples/platform/linux/AppMain.h +++ b/examples/platform/linux/AppMain.h @@ -19,8 +19,8 @@ #pragma once #include -#include #include +#include #include #include #include @@ -88,19 +88,6 @@ class DefaultAppMainLoopImplementation : public AppMainLoopImplementation */ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl = nullptr); -#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE - -using chip::Controller::DeviceCommissioner; -using chip::Transport::PeerAddress; - -CHIP_ERROR CommissionerPairOnNetwork(uint32_t pincode, uint16_t disc, PeerAddress address); -CHIP_ERROR CommissionerPairUDC(uint32_t pincode, size_t index); - -DeviceCommissioner * GetDeviceCommissioner(); -CommissionerDiscoveryController * GetCommissionerDiscoveryController(); - -#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE - // For extra init calls, the function will be called right before running Matter main loop. void ApplicationInit(); diff --git a/examples/platform/linux/BUILD.gn b/examples/platform/linux/BUILD.gn index 30583ce7d0e399..1d4f191cb8263e 100644 --- a/examples/platform/linux/BUILD.gn +++ b/examples/platform/linux/BUILD.gn @@ -95,8 +95,7 @@ source_set("app-main") { ":energy-reporting-test-event-trigger", ":smco-test-event-trigger", ":water-heater-management-test-event-trigger", - "${chip_root}/src/controller:controller", - "${chip_root}/src/controller:gen_check_chip_controller_headers", + "${chip_root}/src/app/codegen-data-model-provider:instance-header", "${chip_root}/src/lib", "${chip_root}/src/platform/logging:default", ] @@ -163,10 +162,12 @@ source_set("commissioner-main") { public_deps = [ "${chip_root}/src/controller:controller", - "${chip_root}/src/controller:gen_check_chip_controller_headers", "${chip_root}/src/lib", ] - deps = [ "${chip_root}/src/app/server" ] + deps = [ + "${chip_root}/src/app/codegen-data-model-provider:instance-header", + "${chip_root}/src/app/server", + ] if (chip_enable_transport_trace) { deps += [ "${chip_root}/examples/common/tracing:trace_handlers" ] diff --git a/examples/platform/linux/CommissionerMain.cpp b/examples/platform/linux/CommissionerMain.cpp index e8da5d70b25e8a..54ad104c012e4b 100644 --- a/examples/platform/linux/CommissionerMain.cpp +++ b/examples/platform/linux/CommissionerMain.cpp @@ -24,6 +24,7 @@ #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE #include +#include #include #include #include @@ -134,6 +135,7 @@ CHIP_ERROR InitCommissioner(uint16_t commissionerPort, uint16_t udcListenPort, F factoryParams.fabricIndependentStorage = &gServerStorage; factoryParams.fabricTable = &Server::GetInstance().GetFabricTable(); factoryParams.sessionKeystore = &gSessionKeystore; + factoryParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); gGroupDataProvider.SetStorageDelegate(&gServerStorage); gGroupDataProvider.SetSessionKeystore(factoryParams.sessionKeystore); @@ -457,4 +459,14 @@ CommissionerDiscoveryController * GetCommissionerDiscoveryController() return &gCommissionerDiscoveryController; } +SessionKeystore * GetSessionKeystore() +{ + return &gSessionKeystore; +} + +PersistentStorageDelegate * GetPersistentStorageDelegate() +{ + return &gServerStorage; +} + #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE diff --git a/examples/platform/linux/CommissionerMain.h b/examples/platform/linux/CommissionerMain.h index e241d436c4e71f..106e94b0edcb31 100644 --- a/examples/platform/linux/CommissionerMain.h +++ b/examples/platform/linux/CommissionerMain.h @@ -28,7 +28,9 @@ #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE +using chip::PersistentStorageDelegate; using chip::Controller::DeviceCommissioner; +using chip::Crypto::SessionKeystore; using chip::Transport::PeerAddress; CHIP_ERROR CommissionerPairOnNetwork(uint32_t pincode, uint16_t disc, PeerAddress address); @@ -39,5 +41,7 @@ void ShutdownCommissioner(); DeviceCommissioner * GetDeviceCommissioner(); CommissionerDiscoveryController * GetCommissionerDiscoveryController(); +SessionKeystore * GetSessionKeystore(); +PersistentStorageDelegate * GetPersistentStorageDelegate(); #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE diff --git a/examples/platform/linux/ControllerShellCommands.cpp b/examples/platform/linux/ControllerShellCommands.cpp index b2bc8af2d8f92b..b33beedf3ca837 100644 --- a/examples/platform/linux/ControllerShellCommands.cpp +++ b/examples/platform/linux/ControllerShellCommands.cpp @@ -19,9 +19,9 @@ * @file Contains shell commands for for performing discovery (eg. of commissionable nodes) related to commissioning. */ -#include -#include -#include +#include "ControllerShellCommands.h" +#include "CommissionerMain.h" + #include #include #include @@ -33,6 +33,8 @@ #include #include +#include + namespace chip { namespace Shell { diff --git a/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp b/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp index 81907d21634318..00ccbb9ea31269 100644 --- a/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp +++ b/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -185,6 +186,7 @@ void chip::NXP::App::AppTaskBase::InitServer(intptr_t arg) initParams.operationalKeystore = chip::NXP::App::OperationalKeystore::GetInstance(); #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); #if CONFIG_NET_L2_OPENTHREAD // Init ZCL Data Model and start server diff --git a/examples/platform/nxp/se05x/linux/AppMain.cpp b/examples/platform/nxp/se05x/linux/AppMain.cpp index bd13e249683fcb..5baf36112b31b2 100644 --- a/examples/platform/nxp/se05x/linux/AppMain.cpp +++ b/examples/platform/nxp/se05x/linux/AppMain.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -291,6 +292,7 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl) static chip::CommonCaseDeviceServerInitParams initParams; VerifyOrDie(initParams.InitializeStaticResourcesBeforeServerInit() == CHIP_NO_ERROR); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); #if defined(ENABLE_CHIP_SHELL) Engine::Root().Init(); diff --git a/examples/platform/openiotsdk/app/openiotsdk_platform.cpp b/examples/platform/openiotsdk/app/openiotsdk_platform.cpp index 56bb7c24902bbc..705f35e86b2b29 100644 --- a/examples/platform/openiotsdk/app/openiotsdk_platform.cpp +++ b/examples/platform/openiotsdk/app/openiotsdk_platform.cpp @@ -42,6 +42,7 @@ #include #ifdef USE_CHIP_DATA_MODEL +#include #include #include #include @@ -274,6 +275,7 @@ int openiotsdk_chip_run(void) ChipLogError(NotSpecified, "Initialize static resources before server init failed: %s", err.AsString()); return EXIT_FAILURE; } + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); initParams.operationalServicePort = CHIP_PORT; initParams.userDirectedCommissioningPort = CHIP_UDC_PORT; diff --git a/examples/platform/silabs/MatterConfig.cpp b/examples/platform/silabs/MatterConfig.cpp index 8c0488f74c1bd0..c382a3ab1aa98f 100644 --- a/examples/platform/silabs/MatterConfig.cpp +++ b/examples/platform/silabs/MatterConfig.cpp @@ -56,6 +56,7 @@ static chip::DeviceLayer::Internal::Efr32PsaOperationalKeystore gOperationalKeys #include #include #include +#include #ifdef SL_MATTER_TEST_EVENT_TRIGGER_ENABLED #include "SilabsTestEventTriggerDelegate.h" // nogncheck @@ -275,6 +276,7 @@ CHIP_ERROR SilabsMatterConfig::InitMatter(const char * appName) // Initialize the remaining (not overridden) providers to the SDK example defaults (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); #if CHIP_ENABLE_OPENTHREAD // Set up OpenThread configuration when OpenThread is included diff --git a/examples/platform/silabs/MatterShell.cpp b/examples/platform/silabs/MatterShell.cpp index 6088eeb2ca9404..38f97385bbaef4 100644 --- a/examples/platform/silabs/MatterShell.cpp +++ b/examples/platform/silabs/MatterShell.cpp @@ -114,7 +114,7 @@ void cmdSilabsInit() void startShellTask() { int status = chip::Shell::Engine::Root().Init(); - assert(status == 0); + VerifyOrDie(status == 0); // For now also register commands from shell_common (shell app). // TODO move at least OTCLI to default commands in lib/shell/commands diff --git a/examples/platform/silabs/SiWx917/BUILD.gn b/examples/platform/silabs/SiWx917/BUILD.gn index 2d6d3574ea3506..02769a993c3087 100644 --- a/examples/platform/silabs/SiWx917/BUILD.gn +++ b/examples/platform/silabs/SiWx917/BUILD.gn @@ -189,6 +189,7 @@ source_set("siwx917-common") { public_deps += [ "${chip_root}/examples/providers:device_info_provider", + "${chip_root}/src/app/codegen-data-model-provider:instance-header", "${chip_root}/src/lib", "${chip_root}/src/setup_payload", ] diff --git a/examples/platform/silabs/efr32/BUILD.gn b/examples/platform/silabs/efr32/BUILD.gn index e0e7b45070d2fc..7b9dccf7ccaa06 100644 --- a/examples/platform/silabs/efr32/BUILD.gn +++ b/examples/platform/silabs/efr32/BUILD.gn @@ -214,6 +214,7 @@ source_set("efr32-common") { public_deps += [ "${chip_root}/examples/providers:device_info_provider", + "${chip_root}/src/app/codegen-data-model-provider:instance-header", "${chip_root}/src/app/server", "${chip_root}/src/lib", "${chip_root}/src/setup_payload", diff --git a/examples/platform/telink/common.cmake b/examples/platform/telink/common.cmake index 80050c81b3b641..b8da9a0dc876c8 100644 --- a/examples/platform/telink/common.cmake +++ b/examples/platform/telink/common.cmake @@ -72,7 +72,7 @@ if(NOT EXISTS "${BOOT_CONF_OVERLAY_FILE}") message(FATAL_ERROR "${BOOT_CONF_OVERLAY_FILE} doesn't exist") endif() -if(${CONFIG_USB_TELINK_B9X} MATCHES y) +if((${CONFIG_USB_TELINK_B9X} MATCHES y) OR (${CONFIG_USB_TELINK_TLX} MATCHES y)) set(BOOT_USB_CONF_OVERLAY_FILE "${CHIP_ROOT}/config/telink/app/bootloader_usb.conf") if(NOT EXISTS "${BOOT_USB_CONF_OVERLAY_FILE}") message(FATAL_ERROR "${BOOT_USB_CONF_OVERLAY_FILE} doesn't exist") diff --git a/examples/platform/telink/common/src/AppTaskCommon.cpp b/examples/platform/telink/common/src/AppTaskCommon.cpp index de5faa974a4847..479e746a4aac62 100644 --- a/examples/platform/telink/common/src/AppTaskCommon.cpp +++ b/examples/platform/telink/common/src/AppTaskCommon.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -301,6 +302,7 @@ CHIP_ERROR AppTaskCommon::InitCommonParts(void) VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sOtaTestEventTriggerHandler) == CHIP_NO_ERROR); #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.appDelegate = &sCallbacks; initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); diff --git a/examples/platform/telink/project_include/OpenThreadConfig.h b/examples/platform/telink/project_include/OpenThreadConfig.h index eabe238820ae7f..0e23617e28e21b 100644 --- a/examples/platform/telink/project_include/OpenThreadConfig.h +++ b/examples/platform/telink/project_include/OpenThreadConfig.h @@ -27,12 +27,17 @@ /* Number of message buffers reduced to save RAM */ #undef OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS -#if CONFIG_PM +#if CONFIG_PM || CONFIG_SOC_RISCV_TELINK_TL321X #define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 22 #else #define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 44 #endif +#if CONFIG_SOC_RISCV_TELINK_TL321X +#undef OPENTHREAD_CONFIG_MLE_MAX_CHILDREN +#define OPENTHREAD_CONFIG_MLE_MAX_CHILDREN 5 +#endif + #define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_DEBUG_UART #undef OPENTHREAD_CONFIG_LOG_LEVEL diff --git a/examples/pump-app/cc13x4_26x4/main/AppTask.cpp b/examples/pump-app/cc13x4_26x4/main/AppTask.cpp index 0a7d6a26003221..bb5e212eeee511 100644 --- a/examples/pump-app/cc13x4_26x4/main/AppTask.cpp +++ b/examples/pump-app/cc13x4_26x4/main/AppTask.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -309,6 +310,7 @@ int AppTask::Init() initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); diff --git a/examples/pump-app/nrfconnect/main/AppTask.cpp b/examples/pump-app/nrfconnect/main/AppTask.cpp index d5f4c6dc760e0e..f8939268f3d111 100644 --- a/examples/pump-app/nrfconnect/main/AppTask.cpp +++ b/examples/pump-app/nrfconnect/main/AppTask.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -205,6 +206,7 @@ CHIP_ERROR AppTask::Init() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/examples/pump-controller-app/cc13x4_26x4/main/AppTask.cpp b/examples/pump-controller-app/cc13x4_26x4/main/AppTask.cpp index ac7eb545a18f0c..0a8de126a18965 100644 --- a/examples/pump-controller-app/cc13x4_26x4/main/AppTask.cpp +++ b/examples/pump-controller-app/cc13x4_26x4/main/AppTask.cpp @@ -38,6 +38,7 @@ #endif #include #include +#include #include #include #include @@ -301,6 +302,7 @@ int AppTask::Init() initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); ret = PlatformMgr().StartEventLoopTask(); diff --git a/examples/pump-controller-app/nrfconnect/main/AppTask.cpp b/examples/pump-controller-app/nrfconnect/main/AppTask.cpp index ca79a41160a9d2..eb4d194d2f14b6 100644 --- a/examples/pump-controller-app/nrfconnect/main/AppTask.cpp +++ b/examples/pump-controller-app/nrfconnect/main/AppTask.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -190,6 +191,7 @@ CHIP_ERROR AppTask::Init() VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(sTestEventTriggerEnableKey)) == CHIP_NO_ERROR); VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sOtaTestEventTriggerHandler) == CHIP_NO_ERROR); (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter b/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter index 49f9672046088a..4cafac39256b78 100644 --- a/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter +++ b/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter @@ -1955,8 +1955,8 @@ endpoint 2 { server cluster TemperatureControl { ram attribute temperatureSetpoint; - ram attribute minTemperature; - ram attribute maxTemperature; + ram attribute minTemperature default = -18; + ram attribute maxTemperature default = -15; ram attribute step; callback attribute generatedCommandList; callback attribute acceptedCommandList; @@ -1985,8 +1985,8 @@ endpoint 3 { server cluster TemperatureControl { ram attribute temperatureSetpoint; - ram attribute minTemperature; - ram attribute maxTemperature; + ram attribute minTemperature default = 0; + ram attribute maxTemperature default = 4; ram attribute step; callback attribute generatedCommandList; callback attribute acceptedCommandList; diff --git a/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.zap b/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.zap index 3a6bcd833161f6..31351d35efe49b 100644 --- a/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.zap +++ b/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.zap @@ -3770,7 +3770,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "-18", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3786,7 +3786,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "-15", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -4119,7 +4119,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -4135,7 +4135,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "4", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter b/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter index b4386fe9ef77ac..234974cf1d83aa 100644 --- a/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter +++ b/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter @@ -1863,8 +1863,8 @@ endpoint 2 { server cluster TemperatureControl { ram attribute temperatureSetpoint; - ram attribute minTemperature; - ram attribute maxTemperature; + ram attribute minTemperature default = -18; + ram attribute maxTemperature default = -15; ram attribute step; callback attribute generatedCommandList; callback attribute acceptedCommandList; @@ -1893,8 +1893,8 @@ endpoint 3 { server cluster TemperatureControl { ram attribute temperatureSetpoint; - ram attribute minTemperature; - ram attribute maxTemperature; + ram attribute minTemperature default = 0; + ram attribute maxTemperature default = 4; ram attribute step; callback attribute generatedCommandList; callback attribute acceptedCommandList; diff --git a/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.zap b/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.zap index addfd6f5198818..34ba99ff801652 100644 --- a/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.zap +++ b/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.zap @@ -3675,7 +3675,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "-18", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3691,7 +3691,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "-15", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -4024,7 +4024,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -4040,7 +4040,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "4", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/refrigerator-app/silabs/src/RefrigeratorManager.cpp b/examples/refrigerator-app/silabs/src/RefrigeratorManager.cpp index 09ab827e9d0828..3edb405a765a37 100644 --- a/examples/refrigerator-app/silabs/src/RefrigeratorManager.cpp +++ b/examples/refrigerator-app/silabs/src/RefrigeratorManager.cpp @@ -102,7 +102,6 @@ void RefrigeratorManager::TempCtrlAttributeChangeHandler(EndpointId endpointId, case TempCtrlAttr::TemperatureSetpoint::Id: { int16_t temperatureSetpoint = ConvertToPrintableTemp(static_cast(*value)); mTemperatureSetpoint = temperatureSetpoint; - TempCtrlAttr::TemperatureSetpoint::Set(endpointId, temperatureSetpoint); } break; default: { diff --git a/examples/shell/cc13x4_26x4/main/AppTask.cpp b/examples/shell/cc13x4_26x4/main/AppTask.cpp index 3f5ff1e659126c..cc6122cef027bc 100644 --- a/examples/shell/cc13x4_26x4/main/AppTask.cpp +++ b/examples/shell/cc13x4_26x4/main/AppTask.cpp @@ -22,6 +22,7 @@ #include "FreeRTOS.h" +#include #include #include #include @@ -161,6 +162,7 @@ CHIP_ERROR AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); ret = PlatformMgr().StartEventLoopTask(); diff --git a/examples/shell/shell_common/cmd_server.cpp b/examples/shell/shell_common/cmd_server.cpp index 6c79aae789b541..80884b9c042233 100644 --- a/examples/shell/shell_common/cmd_server.cpp +++ b/examples/shell/shell_common/cmd_server.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -58,6 +59,7 @@ static CHIP_ERROR CmdAppServerStart(int argc, char ** argv) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); initParams.operationalServicePort = sServerPortOperational; initParams.userDirectedCommissioningPort = sServerPortCommissioning; diff --git a/examples/thermostat/genio/src/AppTask.cpp b/examples/thermostat/genio/src/AppTask.cpp index ac419e01f51b9b..3733b7f45989d2 100644 --- a/examples/thermostat/genio/src/AppTask.cpp +++ b/examples/thermostat/genio/src/AppTask.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -123,6 +124,7 @@ CHIP_ERROR AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // Initialize device attestation config diff --git a/examples/thermostat/qpg/src/AppTask.cpp b/examples/thermostat/qpg/src/AppTask.cpp index 306661766a4af4..f91db8b689919c 100644 --- a/examples/thermostat/qpg/src/AppTask.cpp +++ b/examples/thermostat/qpg/src/AppTask.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -173,6 +174,7 @@ void AppTask::InitServer(intptr_t arg) { static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); gExampleDeviceInfoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommonCaseDeviceServerInitParamsProvider.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommonCaseDeviceServerInitParamsProvider.h index d510a0ec48db2b..93b4edc783e431 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommonCaseDeviceServerInitParamsProvider.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommonCaseDeviceServerInitParamsProvider.h @@ -17,6 +17,8 @@ #include "core/Types.h" +#include + #ifndef MCCommonCaseDeviceServerInitParamsProvider_h #define MCCommonCaseDeviceServerInitParamsProvider_h @@ -35,6 +37,7 @@ class MCCommonCaseDeviceServerInitParamsProvider : public matter::casting::suppo CHIP_ERROR err = serverInitParams.InitializeStaticResourcesBeforeServerInit(); VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogError(AppServer, "Initialization of ServerInitParams failed %" CHIP_ERROR_FORMAT, err.Format())); + serverInitParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); return &serverInitParams; } }; diff --git a/examples/tv-casting-app/linux/main.cpp b/examples/tv-casting-app/linux/main.cpp index 0dde8a2f0d03eb..3a41f15d531c30 100644 --- a/examples/tv-casting-app/linux/main.cpp +++ b/examples/tv-casting-app/linux/main.cpp @@ -31,6 +31,7 @@ #include "LinuxCommissionableDataProvider.h" #include "Options.h" +#include #include #include #include @@ -140,6 +141,7 @@ int main(int argc, char * argv[]) // Enter commissioning mode, open commissioning window static chip::CommonCaseDeviceServerInitParams initParams; VerifyOrDie(CHIP_NO_ERROR == initParams.InitializeStaticResourcesBeforeServerInit()); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); VerifyOrDie(CHIP_NO_ERROR == chip::Server::GetInstance().Init(initParams)); if (argc > 1) diff --git a/examples/tv-casting-app/linux/simple-app.cpp b/examples/tv-casting-app/linux/simple-app.cpp index 41f3391da73e78..5526d6a3f6df07 100644 --- a/examples/tv-casting-app/linux/simple-app.cpp +++ b/examples/tv-casting-app/linux/simple-app.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -83,6 +84,7 @@ class CommonCaseDeviceServerInitParamsProvider : public ServerInitParamsProvider CHIP_ERROR err = serverInitParams.InitializeStaticResourcesBeforeServerInit(); VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogError(AppServer, "Initialization of ServerInitParams failed %" CHIP_ERROR_FORMAT, err.Format())); + serverInitParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); return &serverInitParams; } }; diff --git a/examples/window-app/nrfconnect/main/AppTask.cpp b/examples/window-app/nrfconnect/main/AppTask.cpp index 5f971b67f9f9bf..21438b76e9661b 100644 --- a/examples/window-app/nrfconnect/main/AppTask.cpp +++ b/examples/window-app/nrfconnect/main/AppTask.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -208,6 +209,7 @@ CHIP_ERROR AppTask::Init() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/integrations/cloudbuild/chef.yaml b/integrations/cloudbuild/chef.yaml index 1eafb85580a072..238b47b0fc5fb2 100644 --- a/integrations/cloudbuild/chef.yaml +++ b/integrations/cloudbuild/chef.yaml @@ -1,5 +1,5 @@ steps: - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:93" entrypoint: "bash" args: - "-c" @@ -7,7 +7,7 @@ steps: git config --global --add safe.directory "*" python scripts/checkout_submodules.py --shallow --recursive --platform esp32 nrfconnect silabs linux android id: Submodules - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:93" # NOTE: silabs boostrap is NOT done with the rest as it requests a conflicting # jinja2 version (asks for 3.1.3 when constraints.txt asks for 3.0.3) env: @@ -23,7 +23,7 @@ steps: - name: pwenv path: /pwenv timeout: 900s - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:93" env: - PW_ENVIRONMENT_ROOT=/pwenv args: @@ -38,7 +38,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:93" env: - PW_ENVIRONMENT_ROOT=/pwenv args: diff --git a/integrations/cloudbuild/smoke-test.yaml b/integrations/cloudbuild/smoke-test.yaml index f1ca12766f0d29..41a221d048ea06 100644 --- a/integrations/cloudbuild/smoke-test.yaml +++ b/integrations/cloudbuild/smoke-test.yaml @@ -1,5 +1,5 @@ steps: - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:93" entrypoint: "bash" args: - "-c" @@ -7,7 +7,7 @@ steps: git config --global --add safe.directory "*" python scripts/checkout_submodules.py --shallow --recursive --platform esp32 nrfconnect silabs linux android id: Submodules - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:93" # NOTE: silabs boostrap is NOT done with the rest as it requests a conflicting # jinja2 version (asks for 3.1.3 when constraints.txt asks for 3.0.3) env: @@ -24,7 +24,7 @@ steps: path: /pwenv timeout: 900s - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:93" id: ESP32 env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -45,7 +45,7 @@ steps: volumes: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:93" id: NRFConnect env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -66,7 +66,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:93" id: EFR32 env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -88,7 +88,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:93" id: Linux env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -141,7 +141,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:93" id: Android env: - PW_ENVIRONMENT_ROOT=/pwenv diff --git a/integrations/docker/images/base/chip-build/version b/integrations/docker/images/base/chip-build/version index 2546ff1921d2dc..29c26fda8e1678 100644 --- a/integrations/docker/images/base/chip-build/version +++ b/integrations/docker/images/base/chip-build/version @@ -1 +1 @@ -91 : [Ameba] Update matter timers and add more examples +93 : [Telink] Update Docker image (Zephyr update) diff --git a/integrations/docker/images/stage-2/chip-build-telink/Dockerfile b/integrations/docker/images/stage-2/chip-build-telink/Dockerfile index 2b84323d445955..e028e0b9f64142 100644 --- a/integrations/docker/images/stage-2/chip-build-telink/Dockerfile +++ b/integrations/docker/images/stage-2/chip-build-telink/Dockerfile @@ -18,7 +18,7 @@ RUN set -x \ && : # last line # Setup Zephyr -ARG ZEPHYR_REVISION=f762f1a1027284e63e338e6d83deeade62f355b0 +ARG ZEPHYR_REVISION=8b29ee6b118ebe6eeec3224dbe343474e11403d8 WORKDIR /opt/telink/zephyrproject RUN set -x \ && python3 -m pip install --break-system-packages -U --no-cache-dir west \ diff --git a/pigweed.json b/pigweed.json new file mode 100644 index 00000000000000..aef11e7a516f4e --- /dev/null +++ b/pigweed.json @@ -0,0 +1,7 @@ +{ + "pw": { + "pw_cli_analytics": { + "enabled": false + } + } +} diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index 0f80756ec49208..0bb25ef9a06b75 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -770,6 +770,7 @@ def BuildTelinkTarget(): TargetPart('tlsr9528a_retention', board=TelinkBoard.TLSR9528A_RETENTION), TargetPart('tlsr9258a', board=TelinkBoard.TLSR9258A), TargetPart('tlsr9258a_retention', board=TelinkBoard.TLSR9258A_RETENTION), + TargetPart('tl3218x', board=TelinkBoard.TL3218X), ]) target.AppendFixedTargets([ diff --git a/scripts/build/builders/telink.py b/scripts/build/builders/telink.py index a4943007161f53..bf2bb1900a5842 100644 --- a/scripts/build/builders/telink.py +++ b/scripts/build/builders/telink.py @@ -121,6 +121,7 @@ class TelinkBoard(Enum): TLSR9528A_RETENTION = auto() TLSR9258A = auto() TLSR9258A_RETENTION = auto() + TL3218X = auto() def GnArgName(self): if self == TelinkBoard.TLRS9118BDK40D: @@ -135,6 +136,8 @@ def GnArgName(self): return 'tlsr9258a' elif self == TelinkBoard.TLSR9258A_RETENTION: return 'tlsr9258a_retention' + elif self == TelinkBoard.TL3218X: + return 'tl3218x' else: raise Exception('Unknown board type: %r' % self) diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt index c473de1aa1d814..f3330ffc3fe090 100644 --- a/scripts/build/testdata/all_targets_linux_x64.txt +++ b/scripts/build/testdata/all_targets_linux_x64.txt @@ -22,5 +22,5 @@ nuttx-x64-light qpg-qpg6105-{lock,light,shell,persistent-storage,light-switch,thermostat}[-updateimage] stm32-stm32wb5mm-dk-light tizen-arm-{all-clusters,chip-tool,light,tests}[-no-ble][-no-thread][-no-wifi][-asan][-ubsan][-coverage][-with-ui] -telink-{tlsr9118bdk40d,tlsr9518adk80d,tlsr9528a,tlsr9528a_retention,tlsr9258a,tlsr9258a_retention}-{air-quality-sensor,all-clusters,all-clusters-minimal,bridge,contact-sensor,light,light-switch,lock,ota-requestor,pump,pump-controller,shell,smoke-co-alarm,temperature-measurement,thermostat,window-covering}[-ota][-dfu][-shell][-rpc][-factory-data][-4mb][-mars][-usb][-compress-lzma][-thread-analyzer] +telink-{tlsr9118bdk40d,tlsr9518adk80d,tlsr9528a,tlsr9528a_retention,tlsr9258a,tlsr9258a_retention,tl3218x}-{air-quality-sensor,all-clusters,all-clusters-minimal,bridge,contact-sensor,light,light-switch,lock,ota-requestor,pump,pump-controller,shell,smoke-co-alarm,temperature-measurement,thermostat,window-covering}[-ota][-dfu][-shell][-rpc][-factory-data][-4mb][-mars][-usb][-compress-lzma][-thread-analyzer] openiotsdk-{shell,lock}[-mbedtls][-psa] diff --git a/scripts/setup/constraints.txt b/scripts/setup/constraints.txt index 1b5244314196d6..874d46f6f1a526 100644 --- a/scripts/setup/constraints.txt +++ b/scripts/setup/constraints.txt @@ -32,8 +32,6 @@ cbor2==5.4.6 # via -r requirements.zephyr.txt certifi==2022.12.7 # via requests -cffi==1.15.1 - # via cryptography charset-normalizer==3.0.1 # via requests click==8.1.3 diff --git a/scripts/setup/requirements.all.txt b/scripts/setup/requirements.all.txt index 346abfa3936888..4a7672a08f639d 100644 --- a/scripts/setup/requirements.all.txt +++ b/scripts/setup/requirements.all.txt @@ -43,6 +43,8 @@ mypy-protobuf==3.5.0 protobuf==4.24.4 types-protobuf==4.24.0.2 +cffi==1.15.0; python_version < "3.13" +cffi==1.17.1; python_version >= "3.13" cryptography # python unit tests diff --git a/scripts/tools/telink/requirements.txt b/scripts/tools/telink/requirements.txt index 58b519dc924bfa..e76b1423e4ded9 100644 --- a/scripts/tools/telink/requirements.txt +++ b/scripts/tools/telink/requirements.txt @@ -1,5 +1,6 @@ cryptography==43.0.1 -cffi==1.15.0 +cffi==1.15.0; python_version < "3.13" +cffi==1.17.1; python_version >= "3.13" future==0.18.3 pycparser==2.21 pypng==0.0.21 diff --git a/src/app/AttributePathParams.h b/src/app/AttributePathParams.h index dc3b71236d25c1..52d5bb5972162b 100644 --- a/src/app/AttributePathParams.h +++ b/src/app/AttributePathParams.h @@ -25,9 +25,7 @@ namespace chip { namespace app { -#if CHIP_CONFIG_ENABLE_READ_CLIENT -class ReadClient; -#endif // CHIP_CONFIG_ENABLE_READ_CLIENT + struct AttributePathParams { AttributePathParams() = default; diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index 8b008c4e9b238b..2e017dd362d7eb 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -201,11 +201,10 @@ static_library("interaction-model") { "reporting/reporting.h", ] - deps = [ "${chip_root}/src/app:events" ] - - # Temporary dependency: codegen data provider instance should be provided - # by the application - deps += [ "${chip_root}/src/app/codegen-data-model-provider:instance-header" ] + deps = [ + "${chip_root}/src/app:events", + "${chip_root}/src/app:global-attributes", + ] public_deps = [ ":app_config", diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp index 0dd4df635b8e61..9b76dd31bff477 100644 --- a/src/app/InteractionModelEngine.cpp +++ b/src/app/InteractionModelEngine.cpp @@ -50,10 +50,6 @@ #include #include -// TODO: defaulting to codegen should eventually be an application choice and not -// hard-coded in the interaction model -#include - namespace chip { namespace app { namespace { @@ -1798,9 +1794,15 @@ Protocols::InteractionModel::Status InteractionModelEngine::CheckCommandExistenc DataModel::Provider * InteractionModelEngine::SetDataModelProvider(DataModel::Provider * model) { - // Alternting data model should not be done while IM is actively handling requests. + // Altering data model should not be done while IM is actively handling requests. VerifyOrDie(mReadHandlers.begin() == mReadHandlers.end()); + if (model == mDataModelProvider) + { + // no-op, just return + return model; + } + DataModel::Provider * oldModel = mDataModelProvider; if (oldModel != nullptr) { @@ -1830,14 +1832,11 @@ DataModel::Provider * InteractionModelEngine::SetDataModelProvider(DataModel::Pr return oldModel; } -DataModel::Provider * InteractionModelEngine::GetDataModelProvider() +DataModel::Provider * InteractionModelEngine::GetDataModelProvider() const { - if (mDataModelProvider == nullptr) - { - // These should be called within the CHIP processing loop. - assertChipStackLockedByCurrentThread(); - SetDataModelProvider(CodegenDataModelProviderInstance()); - } + // These should be called within the CHIP processing loop. + assertChipStackLockedByCurrentThread(); + return mDataModelProvider; } diff --git a/src/app/InteractionModelEngine.h b/src/app/InteractionModelEngine.h index ef4b041f19d020..3fa379129a0547 100644 --- a/src/app/InteractionModelEngine.h +++ b/src/app/InteractionModelEngine.h @@ -404,10 +404,7 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, } #endif - // Temporarily NOT const because the data model provider will be auto-set - // to codegen on first usage. This behaviour will be changed once each - // application must explicitly set the data model provider. - DataModel::Provider * GetDataModelProvider(); + DataModel::Provider * GetDataModelProvider() const; // MUST NOT be used while the interaction model engine is running as interaction // model functionality (e.g. active reads/writes/subscriptions) rely on data model diff --git a/src/app/SubscriptionResumptionSessionEstablisher.cpp b/src/app/SubscriptionResumptionSessionEstablisher.cpp index e6f1ba02172631..f9ea25cb58dc93 100644 --- a/src/app/SubscriptionResumptionSessionEstablisher.cpp +++ b/src/app/SubscriptionResumptionSessionEstablisher.cpp @@ -17,7 +17,6 @@ #include #include -#include namespace chip { namespace app { diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index 3be8df5710616c..bd1950842a3a80 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -235,6 +235,10 @@ template("chip_data_model") { deps = [] } + if (!defined(public_deps)) { + public_deps = [] + } + if (!defined(cflags)) { cflags = [] } @@ -269,9 +273,12 @@ template("chip_data_model") { } else if (cluster == "application-launcher-server") { sources += [ "${_app_root}/app-platform/ContentApp.cpp", + "${_app_root}/app-platform/ContentApp.h", "${_app_root}/app-platform/ContentAppPlatform.cpp", + "${_app_root}/app-platform/ContentAppPlatform.h", "${_app_root}/clusters/${cluster}/${cluster}.cpp", ] + deps += [ "${chip_root}/src/controller" ] } else if (cluster == "ota-requestor") { sources += [ # TODO - align name of folder ? @@ -288,6 +295,10 @@ template("chip_data_model") { "${_app_root}/clusters/${cluster}/OTATestEventTriggerHandler.cpp", "${_app_root}/clusters/${cluster}/OTATestEventTriggerHandler.h", ] + + # TODO: DefaultOTARequestor depends on controller, however the cluster server itself does not. + # Maybe DefaultOTARequestor and related code should have its own source set. + deps += [ "${chip_root}/src/controller:interactions" ] } else if (cluster == "bindings") { sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp", @@ -446,10 +457,6 @@ template("chip_data_model") { } } - if (!defined(public_deps)) { - public_deps = [] - } - public_deps += [ ":${_data_model_name}_codegen", ":${_data_model_name}_zapgen", @@ -459,12 +466,16 @@ template("chip_data_model") { "${chip_root}/src/app/common:attribute-type", "${chip_root}/src/app/common:cluster-objects", "${chip_root}/src/app/common:enums", + "${chip_root}/src/app/server", "${chip_root}/src/app/util:types", "${chip_root}/src/app/util/persistence", - "${chip_root}/src/controller", "${chip_root}/src/lib/core", "${chip_root}/src/lib/support", "${chip_root}/src/protocols/secure_channel", + + # TODO: Embedded example apps currently build with chip_build_controller = false, and so get a libCHIP without controller support, + # but nevertheless expect to have access to some of the "controller" code to implement bindings and related functionality. + "${chip_root}/src/controller:interactions", ] public_deps += codegen_data_model_PUBLIC_DEPS diff --git a/src/app/clusters/color-control-server/color-control-server.cpp b/src/app/clusters/color-control-server/color-control-server.cpp index a01de7fad22dcb..98379b26a70a50 100644 --- a/src/app/clusters/color-control-server/color-control-server.cpp +++ b/src/app/clusters/color-control-server/color-control-server.cpp @@ -1264,10 +1264,13 @@ EmberEventControl * ColorControlServer::configureHSVEventControl(EndpointId endp * @param saturation Target saturation * @param transitionTime Transition time in 10th of seconds * @return Status::Success When successful, - * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a saturation transition state. + * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a saturation transition state, + * Status::ConstraintError if the saturation or tansitionTime are above maximum. */ Status ColorControlServer::moveToSaturation(EndpointId endpoint, uint8_t saturation, uint16_t transitionTime) { + VerifyOrReturnError(saturation <= MAX_SATURATION_VALUE, Status::ConstraintError); + VerifyOrReturnError(transitionTime <= kMaxTransitionTime, Status::ConstraintError); Color16uTransitionState * colorSaturationTransitionState = getSaturationTransitionState(endpoint); VerifyOrReturnError(nullptr != colorSaturationTransitionState, Status::UnsupportedEndpoint); @@ -1307,6 +1310,7 @@ Status ColorControlServer::moveToSaturation(EndpointId endpoint, uint8_t saturat * was called by MoveHue command and rate is a uint8 value. * @return Status::Success When successful, * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a saturation transition state, + * Status::ConstraintError if the hue, saturation or transitionTime, are above maximum. */ Status ColorControlServer::moveToHueAndSaturation(EndpointId endpoint, uint16_t hue, uint8_t saturation, uint16_t transitionTime, bool isEnhanced) @@ -1315,6 +1319,10 @@ Status ColorControlServer::moveToHueAndSaturation(EndpointId endpoint, uint16_t uint16_t halfWay = isEnhanced ? HALF_MAX_UINT16T : HALF_MAX_UINT8T; bool moveUp; + VerifyOrReturnError((isEnhanced || hue <= MAX_HUE_VALUE), Status::ConstraintError); + VerifyOrReturnError(saturation <= MAX_SATURATION_VALUE, Status::ConstraintError); + VerifyOrReturnError(transitionTime <= kMaxTransitionTime, Status::ConstraintError); + uint16_t epIndex = getEndpointIndex(endpoint); Color16uTransitionState * colorSaturationTransitionState = getSaturationTransitionStateByIndex(epIndex); ColorHueTransitionState * colorHueTransitionState = getColorHueTransitionStateByIndex(epIndex); @@ -1502,10 +1510,11 @@ Status ColorControlServer::moveToHueCommand(EndpointId endpoint, uint16_t hue, D bool isEnhanced) { MATTER_TRACE_SCOPE("moveToHue", "ColorControl"); - VerifyOrReturnValue(moveDirection != DirectionEnum::kUnknownEnumValue, Status::InvalidCommand); - // Command Parameters constraint checks: VerifyOrReturnValue((isEnhanced || hue <= MAX_HUE_VALUE), Status::ConstraintError); + VerifyOrReturnValue(transitionTime <= kMaxTransitionTime, Status::ConstraintError); + + VerifyOrReturnValue(moveDirection != DirectionEnum::kUnknownEnumValue, Status::InvalidCommand); ColorHueTransitionState * colorHueTransitionState = getColorHueTransitionState(endpoint); VerifyOrReturnValue(colorHueTransitionState != nullptr, Status::UnsupportedEndpoint); @@ -1612,7 +1621,6 @@ Status ColorControlServer::moveToHueCommand(EndpointId endpoint, uint16_t hue, D * was called by MoveHue command and rate is a uint8 value. * @return Status::Success when successful, * Status::ConstraintError when the other parameters are outside their defined value range. - */ Status ColorControlServer::moveToHueAndSaturationCommand(EndpointId endpoint, uint16_t hue, uint8_t saturation, uint16_t transitionTime, BitMask optionsMask, @@ -1622,6 +1630,7 @@ Status ColorControlServer::moveToHueAndSaturationCommand(EndpointId endpoint, ui // Command Parameters constraint checks: VerifyOrReturnValue((isEnhanced || hue <= MAX_HUE_VALUE), Status::ConstraintError); VerifyOrReturnValue(saturation <= MAX_SATURATION_VALUE, Status::ConstraintError); + VerifyOrReturnValue(transitionTime <= kMaxTransitionTime, Status::ConstraintError); VerifyOrReturnValue(shouldExecuteIfOff(endpoint, optionsMask, optionsOverride), Status::Success); @@ -1646,12 +1655,19 @@ Status ColorControlServer::moveToHueAndSaturationCommand(EndpointId endpoint, ui * @return Status::Success when successful, * Status::InvalidCommand when StepSize is 0 or an unknown HueStepMode is provided * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a hue transition state. + * Status::ConstraintError when the other parameters are outside their defined value range. */ Status ColorControlServer::stepHueCommand(EndpointId endpoint, HueStepMode stepMode, uint16_t stepSize, uint16_t transitionTime, BitMask optionsMask, BitMask optionsOverride, bool isEnhanced) { MATTER_TRACE_SCOPE("stepHue", "ColorControl"); + // Command Parameters constraint checks: + // The non-enhanced variant passed a uint8 type for transitionTime and the full range (0-255) is allowed + if (isEnhanced) + { + VerifyOrReturnValue(transitionTime <= kMaxTransitionTime, Status::ConstraintError); + } // Confirm validity of the step mode and step size received VerifyOrReturnValue(stepMode != HueStepMode::kUnknownEnumValue, Status::InvalidCommand); VerifyOrReturnValue(stepSize != 0, Status::InvalidCommand); @@ -1787,7 +1803,8 @@ Status ColorControlServer::moveSaturationCommand(EndpointId endpoint, const Comm * @param commandData Struct containing the parameters of the command. * @return Status::Success when successful, * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a saturation transition state (verified in - * moveToSaturation function) Status::ConstraintError when a command parameters is outside its defined value range. + * moveToSaturation function) + * Status::ConstraintError when a command parameter is outside its defined value range. */ Status ColorControlServer::moveToSaturationCommand(EndpointId endpoint, const Commands::MoveToSaturation::DecodableType & commandData) @@ -1795,6 +1812,7 @@ Status ColorControlServer::moveToSaturationCommand(EndpointId endpoint, MATTER_TRACE_SCOPE("moveToSaturation", "ColorControl"); // Command Parameters constraint checks: VerifyOrReturnValue(commandData.saturation <= MAX_SATURATION_VALUE, Status::ConstraintError); + VerifyOrReturnValue(commandData.transitionTime <= kMaxTransitionTime, Status::ConstraintError); VerifyOrReturnValue(shouldExecuteIfOff(endpoint, commandData.optionsMask, commandData.optionsOverride), Status::Success); Status status = moveToSaturation(endpoint, commandData.saturation, commandData.transitionTime); @@ -1810,7 +1828,7 @@ Status ColorControlServer::moveToSaturationCommand(EndpointId endpoint, * @param commandData Struct containing the parameters of the command. * @return Status::Success when successful, * Status::InvalidCommand when a step size of 0 or an unknown SaturationStepMode is provided - * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a saturation transition state. + * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a saturation transition state, */ Status ColorControlServer::stepSaturationCommand(EndpointId endpoint, const Commands::StepSaturation::DecodableType & commandData) { @@ -1861,7 +1879,7 @@ Status ColorControlServer::stepSaturationCommand(EndpointId endpoint, const Comm * @param commandData Struct containing the parameters of the command. * @return Status::Success when successful, * Status::InvalidCommand when an unknown action or direction is provided - * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a hue transition state. + * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a hue transition state, */ Status ColorControlServer::colorLoopCommand(EndpointId endpoint, const Commands::ColorLoopSet::DecodableType & commandData) { @@ -2146,10 +2164,18 @@ EmberEventControl * ColorControlServer::configureXYEventControl(EndpointId endpo * @param colorX target X * @param colorY target Y * @param transitionTime transition time in 10th of seconds - * @return Status::Success if successful,Status::UnsupportedEndpoint XY is not supported on the endpoint + * @return Status::Success if successful, + * @return Status::Success when successful, + * Status::UnsupportedEndpoint XY is not supported on the endpoint, + * Status::ConstraintError when a command parameter is outside its defined value range. */ Status ColorControlServer::moveToColor(EndpointId endpoint, uint16_t colorX, uint16_t colorY, uint16_t transitionTime) { + // Command Parameters constraint checks: + VerifyOrReturnValue(colorX <= MAX_CIE_XY_VALUE, Status::ConstraintError); + VerifyOrReturnValue(colorY <= MAX_CIE_XY_VALUE, Status::ConstraintError); + VerifyOrReturnValue(transitionTime <= kMaxTransitionTime, Status::ConstraintError); + uint16_t epIndex = getEndpointIndex(endpoint); Color16uTransitionState * colorXTransitionState = getXTransitionStateByIndex(epIndex); Color16uTransitionState * colorYTransitionState = getYTransitionStateByIndex(epIndex); @@ -2201,9 +2227,15 @@ Status ColorControlServer::moveToColor(EndpointId endpoint, uint16_t colorX, uin * @return Status::Success when successful, * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a Color XY transition state (verified in * moveToColor function), + * Status::ConstraintError when a command parameter is outside its defined value range. */ Status ColorControlServer::moveToColorCommand(EndpointId endpoint, const Commands::MoveToColor::DecodableType & commandData) { + // Command Parameters constraint checks: + VerifyOrReturnValue(commandData.colorX <= MAX_CIE_XY_VALUE, Status::ConstraintError); + VerifyOrReturnValue(commandData.colorY <= MAX_CIE_XY_VALUE, Status::ConstraintError); + VerifyOrReturnValue(commandData.transitionTime <= kMaxTransitionTime, Status::ConstraintError); + VerifyOrReturnValue(shouldExecuteIfOff(endpoint, commandData.optionsMask, commandData.optionsOverride), Status::Success); Status status = moveToColor(endpoint, commandData.colorX, commandData.colorY, commandData.transitionTime); @@ -2302,10 +2334,14 @@ Status ColorControlServer::moveColorCommand(EndpointId endpoint, const Commands: * @param commandData Struct containing the parameters of the command * @return Status::Success when successful, * Status::InvalidCommand when a step X and Y of 0 is provided - * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a Color XY transition state. + * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a Color XY transition state, + * Status::ConstraintError when a command parameter is outside its defined value range. */ Status ColorControlServer::stepColorCommand(EndpointId endpoint, const Commands::StepColor::DecodableType & commandData) { + // Command Parameters constraint checks: + VerifyOrReturnValue(commandData.transitionTime <= kMaxTransitionTime, Status::ConstraintError); + VerifyOrReturnValue(commandData.stepX != 0 || commandData.stepY != 0, Status::InvalidCommand); uint16_t epIndex = getEndpointIndex(endpoint); @@ -2440,8 +2476,11 @@ ColorControlServer::Color16uTransitionState * ColorControlServer::getTempTransit */ Status ColorControlServer::moveToColorTemp(EndpointId aEndpoint, uint16_t colorTemperature, uint16_t transitionTime) { - EndpointId endpoint = aEndpoint; + // Command Parameters constraint checks: + VerifyOrReturnValue(colorTemperature <= kMaxColorTemperatureMireds, Status::ConstraintError); + VerifyOrReturnValue(transitionTime <= kMaxTransitionTime, Status::ConstraintError); + EndpointId endpoint = aEndpoint; Color16uTransitionState * colorTempTransitionState = getTempTransitionState(endpoint); VerifyOrReturnError(nullptr != colorTempTransitionState, Status::UnsupportedEndpoint); @@ -2638,10 +2677,15 @@ void ColorControlServer::updateTempCommand(EndpointId endpoint) * @return Status::Success when successful, * Status::InvalidCommand when a rate of 0 for a non-stop move or an unknown HueMoveMode is provided * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a color temp transition state. + * Status::ConstraintError when a command parameter is outside its defined value range. */ Status ColorControlServer::moveColorTempCommand(EndpointId endpoint, const Commands::MoveColorTemperature::DecodableType & commandData) { + // Command Parameters constraint checks: + VerifyOrReturnValue(commandData.colorTemperatureMinimumMireds <= kMaxColorTemperatureMireds, Status::ConstraintError); + VerifyOrReturnValue(commandData.colorTemperatureMaximumMireds <= kMaxColorTemperatureMireds, Status::ConstraintError); + // check moveMode and rate before any operation is done on the transition states // rate value is ignored if the MoveMode is stop VerifyOrReturnValue(commandData.moveMode != HueMoveMode::kUnknownEnumValue, Status::InvalidCommand); @@ -2734,11 +2778,16 @@ Status ColorControlServer::moveColorTempCommand(EndpointId endpoint, * @param commandData Struct containing the parameters of the command. * @return Status::Success when successful, * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a color XY transition state (verified in - * moveToColorTemp function). + * moveToColorTemp function), + * Status::ConstraintError when a command parameter is outside its defined value range. */ Status ColorControlServer::moveToColorTempCommand(EndpointId endpoint, const Commands::MoveToColorTemperature::DecodableType & commandData) { + // Command Parameters constraint checks: + VerifyOrReturnValue(commandData.colorTemperatureMireds <= kMaxColorTemperatureMireds, Status::ConstraintError); + VerifyOrReturnValue(commandData.transitionTime <= kMaxTransitionTime, Status::ConstraintError); + VerifyOrReturnValue(shouldExecuteIfOff(endpoint, commandData.optionsMask, commandData.optionsOverride), Status::Success); Status status = moveToColorTemp(endpoint, commandData.colorTemperatureMireds, commandData.transitionTime); @@ -2754,11 +2803,17 @@ Status ColorControlServer::moveToColorTempCommand(EndpointId endpoint, * @param commandData Struct containing the parameters of the command * @return Status::Success when successful, * Status::InvalidCommand when stepSize is 0 or an unknown stepMode is provided - * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a color temp transition state. + * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a color temp transition state, + * Status::ConstraintError when a command parameter is outside its defined value range. */ Status ColorControlServer::stepColorTempCommand(EndpointId endpoint, const Commands::StepColorTemperature::DecodableType & commandData) { + // Command Parameters constraint checks: + VerifyOrReturnValue(commandData.transitionTime <= kMaxTransitionTime, Status::ConstraintError); + VerifyOrReturnValue(commandData.colorTemperatureMinimumMireds <= kMaxColorTemperatureMireds, Status::ConstraintError); + VerifyOrReturnValue(commandData.colorTemperatureMaximumMireds <= kMaxColorTemperatureMireds, Status::ConstraintError); + // Confirm validity of the step mode and step size received VerifyOrReturnValue(commandData.stepMode != HueStepMode::kUnknownEnumValue, Status::InvalidCommand); VerifyOrReturnValue(commandData.stepSize != 0, Status::InvalidCommand); diff --git a/src/app/clusters/color-control-server/color-control-server.h b/src/app/clusters/color-control-server/color-control-server.h index 40ae30aeb2224f..c25313d251494e 100644 --- a/src/app/clusters/color-control-server/color-control-server.h +++ b/src/app/clusters/color-control-server/color-control-server.h @@ -294,6 +294,9 @@ class ColorControlServer MATTER_DM_COLOR_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; static_assert(kColorControlClusterServerMaxEndpointCount <= kEmberInvalidEndpointIndex, "ColorControl endpoint count error"); + static constexpr uint16_t kMaxTransitionTime = 65534; // Max value as defined by the spec. + static constexpr uint16_t kMaxColorTemperatureMireds = 65279; // Max value as defined by the spec (0xFEFF). + #ifdef MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_HSV ColorHueTransitionState colorHueTransitionStates[kColorControlClusterServerMaxEndpointCount]; Color16uTransitionState colorSatTransitionStates[kColorControlClusterServerMaxEndpointCount]; diff --git a/src/app/clusters/content-app-observer/content-app-observer.cpp b/src/app/clusters/content-app-observer/content-app-observer.cpp index d595b058126924..ed726dd7468c10 100644 --- a/src/app/clusters/content-app-observer/content-app-observer.cpp +++ b/src/app/clusters/content-app-observer/content-app-observer.cpp @@ -33,7 +33,8 @@ #include #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED -#include +#include // nogncheck + #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED using namespace chip; diff --git a/src/app/clusters/content-control-server/content-control-server.cpp b/src/app/clusters/content-control-server/content-control-server.cpp index 8c9d076a71d7c5..944f7232d45673 100644 --- a/src/app/clusters/content-control-server/content-control-server.cpp +++ b/src/app/clusters/content-control-server/content-control-server.cpp @@ -33,7 +33,8 @@ #include #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED -#include +#include // nogncheck + #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED using namespace chip; diff --git a/src/app/clusters/content-launch-server/content-launch-server.cpp b/src/app/clusters/content-launch-server/content-launch-server.cpp index f0b5d5992e8a36..a75565413d5da6 100644 --- a/src/app/clusters/content-launch-server/content-launch-server.cpp +++ b/src/app/clusters/content-launch-server/content-launch-server.cpp @@ -29,7 +29,8 @@ #include #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED -#include +#include // nogncheck + #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED #include diff --git a/src/app/clusters/keypad-input-server/keypad-input-server.cpp b/src/app/clusters/keypad-input-server/keypad-input-server.cpp index 6ca7a6dd46767d..8eab54017bb596 100644 --- a/src/app/clusters/keypad-input-server/keypad-input-server.cpp +++ b/src/app/clusters/keypad-input-server/keypad-input-server.cpp @@ -35,7 +35,8 @@ #include #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED -#include +#include // nogncheck + #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED using namespace chip; diff --git a/src/app/clusters/media-playback-server/media-playback-server.cpp b/src/app/clusters/media-playback-server/media-playback-server.cpp index 5f762cf8048ba0..2a55f6372e30dc 100644 --- a/src/app/clusters/media-playback-server/media-playback-server.cpp +++ b/src/app/clusters/media-playback-server/media-playback-server.cpp @@ -37,7 +37,8 @@ #include #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED -#include +#include // nogncheck + #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED using namespace chip; diff --git a/src/app/clusters/target-navigator-server/target-navigator-server.cpp b/src/app/clusters/target-navigator-server/target-navigator-server.cpp index e42673a8bfbebb..90985c14d0e1be 100644 --- a/src/app/clusters/target-navigator-server/target-navigator-server.cpp +++ b/src/app/clusters/target-navigator-server/target-navigator-server.cpp @@ -36,7 +36,8 @@ #include #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED -#include +#include // nogncheck + #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED using namespace chip; diff --git a/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp b/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp index 3e5e3a8cf039c8..b0815da48e0c08 100644 --- a/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp +++ b/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/src/app/codegen-data-model-provider/CodegenDataModelProvider.h b/src/app/codegen-data-model-provider/CodegenDataModelProvider.h index 7549ef1fd44c27..59b91747a0ef07 100644 --- a/src/app/codegen-data-model-provider/CodegenDataModelProvider.h +++ b/src/app/codegen-data-model-provider/CodegenDataModelProvider.h @@ -16,10 +16,10 @@ */ #pragma once -#include "app/ConcreteCommandPath.h" #include #include +#include #include #include diff --git a/src/app/codegen-data-model-provider/CodegenDataModelProvider_Read.cpp b/src/app/codegen-data-model-provider/CodegenDataModelProvider_Read.cpp index a558b8e986298a..88989b52071810 100644 --- a/src/app/codegen-data-model-provider/CodegenDataModelProvider_Read.cpp +++ b/src/app/codegen-data-model-provider/CodegenDataModelProvider_Read.cpp @@ -104,33 +104,6 @@ DataModel::ActionReturnStatus CodegenDataModelProvider::ReadAttribute(const Data ChipLogValueMEI(request.path.mClusterId), request.path.mEndpointId, ChipLogValueMEI(request.path.mAttributeId), request.path.mExpanded); - // ACL check for non-internal requests - if (!request.operationFlags.Has(DataModel::OperationFlags::kInternal)) - { - VerifyOrReturnError(request.subjectDescriptor != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - - Access::RequestPath requestPath{ .cluster = request.path.mClusterId, - .endpoint = request.path.mEndpointId, - .requestType = Access::RequestType::kAttributeReadRequest, - .entityId = request.path.mAttributeId }; - CHIP_ERROR err = Access::GetAccessControl().Check(*request.subjectDescriptor, requestPath, - RequiredPrivilege::ForReadAttribute(request.path)); - if (err != CHIP_NO_ERROR) - { - VerifyOrReturnError((err == CHIP_ERROR_ACCESS_DENIED) || (err == CHIP_ERROR_ACCESS_RESTRICTED_BY_ARL), err); - - // Implementation of 8.4.3.2 of the spec for path expansion - if (request.path.mExpanded) - { - return CHIP_NO_ERROR; - } - - // access denied and access restricted have specific codes for IM - return err == CHIP_ERROR_ACCESS_DENIED ? CHIP_IM_GLOBAL_STATUS(UnsupportedAccess) - : CHIP_IM_GLOBAL_STATUS(AccessRestricted); - } - } - auto metadata = Ember::FindAttributeMetadata(request.path); // Explicit failure in finding a suitable metadata diff --git a/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp b/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp index 8ce369b7bd8220..c9b2a1b99a375c 100644 --- a/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp +++ b/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp @@ -1321,20 +1321,6 @@ TEST(TestCodegenModelViaMocks, CommandHandlerInterfaceAcceptedCommands) EXPECT_FALSE(model.GetAcceptedCommandInfo(ConcreteCommandPath(kMockEndpoint1, MockClusterId(1), 33)).has_value()); } -TEST(TestCodegenModelViaMocks, EmberAttributeReadAclDeny) -{ - UseMockNodeConfig config(gTestNodeConfig); - CodegenDataModelProviderWithContext model; - ScopedMockAccessControl accessControl; - - ReadOperation testRequest(kMockEndpoint1, MockClusterId(1), MockAttributeId(10)); - testRequest.SetSubjectDescriptor(kDenySubjectDescriptor); - - std::unique_ptr encoder = testRequest.StartEncoding(); - - ASSERT_EQ(model.ReadAttribute(testRequest.GetRequest(), *encoder), Status::UnsupportedAccess); -} - TEST(TestCodegenModelViaMocks, ReadForInvalidGlobalAttributePath) { UseMockNodeConfig config(gTestNodeConfig); @@ -1392,24 +1378,6 @@ TEST(TestCodegenModelViaMocks, EmberAttributeInvalidRead) } } -TEST(TestCodegenModelViaMocks, EmberAttributePathExpansionAccessDeniedRead) -{ - UseMockNodeConfig config(gTestNodeConfig); - CodegenDataModelProviderWithContext model; - ScopedMockAccessControl accessControl; - - ReadOperation testRequest(kMockEndpoint1, MockClusterId(1), MockAttributeId(10)); - testRequest.SetSubjectDescriptor(kDenySubjectDescriptor); - testRequest.SetPathExpanded(true); - - std::unique_ptr encoder = testRequest.StartEncoding(); - - // For expanded paths, access control failures succeed without encoding anything - // This is temporary until ACL checks are moved inside the IM/ReportEngine - ASSERT_EQ(model.ReadAttribute(testRequest.GetRequest(), *encoder), CHIP_NO_ERROR); - ASSERT_FALSE(encoder->TriedEncode()); -} - TEST(TestCodegenModelViaMocks, AccessInterfaceUnsupportedRead) { UseMockNodeConfig config(gTestNodeConfig); diff --git a/src/app/data-model-provider/Provider.h b/src/app/data-model-provider/Provider.h index 16dd7327a35a37..c547b75b81984f 100644 --- a/src/app/data-model-provider/Provider.h +++ b/src/app/data-model-provider/Provider.h @@ -60,15 +60,7 @@ class Provider : public ProviderMetadataTree virtual InteractionModelContext CurrentContext() const { return mContext; } /// TEMPORARY/TRANSITIONAL requirement for transitioning from ember-specific code - /// ReadAttribute is REQUIRED to perform: - /// - ACL validation (see notes on OperationFlags::kInternal) - /// - Validation of readability/writability (also controlled by OperationFlags::kInternal) - /// - use request.path.mExpanded to skip encoding replies for data according - /// to 8.4.3.2 of the spec: - /// > If the path indicates attribute data that is not readable, then the path SHALL - /// be discarded. - /// > Else if reading from the attribute in the path requires a privilege that is not - /// granted to access the cluster in the path, then the path SHALL be discarded. + /// ReadAttribute is REQUIRED to respond to GlobalAttribute read requests /// /// Return value notes: /// ActionReturnStatus::IsOutOfSpaceEncodingResponse diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp index ea4c0014e71397..63d71bfc92db7a 100644 --- a/src/app/reporting/Engine.cpp +++ b/src/app/reporting/Engine.cpp @@ -16,17 +16,24 @@ * limitations under the License. */ +#include +#include #include #include +#include #include #include #include +#include #include #include #include #include #include +#include #include +#include +#include #include #if CHIP_CONFIG_ENABLE_ICD_SERVER @@ -52,9 +59,81 @@ Status EventPathValid(DataModel::Provider * model, const ConcreteEventPath & eve return Status::Success; } -DataModel::ActionReturnStatus RetrieveClusterData(DataModel::Provider * dataModel, - const Access::SubjectDescriptor & subjectDescriptor, bool isFabricFiltered, - AttributeReportIBs::Builder & reportBuilder, +/// Returns the status of ACL validation. +/// If the return value has a status set, that means the ACL check failed, +/// the read must not be performed, and the returned status (which may +/// be success, when dealing with non-concrete paths) should be used +/// as the status for the read. +/// +/// If the returned value is std::nullopt, that means the ACL check passed and the +/// read should proceed. +std::optional ValidateReadAttributeACL(DataModel::Provider * dataModel, const SubjectDescriptor & subjectDescriptor, + const ConcreteReadAttributePath & path) +{ + + RequestPath requestPath{ .cluster = path.mClusterId, + .endpoint = path.mEndpointId, + .requestType = RequestType::kAttributeReadRequest, + .entityId = path.mAttributeId }; + + std::optional info = dataModel->GetAttributeInfo(path); + + // If the attribute exists, we know whether it is readable (readPrivilege has value) + // and what the required access privilege is. However for attributes missing from the metatada + // (e.g. global attributes) or completely missing attributes we do not actually know of a required + // privilege and default to kView (this is correct for global attributes and a reasonable check + // for others) + Privilege requiredPrivilege = Privilege::kView; + if (info.has_value() && info->readPrivilege.has_value()) + { + // attribute exists and is readable, set the correct read privilege + requiredPrivilege = *info->readPrivilege; + } + + CHIP_ERROR err = GetAccessControl().Check(subjectDescriptor, requestPath, requiredPrivilege); + if (err == CHIP_NO_ERROR) + { + if (IsSupportedGlobalAttributeNotInMetadata(path.mAttributeId)) + { + // Global attributes passing a kView check is ok + return std::nullopt; + } + + // We want to return "success" (i.e. nulopt) IF AND ONLY IF the attribute exists and is readable (has read privilege). + // Since the Access control check above may have passed with kView, we do another check here: + // - Attribute exists (info has value) + // - Attribute is readable (readProvilege has value) and not "write only" + // If the attribute exists and is not readable, we will return UnsupportedRead (spec 8.4.3.2: "Else if the path indicates + // attribute data that is not readable, an AttributeStatusIB SHALL be generated with the UNSUPPORTED_READ Status Code.") + // + // TODO:: https://github.com/CHIP-Specifications/connectedhomeip-spec/pull/9024 requires interleaved ordering that + // is NOT implemented here. Spec requires: + // - check cluster access check (done here as kView at least) + // - unsupported endpoint/cluster/attribute check (NOT done here) when the attribute is missing. + // this SHOULD be done here when info does not have a value. This was not done as a first pass to + // minimize amount of delta in the initial PR. + // - "write-only" attributes should return UNSUPPORTED_READ (this is done here) + if (info.has_value() && !info->readPrivilege.has_value()) + { + return CHIP_IM_GLOBAL_STATUS(UnsupportedRead); + } + + return std::nullopt; + } + VerifyOrReturnError((err == CHIP_ERROR_ACCESS_DENIED) || (err == CHIP_ERROR_ACCESS_RESTRICTED_BY_ARL), err); + + // Implementation of 8.4.3.2 of the spec for path expansion + if (path.mExpanded) + { + return CHIP_NO_ERROR; + } + + // access denied and access restricted have specific codes for IM + return err == CHIP_ERROR_ACCESS_DENIED ? CHIP_IM_GLOBAL_STATUS(UnsupportedAccess) : CHIP_IM_GLOBAL_STATUS(AccessRestricted); +} + +DataModel::ActionReturnStatus RetrieveClusterData(DataModel::Provider * dataModel, const SubjectDescriptor & subjectDescriptor, + bool isFabricFiltered, AttributeReportIBs::Builder & reportBuilder, const ConcreteReadAttributePath & path, AttributeEncodeState * encoderState) { ChipLogDetail(DataManagement, " Cluster %" PRIx32 ", Attribute %" PRIx32 " is dirty", path.mClusterId, @@ -64,10 +143,7 @@ DataModel::ActionReturnStatus RetrieveClusterData(DataModel::Provider * dataMode DataModel::ReadAttributeRequest readRequest; - if (isFabricFiltered) - { - readRequest.readFlags.Set(DataModel::ReadFlags::kFabricFiltered); - } + readRequest.readFlags.Set(DataModel::ReadFlags::kFabricFiltered, isFabricFiltered); readRequest.subjectDescriptor = &subjectDescriptor; readRequest.path = path; @@ -84,9 +160,17 @@ DataModel::ActionReturnStatus RetrieveClusterData(DataModel::Provider * dataMode TLV::TLVWriter checkpoint; reportBuilder.Checkpoint(checkpoint); + DataModel::ActionReturnStatus status(CHIP_NO_ERROR); AttributeValueEncoder attributeValueEncoder(reportBuilder, subjectDescriptor, path, version, isFabricFiltered, encoderState); - DataModel::ActionReturnStatus status = dataModel->ReadAttribute(readRequest, attributeValueEncoder); + if (auto access_status = ValidateReadAttributeACL(dataModel, subjectDescriptor, path); access_status.has_value()) + { + status = *access_status; + } + else + { + status = dataModel->ReadAttribute(readRequest, attributeValueEncoder); + } if (status.IsSuccess()) { @@ -435,13 +519,13 @@ CHIP_ERROR Engine::CheckAccessDeniedEventPaths(TLV::TLVWriter & aWriter, bool & aHasEncodedData = true; } - Access::RequestPath requestPath{ .cluster = current->mValue.mClusterId, - .endpoint = current->mValue.mEndpointId, - .requestType = RequestType::kEventReadRequest, - .entityId = current->mValue.mEventId }; - Access::Privilege requestPrivilege = RequiredPrivilege::ForReadEvent(path); + RequestPath requestPath{ .cluster = current->mValue.mClusterId, + .endpoint = current->mValue.mEndpointId, + .requestType = RequestType::kEventReadRequest, + .entityId = current->mValue.mEventId }; + Privilege requestPrivilege = RequiredPrivilege::ForReadEvent(path); - err = Access::GetAccessControl().Check(apReadHandler->GetSubjectDescriptor(), requestPath, requestPrivilege); + err = GetAccessControl().Check(apReadHandler->GetSubjectDescriptor(), requestPath, requestPrivilege); if ((err != CHIP_ERROR_ACCESS_DENIED) && (err != CHIP_ERROR_ACCESS_RESTRICTED_BY_ARL)) { ReturnErrorOnFailure(err); @@ -580,13 +664,13 @@ CHIP_ERROR Engine::BuildSingleReportDataEventReports(ReportDataMessage::Builder CHIP_ERROR Engine::BuildAndSendSingleReportData(ReadHandler * apReadHandler) { CHIP_ERROR err = CHIP_NO_ERROR; - chip::System::PacketBufferTLVWriter reportDataWriter; + System::PacketBufferTLVWriter reportDataWriter; ReportDataMessage::Builder reportDataBuilder; - chip::System::PacketBufferHandle bufHandle = nullptr; - uint16_t reservedSize = 0; - bool hasMoreChunks = false; - bool needCloseReadHandler = false; - size_t reportBufferMaxSize = 0; + System::PacketBufferHandle bufHandle = nullptr; + uint16_t reservedSize = 0; + bool hasMoreChunks = false; + bool needCloseReadHandler = false; + size_t reportBufferMaxSize = 0; // Reserved size for the MoreChunks boolean flag, which takes up 1 byte for the control tag and 1 byte for the context tag. const uint32_t kReservedSizeForMoreChunksFlag = 1 + 1; @@ -623,7 +707,7 @@ CHIP_ERROR Engine::BuildAndSendSingleReportData(ReadHandler * apReadHandler) // Always limit the size of the generated packet to fit within the max size returned by the ReadHandler regardless // of the available buffer capacity. // Also, we need to reserve some extra space for the MIC field. - reportDataWriter.ReserveBuffer(static_cast(reservedSize + chip::Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES)); + reportDataWriter.ReserveBuffer(static_cast(reservedSize + Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES)); // Create a report data. err = reportDataBuilder.Init(&reportDataWriter); diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 6808431b67bf4f..e9475fdbf906e8 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -127,6 +127,15 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) VerifyOrExit(initParams.opCertStore != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(initParams.reportScheduler != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + // Extra log since this is an incremental requirement and existing applications may not be aware + if (initParams.dataModelProvider == nullptr) + { + ChipLogError(AppServer, "Application Server requires a `initParams.dataModelProvider` value."); + ChipLogError(AppServer, "For backwards compatibility, you likely can use `CodegenDataModelProviderInstance()`"); + } + + VerifyOrExit(initParams.dataModelProvider != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + // TODO(16969): Remove chip::Platform::MemoryInit() call from Server class, it belongs to outer code chip::Platform::MemoryInit(); @@ -161,6 +170,17 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) SetAttributePersistenceProvider(&mAttributePersister); SetSafeAttributePersistenceProvider(&mAttributePersister); + // SetDataModelProvider() actually initializes/starts the provider. We need + // to preserve the following ordering guarantees: + // + // 1) Provider initialization (under SetDataModelProvider) happens after + // SetSafeAttributePersistenceProvider, since the provider can then use + // the safe persistence provider to implement and initialize its own attribute persistence logic. + // 2) For now, provider initialization happens before InitDataModelHandler(), which depends + // on atttribute persistence being already set up before it runs. Longer-term, the logic from + // InitDataModelHandler should just move into the codegen provider. + chip::app::InteractionModelEngine::GetInstance()->SetDataModelProvider(initParams.dataModelProvider); + { FabricTable::InitParams fabricTableInitParams; fabricTableInitParams.storage = mDeviceStorage; diff --git a/src/app/server/Server.h b/src/app/server/Server.h index fc6f7ac10750d3..5c5068d7902be1 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -192,6 +192,11 @@ struct ServerInitParams // If the ICD Check-In protocol use-case is supported and no strategy is provided, server will use the default strategy. app::ICDCheckInBackOffStrategy * icdCheckInBackOffStrategy = nullptr; #endif // CHIP_CONFIG_ENABLE_ICD_CIP + + // MUST NOT be null during initialization: every application must define the + // data model it wants to use. Backwards-compatibility can use `CodegenDataModelProviderInstance` + // for ember/zap-generated models. + chip::app::DataModel::Provider * dataModelProvider = nullptr; }; /** diff --git a/src/app/server/java/AndroidAppServerWrapper.cpp b/src/app/server/java/AndroidAppServerWrapper.cpp index 69436b17641d55..5e205b7d82fb8a 100644 --- a/src/app/server/java/AndroidAppServerWrapper.cpp +++ b/src/app/server/java/AndroidAppServerWrapper.cpp @@ -17,6 +17,8 @@ */ #include "AndroidAppServerWrapper.h" + +#include #include #include #include @@ -50,6 +52,7 @@ CHIP_ERROR ChipAndroidAppInit(AppDelegate * appDelegate) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); if (appDelegate != nullptr) { initParams.appDelegate = appDelegate; diff --git a/src/app/server/java/BUILD.gn b/src/app/server/java/BUILD.gn index c25548eb112549..98012409b1ee56 100644 --- a/src/app/server/java/BUILD.gn +++ b/src/app/server/java/BUILD.gn @@ -36,6 +36,7 @@ static_library("jni") { ] deps = [ + "${chip_root}/src/app/codegen-data-model-provider:instance-header", "${chip_root}/src/app/server", "${chip_root}/src/inet", "${chip_root}/src/lib", diff --git a/src/app/tests/TestAclEvent.cpp b/src/app/tests/TestAclEvent.cpp index bbded462985012..13b3e36491f359 100644 --- a/src/app/tests/TestAclEvent.cpp +++ b/src/app/tests/TestAclEvent.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -217,6 +218,7 @@ TEST_F(TestAclEvent, TestReadRoundtripWithEventStatusIBInEventReport) auto * engine = chip::app::InteractionModelEngine::GetInstance(); + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(engine->Init(&GetExchangeManager(), &GetFabricTable(), app::reporting::GetDefaultReportScheduler()), CHIP_NO_ERROR); // A custom AccessControl::Delegate has been installed that grants privilege to any cluster except the test cluster. diff --git a/src/app/tests/TestCommandInteraction.cpp b/src/app/tests/TestCommandInteraction.cpp index 4535a51dff4b1e..363b43ccb4d5cf 100644 --- a/src/app/tests/TestCommandInteraction.cpp +++ b/src/app/tests/TestCommandInteraction.cpp @@ -1554,6 +1554,43 @@ TEST_F(TestCommandInteraction, TestCommandSenderCommandAsyncSuccessResponseFlow) EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u); } +TEST_F(TestCommandInteraction, CommandSenderDeletedWhenResponseIsPending) +{ + + mockCommandSenderDelegate.ResetCounter(); + app::CommandSender * commandSender = Platform::New(&mockCommandSenderDelegate, &GetExchangeManager()); + + AddInvokeRequestData(commandSender); + asyncCommand = true; + + EXPECT_EQ(commandSender->SendCommandRequest(GetSessionBobToAlice()), CHIP_NO_ERROR); + + DrainAndServiceIO(); + + EXPECT_EQ(mockCommandSenderDelegate.onResponseCalledTimes, 0); + EXPECT_EQ(mockCommandSenderDelegate.onFinalCalledTimes, 0); + EXPECT_EQ(mockCommandSenderDelegate.onErrorCalledTimes, 0); + EXPECT_EQ(GetNumActiveCommandResponderObjects(), 1u); + EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 2u); + + // This is NOT deleting CommandSender in one of the callbacks, so we are not violating + // the API contract. CommandSender is deleted when no message is being processed which + // is a time that deleting CommandSender is considered safe. + Platform::Delete(commandSender); + + // Decrease CommandHandler refcount and send response + asyncCommandHandle = nullptr; + + DrainAndServiceIO(); + + EXPECT_EQ(mockCommandSenderDelegate.onResponseCalledTimes, 0); + EXPECT_EQ(mockCommandSenderDelegate.onFinalCalledTimes, 0); + EXPECT_EQ(mockCommandSenderDelegate.onErrorCalledTimes, 0); + + EXPECT_EQ(GetNumActiveCommandResponderObjects(), 0u); + EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u); +} + TEST_F(TestCommandInteraction, TestCommandSenderCommandSpecificResponseFlow) { diff --git a/src/app/tests/TestCommissioningWindowManager.cpp b/src/app/tests/TestCommissioningWindowManager.cpp index 297a95e299a30b..7a2e127324348c 100644 --- a/src/app/tests/TestCommissioningWindowManager.cpp +++ b/src/app/tests/TestCommissioningWindowManager.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -113,6 +114,7 @@ class TestCommissioningWindowManager : public ::testing::Test static chip::SimpleTestEventTriggerDelegate sSimpleTestEventTriggerDelegate; initParams.testEventTriggerDelegate = &sSimpleTestEventTriggerDelegate; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); // Use whatever server port the kernel decides to give us. initParams.operationalServicePort = 0; diff --git a/src/app/tests/TestInteractionModelEngine.cpp b/src/app/tests/TestInteractionModelEngine.cpp index 0a4a8bd5af6ef4..acc19c12f44da0 100644 --- a/src/app/tests/TestInteractionModelEngine.cpp +++ b/src/app/tests/TestInteractionModelEngine.cpp @@ -88,6 +88,7 @@ TEST_F(TestInteractionModelEngine, TestAttributePathParamsPushRelease) InteractionModelEngine * engine = InteractionModelEngine::GetInstance(); + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(engine->Init(&GetExchangeManager(), &GetFabricTable(), app::reporting::GetDefaultReportScheduler()), CHIP_NO_ERROR); SingleLinkedListNode * attributePathParamsList = nullptr; @@ -123,6 +124,7 @@ TEST_F(TestInteractionModelEngine, TestRemoveDuplicateConcreteAttribute) InteractionModelEngine * engine = InteractionModelEngine::GetInstance(); + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(CHIP_NO_ERROR, engine->Init(&GetExchangeManager(), &GetFabricTable(), app::reporting::GetDefaultReportScheduler())); SingleLinkedListNode * attributePathParamsList = nullptr; @@ -259,6 +261,7 @@ TEST_F_FROM_FIXTURE(TestInteractionModelEngine, TestSubjectHasActiveSubscription ASSERT_TRUE(exchangeCtx1); // InteractionModelEngine init + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(CHIP_NO_ERROR, engine->Init(&GetExchangeManager(), &GetFabricTable(), reporting::GetDefaultReportScheduler())); // Verify that there are no active subscriptions @@ -306,6 +309,7 @@ TEST_F_FROM_FIXTURE(TestInteractionModelEngine, TestSubjectHasActiveSubscription ASSERT_TRUE(exchangeCtx1); // InteractionModelEngine init + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(CHIP_NO_ERROR, engine->Init(&GetExchangeManager(), &GetFabricTable(), reporting::GetDefaultReportScheduler())); // Verify that both Alice and Bob have no active subscriptions @@ -364,6 +368,7 @@ TEST_F_FROM_FIXTURE(TestInteractionModelEngine, TestSubjectHasActiveSubscription ASSERT_TRUE(exchangeCtx2); // InteractionModelEngine init + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(CHIP_NO_ERROR, engine->Init(&GetExchangeManager(), &GetFabricTable(), reporting::GetDefaultReportScheduler())); // Verify that both Alice and Bob have no active subscriptions @@ -446,6 +451,7 @@ TEST_F_FROM_FIXTURE(TestInteractionModelEngine, TestSubjectHasActiveSubscription ASSERT_TRUE(exchangeCtx22); // InteractionModelEngine init + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(CHIP_NO_ERROR, engine->Init(&GetExchangeManager(), &GetFabricTable(), reporting::GetDefaultReportScheduler())); // Verify that both Alice and Bob have no active subscriptions @@ -525,6 +531,7 @@ TEST_F_FROM_FIXTURE(TestInteractionModelEngine, TestSubjectHasActiveSubscription FabricIndex bobFabricIndex = 1; // InteractionModelEngine init + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(CHIP_NO_ERROR, engine->Init(&GetExchangeManager(), &GetFabricTable(), reporting::GetDefaultReportScheduler())); // Make sure we are using CASE sessions, because there is no defunct-marking for PASE. @@ -575,6 +582,7 @@ TEST_F(TestInteractionModelEngine, TestSubjectHasPersistedSubscription) EXPECT_EQ(subscriptionStorage.Init(&storage), CHIP_NO_ERROR); + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(CHIP_NO_ERROR, engine->Init(&GetExchangeManager(), &GetFabricTable(), app::reporting::GetDefaultReportScheduler(), nullptr, &subscriptionStorage)); @@ -630,6 +638,7 @@ TEST_F_FROM_FIXTURE(TestInteractionModelEngine, TestSubscriptionResumptionTimer) InteractionModelEngine * engine = InteractionModelEngine::GetInstance(); + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(engine->Init(&GetExchangeManager(), &GetFabricTable(), app::reporting::GetDefaultReportScheduler()), CHIP_NO_ERROR); uint32_t timeTillNextResubscriptionMs; @@ -661,6 +670,7 @@ TEST_F_FROM_FIXTURE(TestInteractionModelEngine, TestDecrementNumSubscriptionsToR constexpr uint8_t kNumberOfSubsToResume = 5; uint8_t numberOfSubsRemaining = kNumberOfSubsToResume; + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(engine->Init(&GetExchangeManager(), &GetFabricTable(), app::reporting::GetDefaultReportScheduler()), CHIP_NO_ERROR); #if CHIP_CONFIG_ENABLE_ICD_CIP && !CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION diff --git a/src/app/tests/suites/certification/Test_TC_IDM_4_2.yaml b/src/app/tests/suites/certification/Test_TC_IDM_4_2.yaml deleted file mode 100644 index 21beac03a85b00..00000000000000 --- a/src/app/tests/suites/certification/Test_TC_IDM_4_2.yaml +++ /dev/null @@ -1,774 +0,0 @@ -# Copyright (c) 2023 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# Auto-generated scripts for harness use only, please review before automation. The endpoints and cluster names are currently set to default - -name: - 32.4.2. [TC-IDM-4.2] Subscription Response Messages from DUT Test Cases. - [DUT as Server] - -PICS: - - MCORE.IDM.S - -config: - nodeId: 0x12344321 - cluster: "Basic Information" - endpoint: 0 - -tests: - - label: "Notes/Testing Considerations" - verification: | - 1. The Cluster and Commands should be based on the cluster implementation on the DUT. - 2. The cluster used in the below test steps is an example, User can use any supported chip cluster/attribute/command. - disabled: true - - - label: "Pre condition" - verification: | - Please use Interactive mode to Verify subscription test cases - Here the command to enter interactive mode:-- ./chip-tool interactive start - disabled: true - - - label: "Step 0a: SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT = 60 mins" - PICS: " !ICDM.S " - verification: | - When the ICDM feature is not supported or enabled, the SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT is set to 60 minutes. - disabled: true - - - label: "Step 0b: CR1 reads from the DUT the IdleModeDuration attribute." - PICS: ICDM.S - verification: | - CR1 reads from the DUT the IdleModeDuration attribute by sending below mentioned command - - icdmanagement read idle-mode-interval 1 0 - - Please note down the value of IdleModeDuration as SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT for use in the next step validations. - - [1692870543.225457][7160:7162] CHIP:DMG: SuppressResponse = true, - [1692870543.225495][7160:7162] CHIP:DMG: InteractionModelRevision = 10 - [1692870543.225528][7160:7162] CHIP:DMG: } - [1692870543.225723][7160:7162] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0046 Attribute 0x0000_0000 DataVersion: 4022467249 - [1692870543.225795][7160:7162] CHIP:TOO: IdleModeDuration: 2000 - [1692870543.225992][7160:7162] CHIP:EM: <<< [E:52837i S:57653 M:52559591 (Ack:263018291)] (S) Msg TX to 1:0000000000000001 [853D] --- Type 0000:10 (SecureChannel:StandaloneAck) - disabled: true - - - label: - "Step 1: CR1 sends a subscription message to the DUT with - MaxIntervalCeiling set to a value greater than - SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT. DUT sends a report data - action to the TH. CR1 sends a success status response to the DUT. DUT - sends a Subscribe Response Message to the CR1 to activate the - subscription." - verification: | - Please run the following command on the TH to test the subscription feature and verify that the value of MaxIntervalCeiling is set correctly(set the value greater than SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT) - - onoff subscribe on-off 100 600 1 1 --keepSubscriptions true - - On the CR1( chip-tool), verify a report data message is received and verify it contains the following data : - 1. Verify Report Data Message Received: - Check if a report data message is received on the CR1. - - 2. Verify Report Data Contents: - Confirm that the received report data message contains the data of the attribute/event that was previously requested. - - 3. Verify Subscribe Response Fields: - Examine the Subscribe Response to ensure it includes the following fields: - SubscriptionId: Verify that it is of type uint32. - Verify MaxInterval Field: - - 4. Check for an additional field in the Subscribe Response: - MaxInterval: Verify that it is of type uint32. - - 5. Verify MaxInterval against MaxIntervalCeiling: - Compare the MaxInterval value received in the Subscribe Response to the MaxIntervalCeiling value to verify that MaxInterval is less than or equal to MaxIntervalCeiling. - - [1693221742.765461][22261:22263] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0006 Attribute 0x0000_0000 DataVersion: 523169586 - [1693221742.765473][22261:22263] CHIP:TOO: OnOff: FALSE - [1693221742.765495][22261:22263] CHIP:DMG: MoveToState ReadClient[0x7f6070027e40]: Moving to [AwaitingSu] - [1693221742.765530][22261:22263] CHIP:EM: <<< [E:26388i S:13043 M:192043500 (Ack:11734613)] (S) Msg TX to 1:0000000000000001 [3DC0] --- Type 0001:01 (IM:StatusResponse) - [1693221742.765542][22261:22263] CHIP:IN: (S) Sending msg 192043500 on secure session with LSID: 13043 - [1693221742.765587][22261:22263] CHIP:DL: HandlePlatformSpecificBLEEvent 32793 - [1693221742.765594][22261:22263] CHIP:DL: HandlePlatformSpecificBLEEvent 32793 - [1693221742.765981][22261:22263] CHIP:EM: >>> [E:26388i S:13043 M:11734614 (Ack:192043500)] (S) Msg RX from 1:0000000000000001 [3DC0] --- Type 0001:04 (IM:SubscribeResponse) - [1693221742.765991][22261:22263] CHIP:EM: Found matching exchange: 26388i, Delegate: 0x7f6070027e50 - [1693221742.766002][22261:22263] CHIP:EM: Rxd Ack; Removing MessageCounter:192043500 from Retrans Table on exchange 26388i - [1693221742.766012][22261:22263] CHIP:DMG: SubscribeResponse is received - [1693221742.766025][22261:22263] CHIP:DMG: SubscribeResponseMessage = - [1693221742.766031][22261:22263] CHIP:DMG: { - [1693221742.766038][22261:22263] CHIP:DMG: SubscriptionId = 0x15e2f82f, - [1693221742.766045][22261:22263] CHIP:DMG: MaxInterval = 0x64, - [1693221742.766051][22261:22263] CHIP:DMG: InteractionModelRevision = 10 - [1693221742.766057][22261:22263] CHIP:DMG: } - [1693221742.766068][22261:22263] CHIP:DMG: Subscription established with SubscriptionID = 0x15e2f82f MinInterval = 100s MaxInterval = 100s Peer = 01:0000000000000001 - disabled: true - - - label: - "Step 2: CR1 sends a subscription message to the DUT with - MaxIntervalCeiling set to a value less than - SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT. DUT sends a report data - action to the CR1. CR1 sends a success status response to the DUT. DUT - sends a Subscribe Response Message to the CR1 to activate the - subscription." - verification: | - Please run the following command on the TH to test the subscription feature and verify that the value of MaxIntervalCeiling is set correctly( set the value less than SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT) - - - basicinformation subscribe location 10 400 1 0 --keepSubscriptions true - - On the CR1(chip-tool), verify a report data message is received and verify it contains the following data : - 1. Verify Report Data Message Received: - Check if a report data message is received on the CR1 (target hardware). - - 2. Verify Report Data Contents: - Confirm that the received report data message contains the data of the attribute/event that was previously requested. - - 3. Verify Subscribe Response Fields: - Examine the Subscribe Response to ensure it includes the following fields: - SubscriptionId: Verify that it is of type uint32. - MaxInterval: Verify that it is of type uint32. - - 4. Verify MaxInterval against SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT: - Compare the MaxInterval value received in the Subscribe Response to the value of SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT. - Verify that the MaxInterval value is less than or equal to SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT. - - [1693221766.862968][22261:22263] CHIP:DMG: } - [1693221766.863028][22261:22263] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0028 Attribute 0x0000_0006 DataVersion: 1552486032 - [1693221766.863045][22261:22263] CHIP:TOO: Location: XX - [1693221766.863068][22261:22263] CHIP:DMG: MoveToState ReadClient[0x7f6070027b50]: Moving to [AwaitingSu] - [1693221766.863114][22261:22263] CHIP:EM: <<< [E:26389i S:13043 M:192043503 (Ack:11734615)] (S) Msg TX to 1:0000000000000001 [3DC0] --- Type 0001:01 (IM:StatusResponse) - [1693221766.863130][22261:22263] CHIP:IN: (S) Sending msg 192043503 on secure session with LSID: 13043 - [1693221766.863196][22261:22263] CHIP:DL: HandlePlatformSpecificBLEEvent 32793 - [1693221766.863207][22261:22263] CHIP:DL: HandlePlatformSpecificBLEEvent 32793 - [1693221766.863559][22261:22263] CHIP:EM: >>> [E:26389i S:13043 M:11734616 (Ack:192043503)] (S) Msg RX from 1:0000000000000001 [3DC0] --- Type 0001:04 (IM:SubscribeResponse) - [1693221766.863569][22261:22263] CHIP:EM: Found matching exchange: 26389i, Delegate: 0x7f6070027b60 - [1693221766.863584][22261:22263] CHIP:EM: Rxd Ack; Removing MessageCounter:192043503 from Retrans Table on exchange 26389i - [1693221766.863603][22261:22263] CHIP:DMG: SubscribeResponse is received - [1693221766.863620][22261:22263] CHIP:DMG: SubscribeResponseMessage = - [1693221766.863629][22261:22263] CHIP:DMG: { - [1693221766.863639][22261:22263] CHIP:DMG: SubscriptionId = 0x83e461d9, - [1693221766.863651][22261:22263] CHIP:DMG: MaxInterval = 0xa, - [1693221766.863661][22261:22263] CHIP:DMG: InteractionModelRevision = 10 - [1693221766.863667][22261:22263] CHIP:DMG: } - [1693221766.863677][22261:22263] CHIP:DMG: Subscription established with SubscriptionID = 0x83e461d9 MinInterval = 10s MaxInterval = 10s Peer = 01:0000000000000001 - disabled: true - - - label: - "Step 3: Setup CR2 such that it does not have access to a specific - cluster. CR2 sends a subscription message to subscribe to an attribute - on that cluster for which it does not have access. AttributePath = - [[Attribute = Attribute, Cluster = ClusterID, Endpoint = EndpointID - ]]." - verification: | - To ensure that CR1 and CR2 are on the same fabric and that CR1 grants access to CR2, Please send the below mentioned command, it will configure TH2 without access to a specific cluster, we send the ACL command, allowing access only to the Level Control cluster (cluster ID: 8); any attempts to subscribe to or use commands from other clusters will result in a status of 'INVALID_ACTION - - accesscontrol write acl '[{"privilege":5, "authMode":2, "subjects":[112233], "targets":null, "fabricIndex": 1},{"privilege":3, "authMode":2, "subjects":[4], "targets":[{"cluster":8, "endpoint":null, "deviceType":null}]}]' 1 0 - - [1689933254.566655][48781:48783] CHIP:EM: Rxd Ack; Removing MessageCounter:156974239 from Retrans Table on exchange 6316i - [1689933254.566660][48781:48783] CHIP:DMG: WriteClient moving to [ResponseRe] - [1689933254.566671][48781:48783] CHIP:DMG: WriteResponseMessage = - [1689933254.566675][48781:48783] CHIP:DMG: { - [1689933254.566677][48781:48783] CHIP:DMG: AttributeStatusIBs = - [1689933254.566682][48781:48783] CHIP:DMG: [ - [1689933254.566684][48781:48783] CHIP:DMG: AttributeStatusIB = - [1689933254.566688][48781:48783] CHIP:DMG: { - [1689933254.566691][48781:48783] CHIP:DMG: AttributePathIB = - [1689933254.566695][48781:48783] CHIP:DMG: { - [1689933254.566698][48781:48783] CHIP:DMG: Endpoint = 0x0, - [1689933254.566702][48781:48783] CHIP:DMG: Cluster = 0x1f, - [1689933254.566705][48781:48783] CHIP:DMG: Attribute = 0x0000_0000, - [1689933254.566708][48781:48783] CHIP:DMG: } - [1689933254.566713][48781:48783] CHIP:DMG: - [1689933254.566716][48781:48783] CHIP:DMG: StatusIB = - [1689933254.566720][48781:48783] CHIP:DMG: { - [1689933254.566723][48781:48783] CHIP:DMG: status = 0x00 (SUCCESS), - [1689933254.566726][48781:48783] CHIP:DMG: }, - [1689933254.566730][48781:48783] CHIP:DMG: - [1689933254.566732][48781:48783] CHIP:DMG: }, - [1689933254.566739][48781:48783] CHIP:DMG: - [1689933254.566741][48781:48783] CHIP:DMG: AttributeStatusIB = - [1689933254.566744][48781:48783] CHIP:DMG: { - [1689933254.566747][48781:48783] CHIP:DMG: AttributePathIB = - [1689933254.566750][48781:48783] CHIP:DMG: { - [1689933254.566752][48781:48783] CHIP:DMG: Endpoint = 0x0, - [1689933254.566756][48781:48783] CHIP:DMG: Cluster = 0x1f, - [1689933254.566760][48781:48783] CHIP:DMG: Attribute = 0x0000_0000, - [1689933254.566763][48781:48783] CHIP:DMG: ListIndex = Null, - [1689933254.566766][48781:48783] CHIP:DMG: } - [1689933254.566770][48781:48783] CHIP:DMG: - [1689933254.566773][48781:48783] CHIP:DMG: StatusIB = - [1689933254.566776][48781:48783] CHIP:DMG: { - [1689933254.566779][48781:48783] CHIP:DMG: status = 0x00 (SUCCESS), - [1689933254.566782][48781:48783] CHIP:DMG: }, - [1689933254.566786][48781:48783] CHIP:DMG: - [1689933254.566789][48781:48783] CHIP:DMG: }, - [1689933254.566794][48781:48783] CHIP:DMG: - [1689933254.566797][48781:48783] CHIP:DMG: AttributeStatusIB = - [1689933254.566800][48781:48783] CHIP:DMG: { - [1689933254.566802][48781:48783] CHIP:DMG: AttributePathIB = - [1689933254.566805][48781:48783] CHIP:DMG: { - [1689933254.566808][48781:48783] CHIP:DMG: Endpoint = 0x0, - [1689933254.566811][48781:48783] CHIP:DMG: Cluster = 0x1f, - [1689933254.566815][48781:48783] CHIP:DMG: Attribute = 0x0000_0000, - [1689933254.566818][48781:48783] CHIP:DMG: ListIndex = Null, - [1689933254.566821][48781:48783] CHIP:DMG: } - [1689933254.566825][48781:48783] CHIP:DMG: - [1689933254.566828][48781:48783] CHIP:DMG: StatusIB = - [1689933254.566831][48781:48783] CHIP:DMG: { - [1689933254.566834][48781:48783] CHIP:DMG: status = 0x00 (SUCCESS), - [1689933254.566837][48781:48783] CHIP:DMG: }, - [1689933254.566840][48781:48783] CHIP:DMG: - [1689933254.566843][48781:48783] CHIP:DMG: }, - [1689933254.566847][48781:48783] CHIP:DMG: - [1689933254.566849][48781:48783] CHIP:DMG: ], - [1689933254.566857][48781:48783] CHIP:DMG: - [1689933254.566859][48781:48783] CHIP:DMG: InteractionModelRevision = 1 - [1689933254.566862][48781:48783] CHIP:DMG: } - [1689933254.566897][48781:48783] CHIP:DMG: WriteClient moving to [AwaitingDe] - [1689933254.566916][48781:48783] CHIP:EM: <<< [E:6316i S:13964 M:156974240 (Ack:46397313)] (S) Msg TX to 1:0000000000000001 [B15F] --- Type 0000:10 (SecureChannel:StandaloneAck) - [1689933254.566922][48781:48783] CHIP:IN: (S) Sending msg 156974240 on secure session with LSID: 13964 - - If CR2 attempts to subscribe to an attribute on a cluster (ClusterID) for which it does not have access, the AttributePath used for the subscription would be in the form [[Attribute = AttributeName, Cluster = ClusterID, Endpoint = EndpointID]], but this action will be denied, and CR2 will not be able to access the attribute due to the restricted access. - - below provided the example command used to subscribe location attribute from basicinformation cluster from node id(4) that have access to the “levelcontrol” cluster - - basicinformation subscribe location 10 2400 1 0 --commissioner-nodeid 4 - [1689933387.304826][48781:48783] CHIP:EM: Rxd Ack; Removing MessageCounter:42350588 from Retrans Table on exchange 6319i - [1689933387.304834][48781:48783] CHIP:DMG: StatusResponseMessage = - [1689933387.304838][48781:48783] CHIP:DMG: { - [1689933387.304841][48781:48783] CHIP:DMG: Status = 0x80 (INVALID_ACTION), - [1689933387.304845][48781:48783] CHIP:DMG: InteractionModelRevision = 1 - [1689933387.304846][48781:48783] CHIP:DMG: } - [1689933387.304850][48781:48783] CHIP:IM: Received status response, status is 0x80 (INVALID_ACTION) - [1689933387.304864][48781:48783] CHIP:EM: <<< [E:6319i S:13965 M:42350589 (Ack:227168589)] (S) Msg TX to 2:0000000000000001 [B15F] --- Type 0001:01 (IM:StatusResponse) - [1689933387.304869][48781:48783] CHIP:IN: (S) Sending msg 42350589 on secure session with LSID: 13965 - [1689933387.304882][48781:48783] CHIP:DMG: MoveToState ReadClient[0x7fd404019110]: Moving to [ Idle] - - With the ACL command in step-2, we are overwriting the default privilege that chip-tool has an admin. After this step-3 you need to send below mentioned command to Grant access to all clusters again. - accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode":2, "subjects":[112233,4], "targets":null}]' 1 0 - disabled: true - - - label: - "Step 4: Setup CR2 such that it does not have access to all attributes - on a specific cluster and endpoint. CR2 sends a subscription request - to subscribe to all attributes for which it does not have access. - AttributePath = [[Cluster = ClusterID, Endpoint = EndpointID ]]." - verification: | - To ensure that CR1 and CR2 are on the same fabric and that CR1 grants access to CR2, Please send the below mentioned command, it will configure CR2 without access to a specific cluster on Specific endpoint, we send the ACL command, allowing access only to the Level Control cluster (cluster ID: 8) on endpoint 1 ; any attempts to subscribe to or use commands from other clusters will result in a status of 'INVALID_ACTION - - accesscontrol write acl '[{"privilege":5, "authMode":2, "subjects":[112233], "targets":null, "fabricIndex": 1},{"privilege":3, "authMode":2, "subjects":[4], "targets":[{"cluster":8, "endpoint":1, "deviceType":null}]}]' 1 0 - - [1687418564.590285][167960:167962] CHIP:DMG: WriteResponseMessage = - [1687418564.590290][167960:167962] CHIP:DMG: { - [1687418564.590294][167960:167962] CHIP:DMG: AttributeStatusIBs = - [1687418564.590304][167960:167962] CHIP:DMG: [ - [1687418564.590313][167960:167962] CHIP:DMG: AttributeStatusIB = - [1687418564.590321][167960:167962] CHIP:DMG: { - [1687418564.590327][167960:167962] CHIP:DMG: AttributePathIB = - [1687418564.590336][167960:167962] CHIP:DMG: { - [1687418564.590346][167960:167962] CHIP:DMG: Endpoint = 0x0, - [1687418564.590355][167960:167962] CHIP:DMG: Cluster = 0x1f, - [1687418564.590366][167960:167962] CHIP:DMG: Attribute = 0x0000_0000, - [1687418564.590374][167960:167962] CHIP:DMG: } - [1687418564.590385][167960:167962] CHIP:DMG: - [1687418564.590392][167960:167962] CHIP:DMG: StatusIB = - [1687418564.590406][167960:167962] CHIP:DMG: { - [1687418564.590415][167960:167962] CHIP:DMG: status = 0x00 (SUCCESS), - [1687418564.590423][167960:167962] CHIP:DMG: }, - [1687418564.590433][167960:167962] CHIP:DMG: - [1687418564.590444][167960:167962] CHIP:DMG: }, - [1687418564.590462][167960:167962] CHIP:DMG: - [1687418564.590469][167960:167962] CHIP:DMG: AttributeStatusIB = - [1687418564.590477][167960:167962] CHIP:DMG: { - [1687418564.590484][167960:167962] CHIP:DMG: AttributePathIB = - [1687418564.590493][167960:167962] CHIP:DMG: { - [1687418564.590502][167960:167962] CHIP:DMG: Endpoint = 0x0, - [1687418564.590512][167960:167962] CHIP:DMG: Cluster = 0x1f, - [1687418564.590521][167960:167962] CHIP:DMG: Attribute = 0x0000_0000, - [1687418564.590530][167960:167962] CHIP:DMG: ListIndex = Null, - [1687418564.590539][167960:167962] CHIP:DMG: } - [1687418564.590552][167960:167962] CHIP:DMG: - [1687418564.590559][167960:167962] CHIP:DMG: StatusIB = - [1687418564.590567][167960:167962] CHIP:DMG: { - [1687418564.590576][167960:167962] CHIP:DMG: status = 0x00 (SUCCESS), - [1687418564.590584][167960:167962] CHIP:DMG: }, - [1687418564.590593][167960:167962] CHIP:DMG: - [1687418564.590601][167960:167962] CHIP:DMG: }, - [1687418564.590616][167960:167962] CHIP:DMG: - [1687418564.590623][167960:167962] CHIP:DMG: AttributeStatusIB = - [1687418564.590631][167960:167962] CHIP:DMG: { - [1687418564.590638][167960:167962] CHIP:DMG: AttributePathIB = - [1687418564.590647][167960:167962] CHIP:DMG: { - [1687418564.590656][167960:167962] CHIP:DMG: Endpoint = 0x0, - [1687418564.590665][167960:167962] CHIP:DMG: Cluster = 0x1f, - [1687418564.590675][167960:167962] CHIP:DMG: Attribute = 0x0000_0000, - [1687418564.590683][167960:167962] CHIP:DMG: ListIndex = Null, - [1687418564.590691][167960:167962] CHIP:DMG: } - [1687418564.590704][167960:167962] CHIP:DMG: - [1687418564.590712][167960:167962] CHIP:DMG: StatusIB = - [1687418564.590720][167960:167962] CHIP:DMG: { - [1687418564.590729][167960:167962] CHIP:DMG: status = 0x00 (SUCCESS), - [1687418564.590738][167960:167962] CHIP:DMG: }, - [1687418564.590747][167960:167962] CHIP:DMG: - [1687418564.590754][167960:167962] CHIP:DMG: }, - [1687418564.590768][167960:167962] CHIP:DMG: - [1687418564.590776][167960:167962] CHIP:DMG: ], - [1687418564.590796][167960:167962] CHIP:DMG: - [1687418564.590804][167960:167962] CHIP:DMG: InteractionModelRevision = 1 - [1687418564.590811][167960:167962] CHIP:DMG: } - [1687418564.590882][167960:167962] CHIP:DMG: WriteClient moving to [AwaitingDe] - - If CR2 attempts to subscribe to an attribute on a cluster (ClusterID) for which it does not have access, the AttributePath used for the subscription would be in the form AttributePath = [[Cluster = ClusterID, Endpoint = EndpointID ]]., but this action will be denied, and CR2 will not be able to access the attribute due to the restricted access. - - below provided the example command to subscribe all attributes onto endpoint 1 for onoff cluster from node id(4) that have access to the “levelcontrol” cluster onto endpoint 1 - - - - onoff subscribe-by-id 0xFFFFFFFF 5 100 1 1 --commissioner-nodeid 4 - [1687418591.903193][167960:167962] CHIP:EM: Found matching exchange: 3641i, Delegate: 0x7fc81c00bbd0 - [1687418591.903197][167960:167962] CHIP:EM: Rxd Ack; Removing MessageCounter:104560060 from Retrans Table on exchange 3641i - [1687418591.903206][167960:167962] CHIP:DMG: StatusResponseMessage = - [1687418591.903209][167960:167962] CHIP:DMG: { - [1687418591.903211][167960:167962] CHIP:DMG: Status = 0x80 (INVALID_ACTION), - [1687418591.903213][167960:167962] CHIP:DMG: InteractionModelRevision = 1 - [1687418591.903215][167960:167962] CHIP:DMG: } - [1687418591.903220][167960:167962] CHIP:IM: Received status response, status is 0x80 (INVALID_ACTION) - [1687418591.903236][167960:167962] CHIP:EM: <<< [E:3641i S:26604 M:104560061 (Ack:37058090)] (S) Msg TX to 2:0000000000000001 [2DB4] --- Type 0001:01 (IM:StatusResponse) - [1687418591.903241][167960:167962] CHIP:IN: (S) Sending msg 104560061 on secure session with LSID: 26604 - [1687418591.903262][167960:167962] CHIP:DMG: MoveToState ReadClient[0x7fc81c00bbc0]: Moving to - - With the ACL command in step-2, we are overwriting the default privilege that chip-tool has an admin. After this step-3 you need to send below mentioned command to Grant access to all clusters again. - - accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode":2, "subjects":[112233,4], "targets":null}]' 1 0 - disabled: true - - - label: - "Step 5: Setup CR2 such that it does not have access to an Endpoint. - CR2 sends a subscription request to subscribe to all attributes on all - clusters on a specific Endpoint for which it does not have access. - AttributePath = [[ Endpoint = EndpointID ]]." - verification: | - To ensure that CR1 and CR2 are on the same fabric and that CR1 grants access to CR2, Please send the below mentioned command, it will configure CR2 without access to a specific endpoint, we send the ACL command, allowing access only to the endpoint 1 ; any attempts to subscribe to or use commands from other clusters will result in a status of 'INVALID_ACTION - - accesscontrol write acl '[{"privilege":5, "authMode":2, "subjects":[112233], "targets":null, "fabricIndex": 1},{"privilege":3, "authMode":2, "subjects":[4], "targets":[{"cluster":null, "endpoint":1, "deviceType":null}]}]' 1 0 - - [1687418943.852982][167960:167962] CHIP:DMG: WriteResponseMessage = - [1687418943.852989][167960:167962] CHIP:DMG: { - [1687418943.852996][167960:167962] CHIP:DMG: AttributeStatusIBs = - [1687418943.853006][167960:167962] CHIP:DMG: [ - [1687418943.853012][167960:167962] CHIP:DMG: AttributeStatusIB = - [1687418943.853018][167960:167962] CHIP:DMG: { - [1687418943.853024][167960:167962] CHIP:DMG: AttributePathIB = - [1687418943.853034][167960:167962] CHIP:DMG: { - [1687418943.853042][167960:167962] CHIP:DMG: Endpoint = 0x0, - [1687418943.853053][167960:167962] CHIP:DMG: Cluster = 0x1f, - [1687418943.853060][167960:167962] CHIP:DMG: Attribute = 0x0000_0000, - [1687418943.853067][167960:167962] CHIP:DMG: } - [1687418943.853080][167960:167962] CHIP:DMG: - [1687418943.853087][167960:167962] CHIP:DMG: StatusIB = - [1687418943.853095][167960:167962] CHIP:DMG: { - [1687418943.853103][167960:167962] CHIP:DMG: status = 0x00 (SUCCESS), - [1687418943.853109][167960:167962] CHIP:DMG: }, - [1687418943.853117][167960:167962] CHIP:DMG: - [1687418943.853123][167960:167962] CHIP:DMG: }, - [1687418943.853136][167960:167962] CHIP:DMG: - [1687418943.853142][167960:167962] CHIP:DMG: AttributeStatusIB = - [1687418943.853148][167960:167962] CHIP:DMG: { - [1687418943.853154][167960:167962] CHIP:DMG: AttributePathIB = - [1687418943.853161][167960:167962] CHIP:DMG: { - [1687418943.853167][167960:167962] CHIP:DMG: Endpoint = 0x0, - [1687418943.853175][167960:167962] CHIP:DMG: Cluster = 0x1f, - [1687418943.853182][167960:167962] CHIP:DMG: Attribute = 0x0000_0000, - [1687418943.853189][167960:167962] CHIP:DMG: ListIndex = Null, - [1687418943.853196][167960:167962] CHIP:DMG: } - [1687418943.853205][167960:167962] CHIP:DMG: - [1687418943.853211][167960:167962] CHIP:DMG: StatusIB = - [1687418943.853218][167960:167962] CHIP:DMG: { - [1687418943.853227][167960:167962] CHIP:DMG: status = 0x00 (SUCCESS), - [1687418943.853233][167960:167962] CHIP:DMG: }, - [1687418943.853240][167960:167962] CHIP:DMG: - [1687418943.853246][167960:167962] CHIP:DMG: }, - [1687418943.853258][167960:167962] CHIP:DMG: - [1687418943.853264][167960:167962] CHIP:DMG: AttributeStatusIB = - [1687418943.853274][167960:167962] CHIP:DMG: { - [1687418943.853280][167960:167962] CHIP:DMG: AttributePathIB = - [1687418943.853290][167960:167962] CHIP:DMG: { - [1687418943.853296][167960:167962] CHIP:DMG: Endpoint = 0x0, - [1687418943.853304][167960:167962] CHIP:DMG: Cluster = 0x1f, - [1687418943.853311][167960:167962] CHIP:DMG: Attribute = 0x0000_0000, - [1687418943.853318][167960:167962] CHIP:DMG: ListIndex = Null, - [1687418943.853323][167960:167962] CHIP:DMG: } - [1687418943.853332][167960:167962] CHIP:DMG: - [1687418943.853338][167960:167962] CHIP:DMG: StatusIB = - [1687418943.853345][167960:167962] CHIP:DMG: { - [1687418943.853352][167960:167962] CHIP:DMG: status = 0x00 (SUCCESS), - [1687418943.853359][167960:167962] CHIP:DMG: }, - [1687418943.853368][167960:167962] CHIP:DMG: - [1687418943.853374][167960:167962] CHIP:DMG: }, - [1687418943.853383][167960:167962] CHIP:DMG: - [1687418943.853389][167960:167962] CHIP:DMG: ], - [1687418943.853405][167960:167962] CHIP:DMG: - [1687418943.853411][167960:167962] CHIP:DMG: InteractionModelRevision = 1 - [1687418943.853418][167960:167962] CHIP:DMG: } - [1687418943.853488][167960:167962] CHIP:DMG: WriteClient moving to [AwaitingDe] - - If CR2 attempts to subscribe to an attribute on a cluster (ClusterID) for which it does not have access, the AttributePath used for the subscription would be in the form AttributePath = [[ Endpoint = EndpointID ]], but this action will be denied, and CR2 will not be able to access the attribute due to the restricted access. - - below provided the example command to subscribe to all attributes onto endpoint 0 for cluster 6 from a node id that have access to everything onto endpoint 1 - - - onoff subscribe-by-id 0xFFFFFFFF 5 100 1 0 --commissioner-nodeid 4 - [1687418974.537572][167960:167962] CHIP:EM: Rxd Ack; Removing MessageCounter:104560062 from Retrans Table on exchange 3650i - [1687418974.537610][167960:167962] CHIP:DMG: StatusResponseMessage = - [1687418974.537622][167960:167962] CHIP:DMG: { - [1687418974.537631][167960:167962] CHIP:DMG: Status = 0x80 (INVALID_ACTION), - [1687418974.537640][167960:167962] CHIP:DMG: InteractionModelRevision = 1 - [1687418974.537648][167960:167962] CHIP:DMG: } - [1687418974.537658][167960:167962] CHIP:IM: Received status response, status is 0x80 (INVALID_ACTION) - [1687418974.537725][167960:167962] CHIP:EM: <<< [E:3650i S:26604 M:104560063 (Ack:37058092)] (S) Msg TX to 2:0000000000000001 [2DB4] --- Type 0001:01 (IM:StatusResponse) - [1687418974.537743][167960:167962] CHIP:IN: (S) Sending msg 104560063 on secure session with LSID: 26604 - - - With the ACL command in step-2, we are overwriting the default privilege that chip-tool has an admin. After this step-3 you need to send below mentioned command to Grant access to all clusters again. - accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode":2, "subjects":[112233,4], "targets":null}]' 1 0 - disabled: true - - - label: - "Step 6: Setup CR2 such that it does not have access to the Node. CR2 - sends a subscription request to subscribe to all attributes on all - clusters on all endpoints on a Node for which it does not have access. - AttributePath = [[ ]]." - verification: | - sending a command along with unregistered commissioner node id (5) - - any subscribe-by-id 0xFFFFFFFF 0xFFFFFFFF 10 100 1 0XFFFF --commissioner-nodeid 5 - On CR2, Verify that the DUT returns a "INVALID_ACTION" status response. - - [1695815340.162063][2522:2524] CHIP:EM: Rxd Ack; Removing MessageCounter:187875065 from Retrans Table on exchange 10455i - [1695815340.162181][2522:2524] CHIP:DMG: StatusResponseMessage = - [1695815340.162244][2522:2524] CHIP:DMG: { - [1695815340.162298][2522:2524] CHIP:DMG: Status = 0x80 (INVALID_ACTION), - [1695815340.162357][2522:2524] CHIP:DMG: InteractionModelRevision = 11 - [1695815340.162412][2522:2524] CHIP:DMG: } - [1695815340.162501][2522:2524] CHIP:IM: Received status response, status is 0x80 (INVALID_ACTION) - disabled: true - - - label: - "Step 7: CR1 sends a subscription request action for an attribute with - an empty DataVersionFilters field. DUT sends a report data action with - the data of the attribute along with the data version. Tear down the - subscription for that attribute. Start another subscription with the - DataVersionFilter field set to the data version received above." - verification: | - Chip-Tool support required to validate this step : SDK Issue - https://github.com/project-chip/connectedhomeip/issues/28363 - - Not Testable - disabled: true - - - label: - "Step 8: CR1 sends a subscription request action for an attribute and - sets the MinIntervalFloor value to be same as MaxIntervalCeiling. - Activate the Subscription between CR1 and DUT. Modify the attribute - which has been subscribed to on the DUT." - verification: | - Please send the following command from CR1 (the subscription requester) to DUT (the device under test) to activate the subscription for the "on-time" attribute, setting the MinIntervalFloor and MaxIntervalCeiling values to be the same (in this case, 100 seconds): - - onoff subscribe on-time 100 100 1 1 --keepSubscriptions true - On the CR1(chip-tool) verify the SubscribeResponse is received successfully - [1690540281.061350][9488:9490] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0006 Attribute 0x0000_4001 DataVersion: 3310786904 - [1690540281.061363][9488:9490] CHIP:TOO: OnTime: 0 - [1690540281.061379][9488:9490] CHIP:DMG: MoveToState ReadClient[0x7faef8013880]: Moving to [AwaitingSu] - [1690540281.061427][9488:9490] CHIP:EM: <<< [E:49945i S:38251 M:151709012 (Ack:20807554)] (S) Msg TX to 1:0000000000000001 [8B98] --- Type 0001:01 (IM:StatusResponse) - [1690540281.061441][9488:9490] CHIP:IN: (S) Sending msg 151709012 on secure session with LSID: 38251 - [1690540281.061758][9488:9490] CHIP:EM: >>> [E:49945i S:38251 M:20807555 (Ack:151709012)] (S) Msg RX from 1:0000000000000001 [8B98] --- Type 0001:04 (IM:SubscribeResponse) - [1690540281.061771][9488:9490] CHIP:EM: Found matching exchange: 49945i, Delegate: 0x7faef8013890 - [1690540281.061786][9488:9490] CHIP:EM: Rxd Ack; Removing MessageCounter:151709012 from Retrans Table on exchange 49945i - [1690540281.061800][9488:9490] CHIP:DMG: SubscribeResponse is received - [1690540281.061816][9488:9490] CHIP:DMG: SubscribeResponseMessage = - [1690540281.061825][9488:9490] CHIP:DMG: { - [1690540281.061833][9488:9490] CHIP:DMG: SubscriptionId = 0x3ef5dc34, - [1690540281.061844][9488:9490] CHIP:DMG: MaxInterval = 0x64, - [1690540281.061853][9488:9490] CHIP:DMG: InteractionModelRevision = 1 - [1690540281.061862][9488:9490] CHIP:DMG: } - [1690540281.061875][9488:9490] CHIP:DMG: Subscription established with SubscriptionID = 0x3ef5dc34 MinInterval = 100s MaxInterval = 100s Peer = 01:0000000000000001 - - - - After activating the subscription between TH and DUT, please send the following command to modify the 'on-time' attribute value: - - >>> onoff write on-time 1 1 1 - On CR1(chip-tool), verify that the DUT sends a report data containing the current 'ontime' attribute value after the MinIntervalFloor time has elapsed - - [1690540304.761997][9488:9488] CHIP:TOO: Command: onoff write on-time 1 1 1 - [1690540304.762298][9488:9490] CHIP:TOO: Sending command to node 0x1 - [1690540304.762462][9488:9490] CHIP:CSM: FindOrEstablishSession: PeerId = [1:0000000000000001] - [1690540304.762474][9488:9490] CHIP:CSM: FindOrEstablishSession: No existing OperationalSessionSetup instance found - [1690540304.762493][9488:9490] CHIP:DIS: Found an existing secure session to [1:0000000000000001]! - [1690540304.762501][9488:9490] CHIP:DIS: OperationalSessionSetup[1:0000000000000001]: State change 1 --> 5 - [1690540304.762534][9488:9490] CHIP:TOO: cluster 0x0000_0006, attribute: 0x0000_4001, endpoint 1 - [1690540304.762585][9488:9490] CHIP:DMG: WriteClient moving to [AddAttribu] - [1690540304.762673][9488:9490] CHIP:EM: <<< [E:49946i S:38251 M:151709014] (S) Msg TX to 1:0000000000000001 [8B98] --- Type 0001:06 (IM:WriteRequest) - [1690540304.762693][9488:9490] CHIP:IN: (S) Sending msg 151709014 on secure session with LSID: 38251 - [1690540304.762788][9488:9490] CHIP:DMG: WriteClient moving to [AwaitingRe] - [1690540304.763448][9488:9490] CHIP:EM: >>> [E:49946i S:38251 M:20807556 (Ack:151709014)] (S) Msg RX from 1:0000000000000001 [8B98] --- Type 0001:07 (IM:WriteResponse) - [1690540304.763464][9488:9490] CHIP:EM: Found matching exchange: 49946i, Delegate: 0x7faef800a5e0 - [1690540304.763478][9488:9490] CHIP:EM: Rxd Ack; Removing MessageCounter:151709014 from Retrans Table on exchange 49946i - [1690540304.763493][9488:9490] CHIP:DMG: WriteClient moving to [ResponseRe] - [1690540304.763518][9488:9490] CHIP:DMG: WriteResponseMessage = - [1690540304.763527][9488:9490] CHIP:DMG: { - [1690540304.763534][9488:9490] CHIP:DMG: AttributeStatusIBs = - [1690540304.763546][9488:9490] CHIP:DMG: [ - [1690540304.763553][9488:9490] CHIP:DMG: AttributeStatusIB = - [1690540304.763562][9488:9490] CHIP:DMG: { - [1690540304.763570][9488:9490] CHIP:DMG: AttributePathIB = - [1690540304.763579][9488:9490] CHIP:DMG: { - [1690540304.763589][9488:9490] CHIP:DMG: Endpoint = 0x1, - [1690540304.763597][9488:9490] CHIP:DMG: Cluster = 0x6, - [1690540304.763606][9488:9490] CHIP:DMG: Attribute = 0x0000_4001, - [1690540304.763614][9488:9490] CHIP:DMG: } - [1690540304.763626][9488:9490] CHIP:DMG: - [1690540304.763634][9488:9490] CHIP:DMG: StatusIB = - [1690540304.763646][9488:9490] CHIP:DMG: { - [1690540304.763654][9488:9490] CHIP:DMG: status = 0x00 (SUCCESS), - [1690540304.763662][9488:9490] CHIP:DMG: }, - [1690540304.763671][9488:9490] CHIP:DMG: - [1690540304.763677][9488:9490] CHIP:DMG: }, - [1690540304.763688][9488:9490] CHIP:DMG: - [1690540304.763694][9488:9490] CHIP:DMG: ], - [1690540304.763706][9488:9490] CHIP:DMG: - [1690540304.763713][9488:9490] CHIP:DMG: InteractionModelRevision = 1 - [1690540304.763719][9488:9490] CHIP:DMG: } - [1690540304.763753][9488:9490] CHIP:DMG: WriteClient moving to [AwaitingDe] - [1690540304.763793][9488:9490] CHIP:EM: <<< [E:49946i S:38251 M:151709015 (Ack:20807556)] (S) Msg TX to 1:0000000000000001 [8B98] --- Type 0000:10 (SecureChannel:StandaloneAck) - [1690540304.763810][9488:9490] CHIP:IN: (S) Sending msg 151709015 on secure session with LSID: 38251 - [1690540304.763846][9488:9490] CHIP:EM: Flushed pending ack for MessageCounter:20807556 on exchange 49946i - [1690540325.496486][9488:9490] CHIP:EM: >>> [E:48664r S:38251 M:20807557] (S) Msg RX from 1:0000000000000001 [8B98] --- Type 0001:05 (IM:ReportData) - [1690540325.496520][9488:9490] CHIP:EM: Handling via exchange: 48664r, Delegate: 0x5639a50ebc68 - [1690540325.496552][9488:9490] CHIP:DMG: ReportDataMessage = - [1690540325.496565][9488:9490] CHIP:DMG: { - [1690540325.496576][9488:9490] CHIP:DMG: SubscriptionId = 0x3a11136b, - [1690540325.496587][9488:9490] CHIP:DMG: InteractionModelRevision = 1 - [1690540325.496595][9488:9490] CHIP:DMG: } - [1690540325.496632][9488:9490] CHIP:DMG: Refresh LivenessCheckTime for 804224 milliseconds with SubscriptionId = 0x3a11136b Peer = 01:0000000000000001 - [1690540325.496682][9488:9490] CHIP:EM: <<< [E:48664r S:38251 M:151709016 (Ack:20807557)] (S) Msg TX to 1:0000000000000001 [8B98] --- Type 0001:01 (IM:StatusResponse) - [1690540325.496697][9488:9490] CHIP:IN: (S) Sending msg 151709016 on secure session with LSID: 38251 - [1690540325.497211][9488:9490] CHIP:EM: >>> [E:48664r S:38251 M:20807558 (Ack:151709016)] (S) Msg RX from 1:0000000000000001 [8B98] --- Type 0000:10 (SecureChannel:StandaloneAck) - [1690540325.497237][9488:9490] CHIP:EM: Found matching exchange: 48664r, Delegate: (nil) - [1690540325.497258][9488:9490] CHIP:EM: Rxd Ack; Removing MessageCounter:151709016 from Retrans Table on exchange 48664r - [1690540381.062201][9488:9490] CHIP:EM: >>> [E:48665r S:38251 M:20807559] (S) Msg RX from 1:0000000000000001 [8B98] --- Type 0001:05 (IM:ReportData) - [1690540381.062234][9488:9490] CHIP:EM: Handling via exchange: 48665r, Delegate: 0x5639a50ebc68 - [1690540381.062272][9488:9490] CHIP:DMG: ReportDataMessage = - [1690540381.062281][9488:9490] CHIP:DMG: { - [1690540381.062289][9488:9490] CHIP:DMG: SubscriptionId = 0x3ef5dc34, - [1690540381.062296][9488:9490] CHIP:DMG: AttributeReportIBs = - [1690540381.062308][9488:9490] CHIP:DMG: [ - [1690540381.062315][9488:9490] CHIP:DMG: AttributeReportIB = - [1690540381.062325][9488:9490] CHIP:DMG: { - [1690540381.062332][9488:9490] CHIP:DMG: AttributeDataIB = - [1690540381.062338][9488:9490] CHIP:DMG: { - [1690540381.062346][9488:9490] CHIP:DMG: DataVersion = 0xc5569959, - [1690540381.062354][9488:9490] CHIP:DMG: AttributePathIB = - [1690540381.062367][9488:9490] CHIP:DMG: { - [1690540381.062375][9488:9490] CHIP:DMG: Endpoint = 0x1, - [1690540381.062383][9488:9490] CHIP:DMG: Cluster = 0x6, - [1690540381.062392][9488:9490] CHIP:DMG: Attribute = 0x0000_4001, - [1690540381.062399][9488:9490] CHIP:DMG: } - [1690540381.062409][9488:9490] CHIP:DMG: - [1690540381.062417][9488:9490] CHIP:DMG: Data = 1, - [1690540381.062423][9488:9490] CHIP:DMG: }, - [1690540381.062433][9488:9490] CHIP:DMG: - [1690540381.062439][9488:9490] CHIP:DMG: }, - [1690540381.062447][9488:9490] CHIP:DMG: - [1690540381.062453][9488:9490] CHIP:DMG: ], - [1690540381.062463][9488:9490] CHIP:DMG: - [1690540381.062470][9488:9490] CHIP:DMG: InteractionModelRevision = 1 - [1690540381.062476][9488:9490] CHIP:DMG: } - [1690540381.062543][9488:9490] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0006 Attribute 0x0000_4001 DataVersion: 3310786905 - [1690540381.062558][9488:9490] CHIP:TOO: OnTime: 1 - [1690540381.062580][9488:9490] CHIP:DMG: Refresh LivenessCheckTime for 104224 milliseconds with SubscriptionId = 0x3ef5dc34 Peer = 01:0000000000000001 - [1690540381.062627][9488:9490] CHIP:EM: <<< [E:48665r S:38251 M:151709017 (Ack:20807559)] (S) Msg TX to 1:0000000000000001 [8B98] --- Type 0001:01 (IM:StatusResponse) - [1690540381.062641][9488:9490] CHIP:IN: (S) Sending msg 151709017 on secure session with LSID: 38251 - [1690540381.063237][9488:9490] CHIP:EM: >>> [E:48665r S:38251 M:20807560 (Ack:151709017)] (S) Msg RX from 1:0000000000000001 [8B98] --- Type 0000:10 (SecureChannel:StandaloneAck) - [1690540381.063261][9488:9490] CHIP:EM: Found matching exchange: 48665r, Delegate: (nil) - [1690540381.063276][9488:9490] CHIP:EM: Rxd Ack; Removing MessageCounter:151709017 from Retrans Table on exchange 48665r - disabled: true - - - label: - "Step 9: CR1 sends a subscription request action for an attribute and - set the MinIntervalFloor value to be greater than MaxIntervalCeiling." - verification: | - Please send the following command from CR1 (the subscription requester) to DUT (the device under test) to activate the subscription for the "on-time" attribute, setting the MinIntervalFloor value to be greater than MaxIntervalCeiling: - - - onoff subscribe on-time 500 100 1 1 --keepSubscriptions true - - On CR1 (chip-tool), verify that the DUT sends an error message, confirming that the subscription is not established successfully - - [1661754615.089845][103654:103659] CHIP:DMG: StatusResponseMessage = - [1661754615.089857][103654:103659] CHIP:DMG: { - [1661754615.089868][103654:103659] CHIP:DMG: Status = 0x80 (INVALID_ACTION), - [1661754615.089879][103654:103659] CHIP:DMG: InteractionModelRevision = 1 - [1661754615.089889][103654:103659] CHIP:DMG: } - [1661754615.089901][103654:103659] CHIP:IM: Received status response, status is 0x80 (INVALID_ACTION) - [1661754615.089927][103654:103659] CHIP:EM: Piggybacking Ack for MessageCounter:223396916 on exchange: 6193i - disabled: true - - - label: - "Step 10: CR1 sends a subscription request to subscribe to a specific - global attribute from all clusters on all endpoints. AttributePath = - [[Attribute = Global Attribute]]. +" - verification: | - any subscribe-by-id 0xFFFFFFFF 0xFFFD 10 300 1 0xFFFF --keepSubscriptions true - - The following log is an example of the output obtained for Attribute 0x0000_FFFD on Endpoint 0 - Pls repeat this for every cluster on every endpoint. The log represents the attributes of clusters found on different endpoints. - - Verify the presence of mandatory global attribute ClusterRevision for every cluster on every endpoint: - - - Verification Instructions: - Please use the provided example log as a guide to verify the attributes for other clusters and endpoints in a similar manner. - [1690541617.461279][9488:9490] CHIP:DMG: } - [1690541617.461374][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0003 Attribute 0x0000_FFFD DataVersion: 124546948 - [1690541617.461379][9488:9490] CHIP:TOO: ClusterRevision: 4 - [1690541617.461388][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0004 Attribute 0x0000_FFFD DataVersion: 1468663600 - [1690541617.461391][9488:9490] CHIP:TOO: ClusterRevision: 4 - [1690541617.461399][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_001D Attribute 0x0000_FFFD DataVersion: 2536415407 - [1690541617.461402][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690541617.461410][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_001E Attribute 0x0000_FFFD DataVersion: 1723648967 - [1690541617.461413][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690541617.461421][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_001F Attribute 0x0000_FFFD DataVersion: 659240739 - [1690541617.461424][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690541617.461432][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0028 Attribute 0x0000_FFFD DataVersion: 3950349597 - [1690541617.461435][9488:9490] CHIP:TOO: ClusterRevision: 2 - [1690541617.461443][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002A Attribute 0x0000_FFFD DataVersion: 1224601682 - [1690541617.461446][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690541617.461454][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002B Attribute 0x0000_FFFD DataVersion: 2744454868 - [1690541617.461456][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690541617.461464][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002C Attribute 0x0000_FFFD DataVersion: 463823876 - [1690541617.461467][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690541617.461475][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002D Attribute 0x0000_FFFD DataVersion: 115397017 - [1690541617.461477][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690541617.461485][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002F Attribute 0x0000_FFFD DataVersion: 85684249 - [1690541617.461488][9488:9490] CHIP:TOO: ClusterRevision: 2 - [1690541617.461496][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0030 Attribute 0x0000_FFFD DataVersion: 75615160 - [1690541617.461498][9488:9490] CHIP:TOO: ClusterRevision: 1 - disabled: true - - - label: - "Step 11: CR1 sends a subscription request to subscribe to a global - attribute on an endpoint on all clusters. AttributePath = [[Attribute - = Global Attribute, Endpoint = EndpointID ]]. +" - verification: | - any subscribe-by-id 0xFFFFFFFF 0xFFFD 10 300 1 0 --keepSubscriptions true - The following log is an example of the output obtained for Attribute 0x0000_FFFD on Endpoint 0 - Pls repeat this for every cluster on endpoint 0. The log represents the attribute of clusters found on endpoint 0. - - Verify the presence of mandatory global attribute ClusterRevision for every cluster on every endpoint: - - - Verification Instructions: - Please use the provided example log as a guide to verify the attributes for other clusters and endpoints in a similar manner. - - [1690542041.905545][9488:9490] CHIP:DMG: InteractionModelRevision = 1 - [1690542041.905546][9488:9490] CHIP:DMG: } - [1690542041.905621][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0003 Attribute 0x0000_FFFD DataVersion: 124546948 - [1690542041.905625][9488:9490] CHIP:TOO: ClusterRevision: 4 - [1690542041.905634][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0004 Attribute 0x0000_FFFD DataVersion: 1468663600 - [1690542041.905637][9488:9490] CHIP:TOO: ClusterRevision: 4 - [1690542041.905646][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_001D Attribute 0x0000_FFFD DataVersion: 2536415407 - [1690542041.905649][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905657][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_001E Attribute 0x0000_FFFD DataVersion: 1723648967 - [1690542041.905659][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905667][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_001F Attribute 0x0000_FFFD DataVersion: 659240739 - [1690542041.905670][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905678][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0028 Attribute 0x0000_FFFD DataVersion: 3950349597 - [1690542041.905680][9488:9490] CHIP:TOO: ClusterRevision: 2 - [1690542041.905688][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002A Attribute 0x0000_FFFD DataVersion: 1224601682 - [1690542041.905691][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905699][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002B Attribute 0x0000_FFFD DataVersion: 2744454868 - [1690542041.905701][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905710][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002C Attribute 0x0000_FFFD DataVersion: 463823876 - [1690542041.905712][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905720][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002D Attribute 0x0000_FFFD DataVersion: 115397017 - [1690542041.905722][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905730][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002F Attribute 0x0000_FFFD DataVersion: 85684249 - [1690542041.905733][9488:9490] CHIP:TOO: ClusterRevision: 2 - [1690542041.905741][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0030 Attribute 0x0000_FFFD DataVersion: 75615160 - [1690542041.905743][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905751][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0031 Attribute 0x0000_FFFD DataVersion: 1962336111 - [1690542041.905753][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905761][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0032 Attribute 0x0000_FFFD DataVersion: 465381371 - [1690542041.905763][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905772][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0033 Attribute 0x0000_FFFD DataVersion: 2781452270 - [1690542041.905774][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905782][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0034 Attribute 0x0000_FFFD DataVersion: 3343308905 - [1690542041.905784][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905792][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0035 Attribute 0x0000_FFFD DataVersion: 1933667935 - [1690542041.905794][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905803][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0036 Attribute 0x0000_FFFD DataVersion: 1917440631 - [1690542041.905806][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905814][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0037 Attribute 0x0000_FFFD DataVersion: 2059544742 - [1690542041.905816][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905824][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0038 Attribute 0x0000_FFFD DataVersion: 292367345 - [1690542041.905826][9488:9490] CHIP:TOO: ClusterRevision: 2 - [1690542041.905835][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_003C Attribute 0x0000_FFFD DataVersion: 4275836516 - [1690542041.905837][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905845][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_003E Attribute 0x0000_FFFD DataVersion: 2334789054 - [1690542041.905848][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905856][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_003F Attribute 0x0000_FFFD DataVersion: 2215403935 - [1690542041.905858][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905866][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0040 Attribute 0x0000_FFFD DataVersion: 1171006049 - [1690542041.905868][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905877][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0041 Attribute 0x0000_FFFD DataVersion: 1339481925 - [1690542041.905879][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905887][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0046 Attribute 0x0000_FFFD DataVersion: 2155717858 - [1690542041.905889][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905897][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0405 Attribute 0x0000_FFFD DataVersion: 2620361579 - [1690542041.906830][9488:9490] CHIP:TOO: ClusterRevision: 3 - [1690542041.906854][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0xFFF1_FC06 Attribute 0x0000_FFFD DataVersion: 2161647034 - [1690542041.906860][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.906886][9488:9490] CHIP:DMG: MoveToState ReadClient[0x7faef801d0f0]: Moving to [AwaitingSu] - [1690542041.906910][9488:9490] CHIP:EM: <<< [E:49949i S:38251 M:151709045 (Ack:20807605)] (S) Msg TX to 1:0000000000000001 [8B98] --- Type 0001:01 (IM:StatusResponse) - [1690542041.906915][9488:9490] CHIP:IN: (S) Sending msg 151709045 on secure session with LSID: 38251 - [1690542041.907098][9488:9490] CHIP:EM: >>> [E:49949i S:38251 M:20807606 (Ack:151709045)] (S) Msg RX from 1:0000000000000001 [8B98] --- Type 0001:04 (IM:SubscribeResponse) - [1690542041.907107][9488:9490] CHIP:EM: Found matching exchange: 49949i, Delegate: 0x7faef801d100 - [1690542041.907113][9488:9490] CHIP:EM: Rxd Ack; Removing MessageCounter:151709045 from Retrans Table on exchange 49949i - [1690542041.907119][9488:9490] CHIP:DMG: SubscribeResponse is received - [1690542041.907126][9488:9490] CHIP:DMG: SubscribeResponseMessage = - [1690542041.907128][9488:9490] CHIP:DMG: { - [1690542041.907131][9488:9490] CHIP:DMG: SubscriptionId = 0x9488dc04, - [1690542041.907134][9488:9490] CHIP:DMG: MaxInterval = 0x12c, - [1690542041.907137][9488:9490] CHIP:DMG: InteractionModelRevision = 1 - [1690542041.907139][9488:9490] CHIP:DMG: } - [1690542041.907144][9488:9490] CHIP:DMG: Subscription established with SubscriptionID = 0x9488dc04 MinInterval = 10s MaxInterval = 300s Peer = 01:0000000000000001 - disabled: true - - - label: - "Step 12: CR1 sends a subscription request to the DUT with both - AttributeRequests and EventRequests as empty" - verification: | - Please send the following command from TH (the subscription requester) to DUT (the device under test) to activate the subscription with both AttributeRequests and EventRequests as empty - - any subscribe-none 10 100 1 --keepSubscriptions 1 - - On CR1 (chip-tool), verify that the DUT sends an error message, confirming that the subscription is not established successfully - [1690884829.708780][84191:84193] CHIP:EM: Rxd Ack; Removing MessageCounter:136461510 from Retrans Table on exchange 23099i - [1690884829.708861][84191:84193] CHIP:DMG: StatusResponseMessage = - [1690884829.708907][84191:84193] CHIP:DMG: { - [1690884829.708947][84191:84193] CHIP:DMG: Status = 0x80 (INVALID_ACTION), - [1690884829.708988][84191:84193] CHIP:DMG: InteractionModelRevision = 1 - [1690884829.709026][84191:84193] CHIP:DMG: } - [1690884829.709064][84191:84193] CHIP:IM: Received status response, status is 0x80 (INVALID_ACTION) - [1690884829.709196][84191:84193] CHIP:EM: <<< [E:23099i S:5058 M:136461511 (Ack:90075666)] (S) Msg TX to 1:0000000000000001 [EAE3] --- Type 0001:01 (IM:StatusResponse) - [1690884829.709252][84191:84193] CHIP:IN: (S) Sending msg 136461511 on secure session with LSID: 5058 - [1690884829.709420][84191:84193] CHIP:DMG: MoveToState ReadClient[0xffff9c005e90]: Moving to [ Idle] - disabled: true diff --git a/src/app/tests/suites/manualTests.json b/src/app/tests/suites/manualTests.json index bee33964dfac50..0e6e045b8ea7f6 100644 --- a/src/app/tests/suites/manualTests.json +++ b/src/app/tests/suites/manualTests.json @@ -124,7 +124,6 @@ "Test_TC_IDM_3_1", "Test_TC_IDM_3_2", "Test_TC_IDM_4_1", - "Test_TC_IDM_4_2", "Test_TC_IDM_4_3", "Test_TC_IDM_4_4", "Test_TC_IDM_5_1", diff --git a/src/app/util/mock/BUILD.gn b/src/app/util/mock/BUILD.gn index db566aad578793..0b99d827403047 100644 --- a/src/app/util/mock/BUILD.gn +++ b/src/app/util/mock/BUILD.gn @@ -56,4 +56,5 @@ source_set("mock_codegen_data_model") { public_configs = [ ":mock_include" ] public_deps += [ ":mock_ember" ] + deps = [ "${chip_root}/src/app/util/persistence:persistence" ] } diff --git a/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml b/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml index 54fe73d5f0df74..84b5720e165fe1 100644 --- a/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml +++ b/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml @@ -203,7 +203,7 @@ limitations under the License. CLIENT_LIST PARTS_LIST - + REACHABLE @@ -2069,7 +2069,7 @@ limitations under the License. - + diff --git a/src/controller/BUILD.gn b/src/controller/BUILD.gn index b4e81158d497e8..1ddbeafaf1fb35 100644 --- a/src/controller/BUILD.gn +++ b/src/controller/BUILD.gn @@ -24,32 +24,23 @@ source_set("nodatamodel") { public_deps = [ "${chip_root}/src/app" ] } -CHIP_CONTROLLER_HEADERS = [ "ExampleOperationalCredentialsIssuer.h" ] -CHIP_READ_CLIENT_HEADERS = [ - "CommissioningWindowOpener.h", - "CurrentFabricRemover.h", -] - -# This source set exists specifically to deny including them without dependencies -# if "controller" sources do not contain them -# -# They are NOT intended to be used directly. -# -# The intent for this is to force gn to be aware that these files are known and -# error out as `include not allowed due to missing dependency` even if -# controller is built without these sources -source_set("gen_check_chip_controller_headers") { - sources = CHIP_CONTROLLER_HEADERS -} - -source_set("gen_check_chip_read_client_headers") { - sources = CHIP_READ_CLIENT_HEADERS -} - source_set("delegates") { sources = [ "OperationalCredentialsDelegate.h" ] } +source_set("interactions") { + sources = [ + "CHIPCluster.h", + "CommandSenderAllocator.h", + "InvokeInteraction.h", + "ReadInteraction.h", + "TypedCommandCallback.h", + "TypedReadCallback.h", + "WriteInteraction.h", + ] + public_deps = [ "${chip_root}/src/app" ] +} + static_library("controller") { output_name = "libChipController" @@ -67,26 +58,23 @@ static_library("controller") { # dependencies "AbstractDnssdDiscoveryController.h", "AutoCommissioner.h", - "CHIPCluster.h", "CHIPCommissionableNodeController.h", "CHIPDeviceController.h", "CHIPDeviceControllerSystemState.h", - "CommandSenderAllocator.h", "CommissioneeDeviceProxy.h", "CommissioningDelegate.h", + "CommissioningWindowOpener.h", "CommissioningWindowParams.h", + "CurrentFabricRemover.h", "DeviceDiscoveryDelegate.h", "DevicePairingDelegate.h", - "InvokeInteraction.h", - "ReadInteraction.h", + "ExampleOperationalCredentialsIssuer.h", "SetUpCodePairer.h", - "TypedCommandCallback.h", - "TypedReadCallback.h", - "WriteInteraction.h", ] + deps = [ "${chip_root}/src/lib/address_resolve" ] + if (chip_controller && chip_build_controller) { - sources += CHIP_CONTROLLER_HEADERS sources += [ "AbstractDnssdDiscoveryController.cpp", "AutoCommissioner.cpp", @@ -100,8 +88,11 @@ static_library("controller") { "ExampleOperationalCredentialsIssuer.cpp", "SetUpCodePairer.cpp", ] + + # ExampleOperationalCredentialsIssuer uses TestGroupData + deps += [ "${chip_root}/src/lib/support:testing" ] + if (chip_enable_read_client) { - sources += CHIP_READ_CLIENT_HEADERS sources += [ "CHIPDeviceController.cpp", "CommissioningWindowOpener.cpp", @@ -110,9 +101,8 @@ static_library("controller") { } } - cflags = [ "-Wconversion" ] - public_deps = [ + ":interactions", "${chip_root}/src/app", "${chip_root}/src/app/server", "${chip_root}/src/lib/core", @@ -127,12 +117,7 @@ static_library("controller") { "${chip_root}/src/transport", ] - deps = [ "${chip_root}/src/lib/address_resolve" ] - - if (chip_controller && chip_build_controller) { - # ExampleOperationalCredentialsIssuer uses TestGroupData - deps += [ "${chip_root}/src/lib/support:testing" ] - } + cflags = [ "-Wconversion" ] public_configs = [ "${chip_root}/src:includes" ] } diff --git a/src/controller/CHIPCluster.h b/src/controller/CHIPCluster.h index c425b344c68962..b3f35a9ac6d04c 100644 --- a/src/controller/CHIPCluster.h +++ b/src/controller/CHIPCluster.h @@ -26,9 +26,8 @@ #pragma once -#include "app/ConcreteCommandPath.h" #include -#include +#include #include #include #include diff --git a/src/controller/CHIPDeviceControllerFactory.cpp b/src/controller/CHIPDeviceControllerFactory.cpp index e7e718964d3745..a5fe94dcd451e4 100644 --- a/src/controller/CHIPDeviceControllerFactory.cpp +++ b/src/controller/CHIPDeviceControllerFactory.cpp @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -100,6 +101,10 @@ CHIP_ERROR DeviceControllerFactory::ReinitSystemStateIfNecessary() params.certificateValidityPolicy = mCertificateValidityPolicy; params.sessionResumptionStorage = mSessionResumptionStorage; + // re-initialization keeps any previously initialized values. The only place where + // a provider exists is in the InteractionModelEngine, so just say "keep it as is". + params.dataModelProvider = app::InteractionModelEngine::GetInstance()->GetDataModelProvider(); + return InitSystemState(params); } @@ -127,6 +132,13 @@ CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params) ChipLogError(Controller, "Warning: Device Controller Factory should be with a CHIP Device Layer..."); #endif // CONFIG_DEVICE_LAYER + if (params.dataModelProvider == nullptr) + { + ChipLogError(AppServer, "Device Controller Factory requires a `dataModelProvider` value."); + ChipLogError(AppServer, "For backwards compatibility, you likely can use `CodegenDataModelProviderInstance()`"); + } + + VerifyOrReturnError(params.dataModelProvider != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(stateParams.systemLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(stateParams.udpEndPointManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT); @@ -238,6 +250,16 @@ CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params) ReturnErrorOnFailure(stateParams.unsolicitedStatusHandler->Init(stateParams.exchangeMgr)); ReturnErrorOnFailure(stateParams.bdxTransferServer->Init(stateParams.systemLayer, stateParams.exchangeMgr)); + chip::app::InteractionModelEngine * interactionModelEngine = chip::app::InteractionModelEngine::GetInstance(); + + // Note placement of this BEFORE `InitDataModelHandler` since InitDataModelHandler may + // rely on ember (does emberAfInit() and configure which may load data from NVM). + // + // Expected forward path is that we will move move and more things inside datamodel + // provider (e.g. storage settings) so we want datamodelprovider available before + // `InitDataModelHandler`. + interactionModelEngine->SetDataModelProvider(params.dataModelProvider); + InitDataModelHandler(); ReturnErrorOnFailure(Dnssd::Resolver::Instance().Init(stateParams.udpEndPointManager)); @@ -295,8 +317,8 @@ CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params) stateParams.caseSessionManager = Platform::New(); ReturnErrorOnFailure(stateParams.caseSessionManager->Init(stateParams.systemLayer, sessionManagerConfig)); - ReturnErrorOnFailure(chip::app::InteractionModelEngine::GetInstance()->Init( - stateParams.exchangeMgr, stateParams.fabricTable, stateParams.reportScheduler, stateParams.caseSessionManager)); + ReturnErrorOnFailure(interactionModelEngine->Init(stateParams.exchangeMgr, stateParams.fabricTable, stateParams.reportScheduler, + stateParams.caseSessionManager)); // store the system state mSystemState = chip::Platform::New(std::move(stateParams)); diff --git a/src/controller/CHIPDeviceControllerFactory.h b/src/controller/CHIPDeviceControllerFactory.h index 16e2ad487126b9..0efe4518337929 100644 --- a/src/controller/CHIPDeviceControllerFactory.h +++ b/src/controller/CHIPDeviceControllerFactory.h @@ -160,6 +160,11 @@ struct FactoryInitParams /* The port used for operational communication to listen for and send messages over UDP/TCP. * The default value of `0` will pick any available port. */ uint16_t listenPort = 0; + + // MUST NOT be null during initialization: every application must define the + // data model it wants to use. Backwards-compatibility can use `CodegenDataModelProviderInstance` + // for ember/zap-generated models. + chip::app::DataModel::Provider * dataModelProvider = nullptr; }; class DeviceControllerFactory diff --git a/src/controller/ExamplePersistentStorage.cpp b/src/controller/ExamplePersistentStorage.cpp index 599f0980db99b3..609b8ece98a2d3 100644 --- a/src/controller/ExamplePersistentStorage.cpp +++ b/src/controller/ExamplePersistentStorage.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -30,7 +31,6 @@ using Section = std::map; using Sections = std::map; using namespace ::chip; -using namespace ::chip::Controller; using namespace ::chip::IniEscaping; using namespace ::chip::Logging; diff --git a/src/controller/ExamplePersistentStorage.h b/src/controller/ExamplePersistentStorage.h index 685bcfdd4ae6d9..a82cdf9037357c 100644 --- a/src/controller/ExamplePersistentStorage.h +++ b/src/controller/ExamplePersistentStorage.h @@ -18,11 +18,13 @@ #pragma once -#include -#include -#include +#include +#include +#include #include +#include + class PersistentStorage : public chip::PersistentStorageDelegate { public: diff --git a/src/controller/ReadInteraction.h b/src/controller/ReadInteraction.h index 8eae6613ddf10e..466e8eadbf1371 100644 --- a/src/controller/ReadInteraction.h +++ b/src/controller/ReadInteraction.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff --git a/src/controller/data_model/BUILD.gn b/src/controller/data_model/BUILD.gn index a0b57e7b91fc1e..a9a0ca370b5d3a 100644 --- a/src/controller/data_model/BUILD.gn +++ b/src/controller/data_model/BUILD.gn @@ -42,5 +42,4 @@ chip_codegen("cluster-tlv-metadata") { chip_data_model("data_model") { zap_file = "controller-clusters.zap" - allow_circular_includes_from = [ "${chip_root}/src/controller" ] } diff --git a/src/controller/java/AndroidDeviceControllerWrapper.cpp b/src/controller/java/AndroidDeviceControllerWrapper.cpp index 3eb6dd82e459cd..2582e8f0e7afd5 100644 --- a/src/controller/java/AndroidDeviceControllerWrapper.cpp +++ b/src/controller/java/AndroidDeviceControllerWrapper.cpp @@ -25,17 +25,16 @@ #include +#include #include - -#include -#include -#include - #include #include #include #include #include +#include +#include +#include #include #include #include @@ -210,6 +209,7 @@ AndroidDeviceControllerWrapper * AndroidDeviceControllerWrapper::AllocateNew( setupParams.defaultCommissioner = &wrapper->mAutoCommissioner; initParams.fabricIndependentStorage = wrapperStorage; initParams.sessionKeystore = &wrapper->mSessionKeystore; + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); wrapper->mGroupDataProvider.SetStorageDelegate(wrapperStorage); wrapper->mGroupDataProvider.SetSessionKeystore(initParams.sessionKeystore); diff --git a/src/controller/python/ChipDeviceController-ScriptBinding.cpp b/src/controller/python/ChipDeviceController-ScriptBinding.cpp index 11fdf763da558d..b5dab55f84b6d8 100644 --- a/src/controller/python/ChipDeviceController-ScriptBinding.cpp +++ b/src/controller/python/ChipDeviceController-ScriptBinding.cpp @@ -42,6 +42,7 @@ #include #include +#include #include #include #include @@ -271,6 +272,7 @@ PyChipError pychip_DeviceController_StackInit(Controller::Python::StorageAdapter factoryParams.fabricIndependentStorage = storageAdapter; factoryParams.sessionKeystore = &sSessionKeystore; + factoryParams.dataModelProvider = app::CodegenDataModelProviderInstance(); sICDClientStorage.Init(storageAdapter, &sSessionKeystore); diff --git a/src/controller/python/chip/internal/CommissionerImpl.cpp b/src/controller/python/chip/internal/CommissionerImpl.cpp index 709202426755a5..31824508d92f02 100644 --- a/src/controller/python/chip/internal/CommissionerImpl.cpp +++ b/src/controller/python/chip/internal/CommissionerImpl.cpp @@ -16,6 +16,7 @@ */ #include +#include #include #include #include @@ -135,6 +136,7 @@ extern "C" chip::Controller::DeviceCommissioner * pychip_internal_Commissioner_N factoryParams.fabricIndependentStorage = &gServerStorage; factoryParams.sessionKeystore = &gSessionKeystore; + factoryParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); // Initialize group data provider for local group key state and IPKs gGroupDataProvider.SetStorageDelegate(&gServerStorage); diff --git a/src/controller/python/chip/server/ServerInit.cpp b/src/controller/python/chip/server/ServerInit.cpp index 39edd7a2ad6b2c..83bb8acefecd89 100644 --- a/src/controller/python/chip/server/ServerInit.cpp +++ b/src/controller/python/chip/server/ServerInit.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -161,6 +162,7 @@ PyChipError pychip_server_native_init() // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; PyReturnErrorOnFailure(ToPyChipError(initParams.InitializeStaticResourcesBeforeServerInit())); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); initParams.operationalServicePort = CHIP_PORT; initParams.userDirectedCommissioningPort = CHIP_UDC_PORT; diff --git a/src/controller/tests/TestEventChunking.cpp b/src/controller/tests/TestEventChunking.cpp index d0f4999ee782d3..17e8ece034f1b3 100644 --- a/src/controller/tests/TestEventChunking.cpp +++ b/src/controller/tests/TestEventChunking.cpp @@ -288,6 +288,7 @@ TEST_F(TestEventChunking, TestEventChunking) // Initialize the ember side server logic CodegenDataModelProviderInstance()->Shutdown(); + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. @@ -355,6 +356,7 @@ TEST_F(TestEventChunking, TestMixedEventsAndAttributesChunking) // Initialize the ember side server logic CodegenDataModelProviderInstance()->Shutdown(); + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. @@ -432,6 +434,7 @@ TEST_F(TestEventChunking, TestMixedEventsAndLargeAttributesChunking) // Initialize the ember side server logic CodegenDataModelProviderInstance()->Shutdown(); + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. diff --git a/src/controller/tests/TestReadChunking.cpp b/src/controller/tests/TestReadChunking.cpp index 989d91005290fe..8614b6acf4ad7d 100644 --- a/src/controller/tests/TestReadChunking.cpp +++ b/src/controller/tests/TestReadChunking.cpp @@ -25,6 +25,7 @@ #include "app-common/zap-generated/ids/Attributes.h" #include "app-common/zap-generated/ids/Clusters.h" #include "app/ConcreteAttributePath.h" +#include "app/codegen-data-model-provider/Instance.h" #include "protocols/interaction_model/Constants.h" #include #include @@ -481,6 +482,7 @@ TEST_F(TestReadChunking, TestChunking) app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance(); // Initialize the ember side server logic + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. @@ -543,6 +545,7 @@ TEST_F(TestReadChunking, TestListChunking) app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance(); // Initialize the ember side server logic + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. @@ -644,6 +647,7 @@ TEST_F(TestReadChunking, TestBadChunking) app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance(); // Initialize the ember side server logic + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); app::InteractionModelEngine::GetInstance()->GetReportingEngine().SetWriterReserved(0); @@ -695,6 +699,7 @@ TEST_F(TestReadChunking, TestDynamicEndpoint) app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance(); // Initialize the ember side server logic + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. diff --git a/src/controller/tests/TestWriteChunking.cpp b/src/controller/tests/TestWriteChunking.cpp index 4efc09818694e2..f2f5a0822b48d2 100644 --- a/src/controller/tests/TestWriteChunking.cpp +++ b/src/controller/tests/TestWriteChunking.cpp @@ -21,16 +21,16 @@ #include -#include "app-common/zap-generated/ids/Attributes.h" -#include "app-common/zap-generated/ids/Clusters.h" -#include "app/ConcreteAttributePath.h" -#include "protocols/interaction_model/Constants.h" #include +#include +#include #include #include #include +#include #include #include +#include #include #include #include @@ -39,6 +39,7 @@ #include #include #include +#include using namespace chip; using namespace chip::app; @@ -211,6 +212,7 @@ TEST_F(TestWriteChunking, TestListChunking) auto sessionHandle = GetSessionBobToAlice(); // Initialize the ember side server logic + app::InteractionModelEngine::GetInstance()->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. @@ -284,6 +286,7 @@ TEST_F(TestWriteChunking, TestBadChunking) bool atLeastOneRequestFailed = false; // Initialize the ember side server logic + app::InteractionModelEngine::GetInstance()->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. @@ -363,6 +366,7 @@ TEST_F(TestWriteChunking, TestConflictWrite) auto sessionHandle = GetSessionBobToAlice(); // Initialize the ember side server logic + app::InteractionModelEngine::GetInstance()->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. @@ -437,6 +441,7 @@ TEST_F(TestWriteChunking, TestNonConflictWrite) auto sessionHandle = GetSessionBobToAlice(); // Initialize the ember side server logic + app::InteractionModelEngine::GetInstance()->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. @@ -585,6 +590,7 @@ void TestWriteChunking::RunTest(Instructions instructions) TEST_F(TestWriteChunking, TestTransactionalList) { // Initialize the ember side server logic + app::InteractionModelEngine::GetInstance()->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. diff --git a/src/crypto/CHIPCryptoPAL.h b/src/crypto/CHIPCryptoPAL.h index 45e13f26bb782c..d2915f5d3c2836 100644 --- a/src/crypto/CHIPCryptoPAL.h +++ b/src/crypto/CHIPCryptoPAL.h @@ -900,6 +900,13 @@ class Hash_SHA256_stream */ CHIP_ERROR Begin(); + /** + * @brief check if the digest computation has been initialized. + * + * @return True if the context is correctly initialized; otherwise, false. + */ + bool IsInitialized(); + /** * @brief Add some data to the digest computation, updating internal state. * @@ -942,9 +949,6 @@ class Hash_SHA256_stream private: HashSHA256OpaqueContext mContext; -#if CHIP_CRYPTO_BORINGSSL || CHIP_CRYPTO_OPENSSL - bool mInitialized = false; -#endif }; class HKDF_sha diff --git a/src/crypto/CHIPCryptoPALOpenSSL.cpp b/src/crypto/CHIPCryptoPALOpenSSL.cpp index 033be4488844b3..e1a8acb55fe5d5 100644 --- a/src/crypto/CHIPCryptoPALOpenSSL.cpp +++ b/src/crypto/CHIPCryptoPALOpenSSL.cpp @@ -449,7 +449,7 @@ static inline EVP_MD_CTX * to_inner_hash_evp_md_ctx(HashSHA256OpaqueContext * co return *SafePointerCast(context); } -Hash_SHA256_stream::Hash_SHA256_stream() : mInitialized(false) +Hash_SHA256_stream::Hash_SHA256_stream() { set_inner_hash_evp_md_ctx(&mContext, nullptr); } @@ -470,14 +470,27 @@ CHIP_ERROR Hash_SHA256_stream::Begin() const int result = EVP_DigestInit_ex(mdctx, _digestForType(DigestType::SHA256), nullptr); VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL); - mInitialized = true; return CHIP_NO_ERROR; } +bool Hash_SHA256_stream::IsInitialized() +{ + EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext); + VerifyOrReturnValue(mdctx != nullptr, false); + +// Verify that the EVP_MD_CTX is initialized to SHA256 (ensures that EVP_DigestInit_ex was called) +#if CHIP_CRYPTO_BORINGSSL + return EVP_MD_CTX_md(mdctx) == _digestForType(DigestType::SHA256); +#else + // EVP_MD_CTX_md() was Deprecated in OPENSSL 3.0; However, BoringSSL does not support EVP_MD_CTX_get0_md() yet + return EVP_MD_CTX_get0_md(mdctx) == _digestForType(DigestType::SHA256); +#endif +} + CHIP_ERROR Hash_SHA256_stream::AddData(const ByteSpan data) { - VerifyOrReturnError(mInitialized, CHIP_ERROR_UNINITIALIZED); + VerifyOrReturnError(IsInitialized(), CHIP_ERROR_UNINITIALIZED, Clear()); EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext); VerifyOrReturnError(mdctx != nullptr, CHIP_ERROR_INTERNAL); @@ -492,7 +505,7 @@ CHIP_ERROR Hash_SHA256_stream::AddData(const ByteSpan data) CHIP_ERROR Hash_SHA256_stream::GetDigest(MutableByteSpan & out_buffer) { - VerifyOrReturnError(mInitialized, CHIP_ERROR_UNINITIALIZED); + VerifyOrReturnError(IsInitialized(), CHIP_ERROR_UNINITIALIZED, Clear()); EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext); @@ -519,7 +532,7 @@ CHIP_ERROR Hash_SHA256_stream::Finish(MutableByteSpan & out_buffer) unsigned int size; VerifyOrReturnError(out_buffer.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL); - VerifyOrReturnError(mInitialized, CHIP_ERROR_UNINITIALIZED); + VerifyOrReturnError(IsInitialized(), CHIP_ERROR_UNINITIALIZED, Clear()); EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext); @@ -541,7 +554,6 @@ void Hash_SHA256_stream::Clear() EVP_MD_CTX_free(mdctx); set_inner_hash_evp_md_ctx(&mContext, nullptr); - mInitialized = false; OPENSSL_cleanse(this, sizeof(*this)); } diff --git a/src/darwin/Framework/CHIP/MTRCertificates.mm b/src/darwin/Framework/CHIP/MTRCertificates.mm index 7dcec96cba695b..510bd3a53acf91 100644 --- a/src/darwin/Framework/CHIP/MTRCertificates.mm +++ b/src/darwin/Framework/CHIP/MTRCertificates.mm @@ -152,24 +152,7 @@ + (MTRCertificateDERBytes _Nullable)createOperationalCertificate:(id + (BOOL)keypair:(id)keypair matchesCertificate:(NSData *)certificate { P256PublicKey keypairPubKey; - SecKeyRef publicKey = NULL; - - if ([keypair respondsToSelector:@selector(copyPublicKey)]) { - publicKey = [keypair copyPublicKey]; - } else { - publicKey = [keypair publicKey]; - if (publicKey) { - CFRetain(publicKey); - } - } - - CHIP_ERROR err = MTRP256KeypairBridge::MatterPubKeyFromSecKeyRef(publicKey, &keypairPubKey); - - if (publicKey != NULL) { - CFRelease(publicKey); - publicKey = NULL; - } - + CHIP_ERROR err = MTRP256KeypairBridge::MatterPubKeyFromMTRKeypair(keypair, &keypairPubKey); if (err != CHIP_NO_ERROR) { MTR_LOG_ERROR("Can't extract public key from keypair: %s", ErrorStr(err)); return NO; diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.h b/src/darwin/Framework/CHIP/MTRDeviceController.h index 35a20c1ab43e25..3ad0c37ea025bb 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController.h +++ b/src/darwin/Framework/CHIP/MTRDeviceController.h @@ -98,12 +98,13 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) * Then a PASE session will be established with the device, unless an error * occurs. MTRDeviceControllerDelegate will be notified as follows: * - * * Discovery fails: onStatusUpdate with MTRCommissioningStatusFailed. + * * Discovery fails: controller:statusUpdate: with MTRCommissioningStatusFailed. * - * * Discovery succeeds but commissioning session setup fails: onPairingComplete - * with an error. + * * Commissioning session setup fails: + * controller:commissioningSessionEstablishmentDone: with non-nil error. * - * * Commissioning session setup succeeds: onPairingComplete with no error. + * * Commissioning session setup succeeds: + * controller:commissioningSessionEstablishmentDone: with nil error. * * Once a commissioning session is set up, getDeviceBeingCommissioned * can be used to get an MTRBaseDevice and discover what sort of network @@ -132,11 +133,13 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) * Then a PASE session will be established with the device, unless an error * occurs. MTRDeviceControllerDelegate will be notified as follows: * - * * Invalid connection information: onStatusUpdate with MTRCommissioningStatusFailed. + * * Invalid connection information: controller:statusUpdate: with MTRCommissioningStatusFailed. * - * * Commissioning session setup fails: onPairingComplete with an error. + * * Commissioning session setup fails: + * controller:commissioningSessionEstablishmentDone: with non-nil error. * - * * Commissioning session setup succeeds: onPairingComplete with no error. + * * Commissioning session setup succeeds: + * controller:commissioningSessionEstablishmentDone: with nil error. * * Once a commissioning session is set up, getDeviceBeingCommissioned * can be used to get an MTRBaseDevice and discover what sort of network diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.mm b/src/darwin/Framework/CHIP/MTRDeviceController.mm index 5cee77cb663bb8..3b222a1e3eccfc 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController.mm @@ -371,17 +371,22 @@ - (MTRDevice *)_setupDeviceForNodeID:(NSNumber *)nodeID prefetchedClusterData:(N return [[MTRDevice alloc] initForSubclassesWithNodeID:nodeID controller:self]; } -- (MTRDevice *)deviceForNodeID:(NSNumber *)nodeID +- (MTRDevice * _Nullable)_deviceForNodeID:(NSNumber *)nodeID createIfNeeded:(BOOL)createIfNeeded { std::lock_guard lock(*self.deviceMapLock); MTRDevice * deviceToReturn = [_nodeIDToDeviceMap objectForKey:nodeID]; - if (!deviceToReturn) { + if (!deviceToReturn && createIfNeeded) { deviceToReturn = [self _setupDeviceForNodeID:nodeID prefetchedClusterData:nil]; } return deviceToReturn; } +- (MTRDevice *)deviceForNodeID:(NSNumber *)nodeID +{ + return [self _deviceForNodeID:nodeID createIfNeeded:YES]; +} + - (void)removeDevice:(MTRDevice *)device { std::lock_guard lock(*self.deviceMapLock); diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm index e287ef0446593f..4eb7328949ec0a 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm @@ -50,6 +50,7 @@ #import +#include #include #include #include @@ -398,6 +399,7 @@ - (BOOL)_startControllerFactory:(MTRDeviceControllerFactoryParams *)startupParam params.opCertStore = _opCertStore; params.certificateValidityPolicy = &_certificateValidityPolicy; params.sessionResumptionStorage = _sessionResumptionStorage; + params.dataModelProvider = app::CodegenDataModelProviderInstance(); SuccessOrExit(err = _controllerFactory->Init(params)); } @@ -819,24 +821,7 @@ - (BOOL)findMatchingFabric:(FabricTable &)fabricTable } else { // No root certificate means the nocSigner is using the root keys, because // consumers must provide a root certificate whenever an ICA is used. - SecKeyRef publicKey = NULL; - - if ([params.nocSigner respondsToSelector:@selector(copyPublicKey)]) { - publicKey = [params.nocSigner copyPublicKey]; - } else { - publicKey = [params.nocSigner publicKey]; - if (publicKey) { - CFRetain(publicKey); - } - } - - CHIP_ERROR err = MTRP256KeypairBridge::MatterPubKeyFromSecKeyRef(publicKey, &pubKey); - - if (publicKey != NULL) { - CFRelease(publicKey); - publicKey = NULL; - } - + CHIP_ERROR err = MTRP256KeypairBridge::MatterPubKeyFromMTRKeypair(params.nocSigner, &pubKey); if (err != CHIP_NO_ERROR) { MTR_LOG_ERROR("Can't extract public key from MTRKeypair: %s", ErrorStr(err)); return NO; diff --git a/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm b/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm index 4dfffcbb8907b3..99398867ccfa68 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm @@ -1619,12 +1619,9 @@ - (void)invalidateCASESessionForNode:(NSNumber *)nodeID; - (void)operationalInstanceAdded:(NSNumber *)nodeID { - // Don't use deviceForNodeID here, because we don't want to create the - // device if it does not already exist. - os_unfair_lock_lock(self.deviceMapLock); - MTRDevice * device = [self.nodeIDToDeviceMap objectForKey:nodeID]; - os_unfair_lock_unlock(self.deviceMapLock); - + // If we don't have an existing MTRDevice for this node ID, that's fine; + // nothing to do. + MTRDevice * device = [self _deviceForNodeID:nodeID createIfNeeded:NO]; if (device == nil) { return; } diff --git a/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h b/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h index 8fc93b6235015c..0ca85b1f222917 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h +++ b/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h @@ -107,6 +107,8 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - Device-specific data and SDK access // DeviceController will act as a central repository for this opaque dictionary that MTRDevice manages - (MTRDevice *)deviceForNodeID:(NSNumber *)nodeID; +// _deviceForNodeID:createIfNeeded: can only return nil if NO is passed for createIfNeeded. +- (MTRDevice * _Nullable)_deviceForNodeID:(NSNumber *)nodeID createIfNeeded:(BOOL)createIfNeeded; /** * _setupDeviceForNodeID is a hook expected to be implemented by subclasses to * actually allocate a device object of the right type. diff --git a/src/darwin/Framework/CHIP/MTRDeviceController_XPC.mm b/src/darwin/Framework/CHIP/MTRDeviceController_XPC.mm index 9b9a87bb97a5cc..827dad526025d0 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController_XPC.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController_XPC.mm @@ -487,7 +487,7 @@ - (oneway void)controller:(NSUUID *)controller controllerConfigurationUpdated:(N continue; } - auto * device = static_cast([self deviceForNodeID:nodeID]); + auto * device = static_cast([self _deviceForNodeID:nodeID createIfNeeded:NO]); [device device:nodeID internalStateUpdated:deviceInternalState]; } } diff --git a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm index 35cfbcf7d8ceb1..0fa798e8fa3d79 100644 --- a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm +++ b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm @@ -3799,7 +3799,14 @@ - (NSUInteger)unitTestAttributeCount - (void)setPersistedClusterData:(NSDictionary *)clusterData { + [self _doSetPersistedClusterData:clusterData]; + + // Log after we do the state update, so the log includes the data we just set. MTR_LOG("%@ setPersistedClusterData count: %lu", self, static_cast(clusterData.count)); +} + +- (void)_doSetPersistedClusterData:(NSDictionary *)clusterData +{ if (!clusterData.count) { return; } diff --git a/src/darwin/Framework/CHIP/MTROTAImageTransferHandler.h b/src/darwin/Framework/CHIP/MTROTAImageTransferHandler.h new file mode 100644 index 00000000000000..bc45f6e0aed849 --- /dev/null +++ b/src/darwin/Framework/CHIP/MTROTAImageTransferHandler.h @@ -0,0 +1,79 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#include + +NS_ASSUME_NONNULL_BEGIN + +@class MTROTAImageTransferHandlerWrapper; + +/** + * This class handles the BDX events for a BDX transfer session. + * + * This object may be destroyed directly, when not processing some call it made, to interrupt the BDX + * transfer. Specifically, this has to be done if the fabric it's associated with is shut down. This + * method of interrupting the BDX transfer will not notify the peer that we are interrupting and it will + * keep waiting until it times out. + * + * If not otherwise destroyed, this object will destroy itself when the transfer completes. + */ +class MTROTAImageTransferHandler : public chip::bdx::AsyncResponder { +public: + MTROTAImageTransferHandler(chip::System::Layer * layer); + ~MTROTAImageTransferHandler(); + + chip::FabricIndex GetPeerFabricIndex() { return mPeer.GetFabricIndex(); } + +protected: + CHIP_ERROR OnMessageReceived(chip::Messaging::ExchangeContext * ec, const chip::PayloadHeader & payloadHeader, + chip::System::PacketBufferHandle && payload) override; + + void HandleTransferSessionOutput(chip::bdx::TransferSession::OutputEvent & event) override; + +private: + CHIP_ERROR Init(chip::Messaging::ExchangeContext * exchangeCtx); + + CHIP_ERROR OnTransferSessionBegin(const chip::bdx::TransferSession::OutputEventType event); + + CHIP_ERROR OnTransferSessionEnd(const chip::bdx::TransferSession::OutputEventType eventType); + + CHIP_ERROR OnBlockQuery(const chip::bdx::TransferSession::OutputEventType eventType, uint64_t bytesToSkip); + + chip::ScopedNodeId GetPeerScopedNodeId(chip::Messaging::ExchangeContext * exchangeCtx); + + void InvokeTransferSessionEndCallback(CHIP_ERROR error); + + void DestroySelf() override; + + // The scoped node id of the node with which the BDX session is established. + chip::ScopedNodeId mPeer; + + // The OTA provider delegate that is responding to the BDX transfer request. + id mDelegate = nil; + chip::System::Layer * mSystemLayer = nil; + + // The queue mDelegate must be called on. + dispatch_queue_t mDelegateNotificationQueue = nil; + + MTROTAImageTransferHandlerWrapper * mOTAImageTransferHandlerWrapper; + + bool mNeedToCallTransferSessionEnd = false; +}; + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTROTAImageTransferHandler.mm b/src/darwin/Framework/CHIP/MTROTAImageTransferHandler.mm new file mode 100644 index 00000000000000..efa84ef9168a8e --- /dev/null +++ b/src/darwin/Framework/CHIP/MTROTAImageTransferHandler.mm @@ -0,0 +1,401 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "MTROTAImageTransferHandler.h" +#import "MTRDeviceControllerFactory_Internal.h" +#import "MTRDeviceController_Internal.h" +#import "MTRError_Internal.h" +#import "MTROTAUnsolicitedBDXMessageHandler.h" +#import "NSStringSpanConversion.h" + +using namespace chip; +using namespace chip::bdx; +using namespace chip::app; + +constexpr uint32_t kMaxBdxBlockSize = 1024; + +// Timeout for the BDX transfer session. The OTA Spec mandates this should be >= 5 minutes. +constexpr System::Clock::Timeout kBdxTimeout = System::Clock::Seconds16(5 * 60); + +constexpr bdx::TransferRole kBdxRole = bdx::TransferRole::kSender; + +// An ARC-managed object that lets us do weak references to a MTROTAImageTransferHandler +// (which is a C++ object). +@interface MTROTAImageTransferHandlerWrapper : NSObject +- (instancetype)initWithMTROTAImageTransferHandler:(MTROTAImageTransferHandler *)otaImageTransferHandler; + +// Non-atomic property since it's read or written only on the Matter queue. +@property (nonatomic, nullable, readwrite, assign) MTROTAImageTransferHandler * otaImageTransferHandler; +@end + +@implementation MTROTAImageTransferHandlerWrapper + +- (instancetype)initWithMTROTAImageTransferHandler:(MTROTAImageTransferHandler *)otaImageTransferHandler +{ + if (self = [super init]) { + _otaImageTransferHandler = otaImageTransferHandler; + } + return self; +} +@end + +MTROTAImageTransferHandler::MTROTAImageTransferHandler(chip::System::Layer * layer) +{ + assertChipStackLockedByCurrentThread(); + + mSystemLayer = layer; + + MTROTAUnsolicitedBDXMessageHandler::GetInstance()->OnTransferHandlerCreated(this); + mOTAImageTransferHandlerWrapper = [[MTROTAImageTransferHandlerWrapper alloc] initWithMTROTAImageTransferHandler:this]; +} + +CHIP_ERROR MTROTAImageTransferHandler::Init(Messaging::ExchangeContext * exchangeCtx) +{ + assertChipStackLockedByCurrentThread(); + + mPeer = GetPeerScopedNodeId(exchangeCtx); + auto * controller = [[MTRDeviceControllerFactory sharedInstance] runningControllerForFabricIndex:mPeer.GetFabricIndex()]; + VerifyOrReturnError(controller != nil, CHIP_ERROR_INCORRECT_STATE); + + mDelegate = controller.otaProviderDelegate; + mDelegateNotificationQueue = controller.otaProviderDelegateQueue; + + // We should have already checked that this controller supports OTA. + VerifyOrReturnError(mDelegate != nil, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mDelegateNotificationQueue != nil, CHIP_ERROR_INCORRECT_STATE); + + BitFlags flags(bdx::TransferControlFlags::kReceiverDrive); + + return AsyncResponder::Init(mSystemLayer, exchangeCtx, kBdxRole, flags, kMaxBdxBlockSize, kBdxTimeout); +} + +MTROTAImageTransferHandler::~MTROTAImageTransferHandler() +{ + assertChipStackLockedByCurrentThread(); + + if (mNeedToCallTransferSessionEnd) { + // TODO: Store the actual error involved in error cases, so we can pass the right thing here. + InvokeTransferSessionEndCallback(CHIP_ERROR_INTERNAL); + } + + MTROTAUnsolicitedBDXMessageHandler::GetInstance()->OnTransferHandlerDestroyed(this); + mOTAImageTransferHandlerWrapper.otaImageTransferHandler = nullptr; +} + +CHIP_ERROR MTROTAImageTransferHandler::OnTransferSessionBegin(const TransferSession::OutputEventType eventType) +{ + assertChipStackLockedByCurrentThread(); + + uint16_t fdl = 0; + auto fd = mTransfer.GetFileDesignator(fdl); + VerifyOrReturnError(fdl <= bdx::kMaxFileDesignatorLen, CHIP_ERROR_INCORRECT_STATE); + CharSpan fileDesignatorSpan(Uint8::to_const_char(fd), fdl); + + auto fileDesignator = AsString(fileDesignatorSpan); + if (fileDesignator == nil) { + return CHIP_ERROR_INCORRECT_STATE; + } + + auto offset = @(mTransfer.GetStartOffset()); + + auto * controller = [[MTRDeviceControllerFactory sharedInstance] runningControllerForFabricIndex:mPeer.GetFabricIndex()]; + VerifyOrReturnError(controller != nil, CHIP_ERROR_INCORRECT_STATE); + + MTROTAImageTransferHandlerWrapper * __weak weakWrapper = mOTAImageTransferHandlerWrapper; + + auto completionHandler = ^(NSError * _Nullable error) { + [controller + asyncDispatchToMatterQueue:^() { + assertChipStackLockedByCurrentThread(); + + // Check if the OTA image transfer handler is still valid. If not, return from the completion handler. + MTROTAImageTransferHandlerWrapper * strongWrapper = weakWrapper; + if (!strongWrapper || !strongWrapper.otaImageTransferHandler) { + return; + } + + if (error != nil) { + CHIP_ERROR err = [MTRError errorToCHIPErrorCode:error]; + LogErrorOnFailure(err); + NotifyEventHandled(eventType, err); + return; + } + + // bdx::TransferSession will automatically reject a transfer if there are no + // common supported control modes. It will also default to the smaller + // block size. + TransferSession::TransferAcceptData acceptData; + acceptData.ControlMode = bdx::TransferControlFlags::kReceiverDrive; + acceptData.MaxBlockSize = mTransfer.GetTransferBlockSize(); + acceptData.StartOffset = mTransfer.GetStartOffset(); + acceptData.Length = mTransfer.GetTransferLength(); + + CHIP_ERROR err = mTransfer.AcceptTransfer(acceptData); + LogErrorOnFailure(err); + NotifyEventHandled(eventType, err); + } + errorHandler:^(NSError *) { + // Not much we can do here, but if the controller is shut down we + // should already have been destroyed anyway. + }]; + }; + + auto nodeId = @(mPeer.GetNodeId()); + + auto strongDelegate = mDelegate; + auto delegateQueue = mDelegateNotificationQueue; + if (strongDelegate == nil || delegateQueue == nil) { + LogErrorOnFailure(CHIP_ERROR_INCORRECT_STATE); + return CHIP_ERROR_INCORRECT_STATE; + } + + dispatch_async(delegateQueue, ^{ + if ([strongDelegate respondsToSelector:@selector + (handleBDXTransferSessionBeginForNodeID:controller:fileDesignator:offset:completion:)]) { + [strongDelegate handleBDXTransferSessionBeginForNodeID:nodeId + controller:controller + fileDesignator:fileDesignator + offset:offset + completion:completionHandler]; + } else { + [strongDelegate handleBDXTransferSessionBeginForNodeID:nodeId + controller:controller + fileDesignator:fileDesignator + offset:offset + completionHandler:completionHandler]; + } + }); + mNeedToCallTransferSessionEnd = true; + return CHIP_NO_ERROR; +} + +void MTROTAImageTransferHandler::InvokeTransferSessionEndCallback(CHIP_ERROR error) +{ + assertChipStackLockedByCurrentThread(); + + mNeedToCallTransferSessionEnd = false; + + auto * controller = [[MTRDeviceControllerFactory sharedInstance] runningControllerForFabricIndex:mPeer.GetFabricIndex()]; + VerifyOrReturn(controller != nil); + auto nodeId = @(mPeer.GetNodeId()); + + auto strongDelegate = mDelegate; + auto delegateQueue = mDelegateNotificationQueue; + if (strongDelegate == nil || delegateQueue == nil) { + LogErrorOnFailure(CHIP_ERROR_INCORRECT_STATE); + return; + } + + auto nsError = [MTRError errorForCHIPErrorCode:error]; + if ([strongDelegate respondsToSelector:@selector(handleBDXTransferSessionEndForNodeID:controller:error:)]) { + dispatch_async(delegateQueue, ^{ + [strongDelegate handleBDXTransferSessionEndForNodeID:nodeId + controller:controller + error:nsError]; + }); + } +} + +CHIP_ERROR MTROTAImageTransferHandler::OnTransferSessionEnd(const TransferSession::OutputEventType eventType) +{ + assertChipStackLockedByCurrentThread(); + + CHIP_ERROR error = CHIP_NO_ERROR; + if (eventType == TransferSession::OutputEventType::kTransferTimeout) { + error = CHIP_ERROR_TIMEOUT; + } else if (eventType != TransferSession::OutputEventType::kAckEOFReceived) { + error = CHIP_ERROR_INTERNAL; + } + + InvokeTransferSessionEndCallback(error); + + if (error == CHIP_NO_ERROR) { + NotifyEventHandled(eventType, error); + } + return error; +} + +CHIP_ERROR MTROTAImageTransferHandler::OnBlockQuery(const TransferSession::OutputEventType eventType, uint64_t bytesToSkip) +{ + assertChipStackLockedByCurrentThread(); + + auto blockSize = @(mTransfer.GetTransferBlockSize()); + auto blockIndex = @(mTransfer.GetNextBlockNum()); + + auto * controller = [[MTRDeviceControllerFactory sharedInstance] runningControllerForFabricIndex:mPeer.GetFabricIndex()]; + VerifyOrReturnError(controller != nil, CHIP_ERROR_INCORRECT_STATE); + + MTROTAImageTransferHandlerWrapper * __weak weakWrapper = mOTAImageTransferHandlerWrapper; + + auto completionHandler = ^(NSData * _Nullable data, BOOL isEOF) { + [controller + asyncDispatchToMatterQueue:^() { + assertChipStackLockedByCurrentThread(); + + // Check if the OTA image transfer handler is still valid. If not, return from the completion handler. + MTROTAImageTransferHandlerWrapper * strongWrapper = weakWrapper; + if (!strongWrapper || !strongWrapper.otaImageTransferHandler) { + return; + } + + if (data == nil) { + NotifyEventHandled(eventType, CHIP_ERROR_INCORRECT_STATE); + return; + } + + TransferSession::BlockData blockData; + blockData.Data = static_cast([data bytes]); + blockData.Length = static_cast([data length]); + blockData.IsEof = isEOF; + + CHIP_ERROR err = mTransfer.PrepareBlock(blockData); + LogErrorOnFailure(err); + NotifyEventHandled(eventType, err); + } + errorHandler:^(NSError *) { + // Not much we can do here, but if the controller is shut down we + // should already have been destroyed anyway. + }]; + }; + + // TODO Handle MaxLength + + auto nodeId = @(mPeer.GetNodeId()); + + auto strongDelegate = mDelegate; + auto delegateQueue = mDelegateNotificationQueue; + if (strongDelegate == nil || delegateQueue == nil) { + LogErrorOnFailure(CHIP_ERROR_INCORRECT_STATE); + return CHIP_ERROR_INCORRECT_STATE; + } + + dispatch_async(delegateQueue, ^{ + if ([strongDelegate respondsToSelector:@selector(handleBDXQueryForNodeID: + controller:blockSize:blockIndex:bytesToSkip:completion:)]) { + [strongDelegate handleBDXQueryForNodeID:nodeId + controller:controller + blockSize:blockSize + blockIndex:blockIndex + bytesToSkip:@(bytesToSkip) + completion:completionHandler]; + } else { + [strongDelegate handleBDXQueryForNodeID:nodeId + controller:controller + blockSize:blockSize + blockIndex:blockIndex + bytesToSkip:@(bytesToSkip) + completionHandler:completionHandler]; + } + }); + return CHIP_NO_ERROR; +} + +void MTROTAImageTransferHandler::HandleTransferSessionOutput(TransferSession::OutputEvent & event) +{ + VerifyOrReturn(mDelegate != nil); + + TransferSession::OutputEventType eventType = event.EventType; + + ChipLogError(BDX, "OutputEvent type: %s", event.ToString(eventType)); + + CHIP_ERROR err = CHIP_NO_ERROR; + switch (event.EventType) { + case TransferSession::OutputEventType::kInitReceived: + err = OnTransferSessionBegin(eventType); + if (err != CHIP_NO_ERROR) { + LogErrorOnFailure(err); + NotifyEventHandled(eventType, err); + } + break; + case TransferSession::OutputEventType::kStatusReceived: + ChipLogError(BDX, "Got StatusReport %x", static_cast(event.statusData.statusCode)); + [[fallthrough]]; + case TransferSession::OutputEventType::kAckEOFReceived: + case TransferSession::OutputEventType::kInternalError: + case TransferSession::OutputEventType::kTransferTimeout: + err = OnTransferSessionEnd(eventType); + if (err != CHIP_NO_ERROR) { + LogErrorOnFailure(err); + NotifyEventHandled(eventType, err); + } + break; + case TransferSession::OutputEventType::kQueryWithSkipReceived: + case TransferSession::OutputEventType::kQueryReceived: { + uint64_t bytesToSkip = (eventType == TransferSession::OutputEventType::kQueryWithSkipReceived ? event.bytesToSkip.BytesToSkip : 0); + err = OnBlockQuery(eventType, bytesToSkip); + if (err != CHIP_NO_ERROR) { + LogErrorOnFailure(err); + NotifyEventHandled(eventType, err); + } + break; + } + case TransferSession::OutputEventType::kNone: + case TransferSession::OutputEventType::kAckReceived: + case TransferSession::OutputEventType::kAcceptReceived: + case TransferSession::OutputEventType::kBlockReceived: + default: + // Should never happen since this implements an OTA provider in BDX Receiver role. + chipDie(); + break; + } +} + +void MTROTAImageTransferHandler::DestroySelf() +{ + assertChipStackLockedByCurrentThread(); + + delete this; +} + +ScopedNodeId MTROTAImageTransferHandler::GetPeerScopedNodeId(Messaging::ExchangeContext * ec) +{ + auto sessionHandle = ec->GetSessionHandle(); + + if (sessionHandle->IsSecureSession()) { + return sessionHandle->AsSecureSession()->GetPeer(); + } else if (sessionHandle->IsGroupSession()) { + return sessionHandle->AsIncomingGroupSession()->GetPeer(); + } + return ScopedNodeId(); +} + +CHIP_ERROR MTROTAImageTransferHandler::OnMessageReceived( + Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader, System::PacketBufferHandle && payload) +{ + assertChipStackLockedByCurrentThread(); + + ChipLogProgress(BDX, "MTROTAImageTransferHandler: OnMessageReceived: message " ChipLogFormatMessageType " protocol " ChipLogFormatProtocolId, + payloadHeader.GetMessageType(), ChipLogValueProtocolId(payloadHeader.GetProtocolID())); + + VerifyOrReturnError(ec != nullptr, CHIP_ERROR_INCORRECT_STATE); + CHIP_ERROR err; + + // If we receive a ReceiveInit message, then we prepare for transfer. + // + // If init succeeds, or is not needed, we send the message to the AsyncTransferFacilitator for processing. + if (payloadHeader.HasMessageType(MessageType::ReceiveInit)) { + err = Init(ec); + if (err != CHIP_NO_ERROR) { + ChipLogError(Controller, "OnMessageReceived: Failed to prepare for transfer for BDX: %" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + } + + // Send the message to the AsyncFacilitator to drive the BDX session state machine. + AsyncTransferFacilitator::OnMessageReceived(ec, payloadHeader, std::move(payload)); + return err; +} diff --git a/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.h b/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.h index 3d70954bb97200..1b7a6f1bc78870 100644 --- a/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.h +++ b/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.h @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2022 Project CHIP Authors + * Copyright (c) 2022-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. @@ -18,6 +18,7 @@ #import #import "MTRDeviceController_Concrete.h" +#import "MTROTAUnsolicitedBDXMessageHandler.h" #include @@ -67,6 +68,9 @@ class MTROTAProviderDelegateBridge : public chip::app::Clusters::OTAProviderDele static void ConvertToNotifyUpdateAppliedParams( const chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::NotifyUpdateApplied::DecodableType & commandData, MTROTASoftwareUpdateProviderClusterNotifyUpdateAppliedParams * commandParams); + +protected: + MTROTAUnsolicitedBDXMessageHandler mOtaUnsolicitedBDXMsgHandler; }; NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.mm b/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.mm index 8729ac2a0f0a55..a0f831cc83ab31 100644 --- a/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.mm +++ b/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.mm @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2022 Project CHIP Authors + * Copyright (c) 2022-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. @@ -20,6 +20,7 @@ #import "MTRCommandPayloadsObjC.h" #import "MTRDeviceControllerFactory_Internal.h" #import "MTRDeviceController_Internal.h" +#import "MTRError_Internal.h" #import "NSDataSpanConversion.h" #import "NSStringSpanConversion.h" @@ -30,11 +31,10 @@ #include #include -#include #include #include +#include #include -#include using namespace chip; using namespace chip::app; @@ -42,13 +42,9 @@ using namespace chip::bdx; using Protocols::InteractionModel::Status; -// TODO Expose a method onto the delegate to make that configurable. -constexpr uint32_t kMaxBdxBlockSize = 1024; -constexpr uint32_t kMaxBDXURILen = 256; +namespace { -// Since the BDX timeout is 5 minutes and we are starting this after query image is available and before the BDX init comes, -// we just double the timeout to give enough time for the BDX init to come in a reasonable amount of time. -constexpr System::Clock::Timeout kBdxInitReceivedTimeout = System::Clock::Seconds16(10 * 60); +constexpr uint32_t kMaxBDXURILen = 256; // Time in seconds after which the requestor should retry calling query image if // busy status is receieved. The spec minimum is 2 minutes, but in practice OTA @@ -58,457 +54,44 @@ // OTA. constexpr uint32_t kDelayedActionTimeSeconds = 600; -constexpr System::Clock::Timeout kBdxTimeout = System::Clock::Seconds16(5 * 60); // OTA Spec mandates >= 5 minutes -constexpr System::Clock::Timeout kBdxPollIntervalMs = System::Clock::Milliseconds32(50); -constexpr bdx::TransferRole kBdxRole = bdx::TransferRole::kSender; - -class BdxOTASender : public bdx::Responder { -public: - BdxOTASender() {}; - - CHIP_ERROR PrepareForTransfer(FabricIndex fabricIndex, NodeId nodeId) - { - assertChipStackLockedByCurrentThread(); - - VerifyOrReturnError(mExchangeMgr != nullptr, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mSystemLayer != nullptr, CHIP_ERROR_INCORRECT_STATE); - - ReturnErrorOnFailure(ConfigureState(fabricIndex, nodeId)); - - BitFlags flags(bdx::TransferControlFlags::kReceiverDrive); - return Responder::PrepareForTransfer(mSystemLayer, kBdxRole, flags, kMaxBdxBlockSize, kBdxTimeout, kBdxPollIntervalMs); - } - - CHIP_ERROR Init(System::Layer * systemLayer, Messaging::ExchangeManager * exchangeMgr) - { - assertChipStackLockedByCurrentThread(); - - VerifyOrReturnError(mSystemLayer == nullptr, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mExchangeMgr == nullptr, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(systemLayer != nullptr, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(exchangeMgr != nullptr, CHIP_ERROR_INCORRECT_STATE); - - exchangeMgr->RegisterUnsolicitedMessageHandlerForProtocol(Protocols::BDX::Id, this); - - mSystemLayer = systemLayer; - mExchangeMgr = exchangeMgr; - - return CHIP_NO_ERROR; - } - - CHIP_ERROR Shutdown() - { - assertChipStackLockedByCurrentThread(); - - VerifyOrReturnError(mSystemLayer != nullptr, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mExchangeMgr != nullptr, CHIP_ERROR_INCORRECT_STATE); - - mExchangeMgr->UnregisterUnsolicitedMessageHandlerForProtocol(Protocols::BDX::Id); - ResetState(CHIP_ERROR_CANCELLED); - - mExchangeMgr = nullptr; - mSystemLayer = nullptr; - - return CHIP_NO_ERROR; - } - - void ControllerShuttingDown(MTRDeviceController_Concrete * controller) - { - assertChipStackLockedByCurrentThread(); - - if (mInitialized && mFabricIndex.Value() == controller.fabricIndex) { - ResetState(CHIP_ERROR_CANCELLED); - } - } - - void ResetState(CHIP_ERROR error) - { - assertChipStackLockedByCurrentThread(); - if (mNodeId.HasValue() && mFabricIndex.HasValue()) { - ChipLogProgress(Controller, - "Resetting state for OTA Provider; no longer providing an update for node id 0x" ChipLogFormatX64 - ", fabric index %u", - ChipLogValueX64(mNodeId.Value()), mFabricIndex.Value()); - - if (mTransferStarted) { - auto controller = [MTRDeviceControllerFactory.sharedInstance runningControllerForFabricIndex:mFabricIndex.Value()]; - if (controller) { - auto nodeId = @(mNodeId.Value()); - auto strongDelegate = mDelegate; - if ([strongDelegate respondsToSelector:@selector(handleBDXTransferSessionEndForNodeID:controller:error:)]) { - dispatch_async(mDelegateNotificationQueue, ^{ - [strongDelegate handleBDXTransferSessionEndForNodeID:nodeId - controller:controller - error:[MTRError errorForCHIPErrorCode:error]]; - }); - } - } else { - ChipLogError(Controller, "Not notifying delegate of BDX Transfer Session End, controller is not running"); - } - } - } else { - ChipLogProgress(Controller, "Resetting state for OTA Provider"); - } - if (mSystemLayer) { - mSystemLayer->CancelTimer(HandleBdxInitReceivedTimeoutExpired, this); - } - // TODO: Check if this can be removed. It seems like we can close the exchange context and reset transfer regardless. - if (!mInitialized) { - return; - } - Responder::ResetTransfer(); - ++mTransferGeneration; - mFabricIndex.ClearValue(); - mNodeId.ClearValue(); - - if (mExchangeCtx != nullptr) { - mExchangeCtx->Close(); - mExchangeCtx = nullptr; - } - - mDelegate = nil; - mDelegateNotificationQueue = nil; - - mInitialized = false; - mTransferStarted = false; - } - -private: - /** - * Timer callback called when we don't receive a BDX init within a reasonable time after a successful QueryImage response. - */ - static void HandleBdxInitReceivedTimeoutExpired(chip::System::Layer * systemLayer, void * state) - { - VerifyOrReturn(state != nullptr); - static_cast(state)->ResetState(CHIP_ERROR_TIMEOUT); - } - - CHIP_ERROR OnMessageToSend(TransferSession::OutputEvent & event) - { - assertChipStackLockedByCurrentThread(); - - VerifyOrReturnError(mExchangeCtx != nullptr, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mDelegate != nil, CHIP_ERROR_INCORRECT_STATE); - - Messaging::SendFlags sendFlags; - - // All messages sent from the Sender expect a response, except for a StatusReport which would indicate an error and - // the end of the transfer. - if (!event.msgTypeData.HasMessageType(Protocols::SecureChannel::MsgType::StatusReport)) { - sendFlags.Set(Messaging::SendMessageFlags::kExpectResponse); - } - - auto & msgTypeData = event.msgTypeData; - // If there's an error sending the message, close the exchange and call ResetState. - // TODO: If we can remove the !mInitialized check in ResetState(), just calling ResetState() will suffice here. - CHIP_ERROR err - = mExchangeCtx->SendMessage(msgTypeData.ProtocolId, msgTypeData.MessageType, std::move(event.MsgData), sendFlags); - if (err != CHIP_NO_ERROR) { - mExchangeCtx->Close(); - mExchangeCtx = nullptr; - ResetState(err); - } else if (msgTypeData.HasMessageType(Protocols::SecureChannel::MsgType::StatusReport)) { - // If the send was successful for a status report, since we are not expecting a response the exchange context is - // already closed. We need to null out the reference to avoid having a dangling pointer. - mExchangeCtx = nullptr; - ResetState(CHIP_ERROR_INTERNAL); - } - return err; - } - - CHIP_ERROR OnTransferSessionBegin(TransferSession::OutputEvent & event) - { - assertChipStackLockedByCurrentThread(); - // Once we receive the BDX init, cancel the BDX Init timeout and start the BDX session - if (mSystemLayer) { - mSystemLayer->CancelTimer(HandleBdxInitReceivedTimeoutExpired, this); - } - - VerifyOrReturnError(mFabricIndex.HasValue(), CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mNodeId.HasValue(), CHIP_ERROR_INCORRECT_STATE); - uint16_t fdl = 0; - auto fd = mTransfer.GetFileDesignator(fdl); - VerifyOrReturnError(fdl <= bdx::kMaxFileDesignatorLen, CHIP_ERROR_INVALID_ARGUMENT); - CharSpan fileDesignatorSpan(Uint8::to_const_char(fd), fdl); - - auto fileDesignator = AsString(fileDesignatorSpan); - if (fileDesignator == nil) { - return CHIP_ERROR_INCORRECT_STATE; - } - - auto offset = @(mTransfer.GetStartOffset()); - - auto * controller = [[MTRDeviceControllerFactory sharedInstance] runningControllerForFabricIndex:mFabricIndex.Value()]; - VerifyOrReturnError(controller != nil, CHIP_ERROR_INCORRECT_STATE); - - auto transferGeneration = mTransferGeneration; - - auto completionHandler = ^(NSError * _Nullable error) { - [controller - asyncDispatchToMatterQueue:^() { - assertChipStackLockedByCurrentThread(); - - if (!mInitialized || mTransferGeneration != transferGeneration) { - // Callback for a stale transfer. - return; - } - - if (error != nil) { - CHIP_ERROR err = [MTRError errorToCHIPErrorCode:error]; - LogErrorOnFailure(err); - LogErrorOnFailure(mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(err))); - return; - } - - // bdx::TransferSession will automatically reject a transfer if there are no - // common supported control modes. It will also default to the smaller - // block size. - TransferSession::TransferAcceptData acceptData; - acceptData.ControlMode = bdx::TransferControlFlags::kReceiverDrive; - acceptData.MaxBlockSize = mTransfer.GetTransferBlockSize(); - acceptData.StartOffset = mTransfer.GetStartOffset(); - acceptData.Length = mTransfer.GetTransferLength(); - - LogErrorOnFailure(mTransfer.AcceptTransfer(acceptData)); - } - errorHandler:^(NSError *) { - // Not much we can do here - }]; - }; - - mTransferStarted = true; - auto nodeId = @(mNodeId.Value()); - auto strongDelegate = mDelegate; - dispatch_async(mDelegateNotificationQueue, ^{ - if ([strongDelegate respondsToSelector:@selector(handleBDXTransferSessionBeginForNodeID:controller:fileDesignator:offset:completion:)]) { - [strongDelegate handleBDXTransferSessionBeginForNodeID:nodeId - controller:controller - fileDesignator:fileDesignator - offset:offset - completion:completionHandler]; - } else { - [strongDelegate handleBDXTransferSessionBeginForNodeID:nodeId - controller:controller - fileDesignator:fileDesignator - offset:offset - completionHandler:completionHandler]; - } - }); - - return CHIP_NO_ERROR; - } - - CHIP_ERROR OnTransferSessionEnd(TransferSession::OutputEvent & event) - { - assertChipStackLockedByCurrentThread(); - - VerifyOrReturnError(mFabricIndex.HasValue(), CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mNodeId.HasValue(), CHIP_ERROR_INCORRECT_STATE); - - CHIP_ERROR error = CHIP_NO_ERROR; - if (event.EventType == TransferSession::OutputEventType::kTransferTimeout) { - error = CHIP_ERROR_TIMEOUT; - } else if (event.EventType != TransferSession::OutputEventType::kAckEOFReceived) { - error = CHIP_ERROR_INTERNAL; - } - - ResetState(error); // will notify the delegate - return CHIP_NO_ERROR; - } - - CHIP_ERROR OnBlockQuery(TransferSession::OutputEvent & event) - { - assertChipStackLockedByCurrentThread(); - - VerifyOrReturnError(mFabricIndex.HasValue(), CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mNodeId.HasValue(), CHIP_ERROR_INCORRECT_STATE); - - auto blockSize = @(mTransfer.GetTransferBlockSize()); - auto blockIndex = @(mTransfer.GetNextBlockNum()); - - auto bytesToSkip = @(0); - if (event.EventType == TransferSession::OutputEventType::kQueryWithSkipReceived) { - bytesToSkip = @(event.bytesToSkip.BytesToSkip); - } - - auto * controller = [[MTRDeviceControllerFactory sharedInstance] runningControllerForFabricIndex:mFabricIndex.Value()]; - VerifyOrReturnError(controller != nil, CHIP_ERROR_INCORRECT_STATE); - - auto transferGeneration = mTransferGeneration; - - auto completionHandler = ^(NSData * _Nullable data, BOOL isEOF) { - [controller - asyncDispatchToMatterQueue:^() { - assertChipStackLockedByCurrentThread(); - - if (!mInitialized || mTransferGeneration != transferGeneration) { - // Callback for a stale transfer. - return; - } - - if (data == nil) { - LogErrorOnFailure(mTransfer.AbortTransfer(bdx::StatusCode::kUnknown)); - return; - } - - TransferSession::BlockData blockData; - blockData.Data = static_cast([data bytes]); - blockData.Length = static_cast([data length]); - blockData.IsEof = isEOF; - - CHIP_ERROR err = mTransfer.PrepareBlock(blockData); - if (CHIP_NO_ERROR != err) { - LogErrorOnFailure(err); - LogErrorOnFailure(mTransfer.AbortTransfer(bdx::StatusCode::kUnknown)); - } - } - errorHandler:^(NSError *) { - // Not much we can do here - }]; - }; - - // TODO Handle MaxLength - - auto nodeId = @(mNodeId.Value()); - - auto strongDelegate = mDelegate; - dispatch_async(mDelegateNotificationQueue, ^{ - if ([strongDelegate respondsToSelector:@selector(handleBDXQueryForNodeID:controller:blockSize:blockIndex:bytesToSkip:completion:)]) { - [strongDelegate handleBDXQueryForNodeID:nodeId - controller:controller - blockSize:blockSize - blockIndex:blockIndex - bytesToSkip:bytesToSkip - completion:completionHandler]; - } else { - [strongDelegate handleBDXQueryForNodeID:nodeId - controller:controller - blockSize:blockSize - blockIndex:blockIndex - bytesToSkip:bytesToSkip - completionHandler:completionHandler]; - } - }); - - return CHIP_NO_ERROR; - } - - void HandleTransferSessionOutput(TransferSession::OutputEvent & event) override - { - VerifyOrReturn(mDelegate != nil); - - CHIP_ERROR err = CHIP_NO_ERROR; - switch (event.EventType) { - case TransferSession::OutputEventType::kInitReceived: - err = OnTransferSessionBegin(event); - if (err != CHIP_NO_ERROR) { - LogErrorOnFailure(mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(err))); - } - break; - case TransferSession::OutputEventType::kStatusReceived: - ChipLogError(BDX, "Got StatusReport %x", static_cast(event.statusData.statusCode)); - [[fallthrough]]; - case TransferSession::OutputEventType::kAckEOFReceived: - case TransferSession::OutputEventType::kInternalError: - case TransferSession::OutputEventType::kTransferTimeout: - err = OnTransferSessionEnd(event); - break; - case TransferSession::OutputEventType::kQueryWithSkipReceived: - case TransferSession::OutputEventType::kQueryReceived: - err = OnBlockQuery(event); - break; - case TransferSession::OutputEventType::kMsgToSend: - err = OnMessageToSend(event); - break; - case TransferSession::OutputEventType::kNone: - case TransferSession::OutputEventType::kAckReceived: - // Nothing to do. - break; - case TransferSession::OutputEventType::kAcceptReceived: - case TransferSession::OutputEventType::kBlockReceived: - default: - // Should never happens. - chipDie(); - break; - } - LogErrorOnFailure(err); - } - - CHIP_ERROR ConfigureState(chip::FabricIndex fabricIndex, chip::NodeId nodeId) - { - assertChipStackLockedByCurrentThread(); - - if (mInitialized) { - // Prevent a new node connection since another is active. - VerifyOrReturnError(mFabricIndex.Value() == fabricIndex && mNodeId.Value() == nodeId, CHIP_ERROR_BUSY); - - // Reset stale connection from the same Node if exists. - ResetState(CHIP_ERROR_CANCELLED); - } - - auto * controller = [[MTRDeviceControllerFactory sharedInstance] runningControllerForFabricIndex:fabricIndex]; - VerifyOrReturnError(controller != nil, CHIP_ERROR_INCORRECT_STATE); - - mDelegate = controller.otaProviderDelegate; - mDelegateNotificationQueue = controller.otaProviderDelegateQueue; - - // We should have already checked that this controller supports OTA. - VerifyOrReturnError(mDelegate != nil, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mDelegateNotificationQueue != nil, CHIP_ERROR_INCORRECT_STATE); - - // Start a timer to track whether we receive a BDX init after a successful query image in a reasonable amount of time - CHIP_ERROR err = mSystemLayer->StartTimer(kBdxInitReceivedTimeout, HandleBdxInitReceivedTimeoutExpired, this); - LogErrorOnFailure(err); - - ReturnErrorOnFailure(err); - - mFabricIndex.SetValue(fabricIndex); - mNodeId.SetValue(nodeId); - - mInitialized = true; - - return CHIP_NO_ERROR; - } - - bool mInitialized = false; - bool mTransferStarted = false; - Optional mFabricIndex; - Optional mNodeId; - id mDelegate = nil; - dispatch_queue_t mDelegateNotificationQueue = nil; - Messaging::ExchangeManager * mExchangeMgr = nullptr; - - // Since we are a singleton, we get reused across transfers, but also have - // async calls that can happen. The transfer generation keeps track of - // which transfer we are currently doing, so we can ignore async calls - // attached to no-longer-running transfers. - uint64_t mTransferGeneration = 0; -}; - -namespace { -Global gOtaSender; - -NSInteger constexpr kOtaProviderEndpoint = 0; +NSInteger const kOtaProviderEndpoint = 0; } // anonymous namespace -MTROTAProviderDelegateBridge::MTROTAProviderDelegateBridge() { Clusters::OTAProvider::SetDelegate(kOtaProviderEndpoint, this); } +MTROTAProviderDelegateBridge::MTROTAProviderDelegateBridge() +{ + Clusters::OTAProvider::SetDelegate(kOtaProviderEndpoint, this); +} MTROTAProviderDelegateBridge::~MTROTAProviderDelegateBridge() { - gOtaSender->ResetState(CHIP_ERROR_CANCELLED); Clusters::OTAProvider::SetDelegate(kOtaProviderEndpoint, nullptr); } CHIP_ERROR MTROTAProviderDelegateBridge::Init(System::Layer * systemLayer, Messaging::ExchangeManager * exchangeManager) { - return gOtaSender->Init(systemLayer, exchangeManager); + assertChipStackLockedByCurrentThread(); + + VerifyOrReturnError(exchangeManager != nullptr, CHIP_ERROR_INCORRECT_STATE); + + CHIP_ERROR err = mOtaUnsolicitedBDXMsgHandler.Init(systemLayer, exchangeManager); + if (err != CHIP_NO_ERROR) { + ChipLogError(Controller, "Failed to initialize the unsolicited BDX Message handler with err %s", err.AsString()); + } + return err; } -void MTROTAProviderDelegateBridge::Shutdown() { gOtaSender->Shutdown(); } +void MTROTAProviderDelegateBridge::Shutdown() +{ + assertChipStackLockedByCurrentThread(); + + mOtaUnsolicitedBDXMsgHandler.Shutdown(); +} void MTROTAProviderDelegateBridge::ControllerShuttingDown(MTRDeviceController_Concrete * controller) { - gOtaSender->ControllerShuttingDown(controller); + assertChipStackLockedByCurrentThread(); + + mOtaUnsolicitedBDXMsgHandler.ControllerShuttingDown(controller); } namespace { @@ -611,7 +194,6 @@ bool GetPeerNodeInfo(CommandHandler * commandHandler, const ConcreteCommandPath return; } - auto fabricIndex = commandObj->GetAccessingFabricIndex(); auto ourNodeId = commandObj->GetExchangeContext()->GetSessionHandle()->AsSecureSession()->GetLocalScopedNodeId(); auto * commandParams = [[MTROTASoftwareUpdateProviderClusterQueryImageParams alloc] init]; @@ -667,42 +249,25 @@ bool GetPeerNodeInfo(CommandHandler * commandHandler, const ConcreteCommandPath return; } - // If there is an update available, try to prepare for a transfer. - CHIP_ERROR err = gOtaSender->PrepareForTransfer(fabricIndex, nodeId); - if (CHIP_NO_ERROR != err) { - - // Handle busy error separately as we have a query image response status that maps to busy - if (err == CHIP_ERROR_BUSY) { - ChipLogError( - Controller, "Responding with Busy due to being in the middle of handling another BDX transfer"); - Commands::QueryImageResponse::Type response; - response.status = static_cast(MTROTASoftwareUpdateProviderStatusBusy); - response.delayedActionTime.SetValue(delegateResponse.delayedActionTime.ValueOr(kDelayedActionTimeSeconds)); - handler->AddResponse(cachedCommandPath, response); - handle.Release(); - // We do not reset state when we get the busy error because that means we are locked in a BDX transfer - // session with another requestor when we get this query image request. We do not want to interrupt the - // ongoing transfer instead just respond to the second requestor with a busy status and a delayedActionTime - // in which the requestor can retry. - return; - } - LogErrorOnFailure(err); - handler->AddStatus(cachedCommandPath, StatusIB(err).mStatus); + // If the MTROTAUnsolicitedBDXMessageHandler already has an ongoing transfer, send busy error. + if (MTROTAUnsolicitedBDXMessageHandler::GetInstance()->IsInAnOngoingTransfer()) { + ChipLogError( + Controller, "Responding with Busy due to being in the middle of handling another BDX transfer"); + Commands::QueryImageResponse::Type response; + response.status = static_cast(MTROTASoftwareUpdateProviderStatusBusy); + response.delayedActionTime.SetValue(delegateResponse.delayedActionTime.ValueOr(kDelayedActionTimeSeconds)); + handler->AddResponse(cachedCommandPath, response); handle.Release(); - // We need to reset state here to clean up any initialization we might have done including starting the BDX - // timeout timer while preparing for transfer if any failure occurs afterwards. - gOtaSender->ResetState(err); return; } char uriBuffer[kMaxBDXURILen]; MutableCharSpan uri(uriBuffer); - err = bdx::MakeURI(ourNodeId.GetNodeId(), AsCharSpan(data.imageURI), uri); + CHIP_ERROR err = bdx::MakeURI(ourNodeId.GetNodeId(), AsCharSpan(data.imageURI), uri); if (CHIP_NO_ERROR != err) { LogErrorOnFailure(err); handler->AddStatus(cachedCommandPath, StatusIB(err).mStatus); handle.Release(); - gOtaSender->ResetState(err); return; } delegateResponse.imageURI.SetValue(uri); diff --git a/src/darwin/Framework/CHIP/MTROTAUnsolicitedBDXMessageHandler.h b/src/darwin/Framework/CHIP/MTROTAUnsolicitedBDXMessageHandler.h new file mode 100644 index 00000000000000..83a5f4443ca98b --- /dev/null +++ b/src/darwin/Framework/CHIP/MTROTAUnsolicitedBDXMessageHandler.h @@ -0,0 +1,74 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "MTRDeviceController_Concrete.h" +#import "MTROTAImageTransferHandler.h" +#import + +#include +#include + +NS_ASSUME_NONNULL_BEGIN + +/** + * This class defines a handler that can listen for all unsolicited BDX messages. + * + * When it receives a BDX ReceiveInit message from a node, it creates a new + * MTROTAImageTransferHandler object as the exchange delegate that will + * handle the transfer. + * + * In all other cases, it fails out so that there is no exchange delegate created, + * which means the message is potentially acked, but does not get a response. + */ +class MTROTAUnsolicitedBDXMessageHandler : public chip::Messaging::UnsolicitedMessageHandler +{ +public: + MTROTAUnsolicitedBDXMessageHandler() : mExchangeMgr(nullptr) { sInstance = this; } + + ~MTROTAUnsolicitedBDXMessageHandler() {} + + static MTROTAUnsolicitedBDXMessageHandler * GetInstance(); + + CHIP_ERROR Init(chip::System::Layer * systemLayer, chip::Messaging::ExchangeManager * exchangeManager); + + bool IsInAnOngoingTransfer(); + + void OnTransferHandlerCreated(MTROTAImageTransferHandler * imageTransferHandler); + + void OnTransferHandlerDestroyed(MTROTAImageTransferHandler * imageTransferHandler); + + void Shutdown(); + + void ControllerShuttingDown(MTRDeviceController_Concrete * controller); + +private: + CHIP_ERROR OnUnsolicitedMessageReceived(const chip::PayloadHeader & payloadHeader, const chip::SessionHandle & session, + chip::Messaging::ExchangeDelegate * _Nonnull & newDelegate) override; + + void OnExchangeCreationFailed(chip::Messaging::ExchangeDelegate * _Nonnull delegate) override; + + // TODO: #36181 - Have a set of MTROTAImageTransferHandler objects. + MTROTAImageTransferHandler * _Nullable mOTAImageTransferHandler = nullptr; + + chip::System::Layer * mSystemLayer; + + chip::Messaging::ExchangeManager * mExchangeMgr; + + static MTROTAUnsolicitedBDXMessageHandler * sInstance; +}; + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTROTAUnsolicitedBDXMessageHandler.mm b/src/darwin/Framework/CHIP/MTROTAUnsolicitedBDXMessageHandler.mm new file mode 100644 index 00000000000000..2e3e5c22936726 --- /dev/null +++ b/src/darwin/Framework/CHIP/MTROTAUnsolicitedBDXMessageHandler.mm @@ -0,0 +1,132 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "MTROTAUnsolicitedBDXMessageHandler.h" +#import "MTRDeviceController_Internal.h" + +#include + +using namespace chip; +using namespace chip::Messaging; +using namespace chip::bdx; + +MTROTAUnsolicitedBDXMessageHandler * MTROTAUnsolicitedBDXMessageHandler::sInstance = nullptr; + +CHIP_ERROR MTROTAUnsolicitedBDXMessageHandler::Init(System::Layer * systemLayer, ExchangeManager * exchangeManager) +{ + assertChipStackLockedByCurrentThread(); + + VerifyOrReturnError(systemLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(exchangeManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + mSystemLayer = systemLayer; + mExchangeMgr = exchangeManager; + return mExchangeMgr->RegisterUnsolicitedMessageHandlerForProtocol(Protocols::BDX::Id, this); +} + +MTROTAUnsolicitedBDXMessageHandler * MTROTAUnsolicitedBDXMessageHandler::GetInstance() +{ + return sInstance; +} + +void MTROTAUnsolicitedBDXMessageHandler::Shutdown() +{ + assertChipStackLockedByCurrentThread(); + + VerifyOrReturn(mExchangeMgr != nullptr); + mExchangeMgr->UnregisterUnsolicitedMessageHandlerForProtocol(Protocols::BDX::Id); + + VerifyOrReturn(mOTAImageTransferHandler != nullptr); + + delete mOTAImageTransferHandler; + mOTAImageTransferHandler = nullptr; +} + +void MTROTAUnsolicitedBDXMessageHandler::ControllerShuttingDown(MTRDeviceController_Concrete * controller) +{ + assertChipStackLockedByCurrentThread(); + + VerifyOrReturn(mOTAImageTransferHandler != nullptr); + + FabricIndex peerFabricIndex = mOTAImageTransferHandler->GetPeerFabricIndex(); + VerifyOrReturn(peerFabricIndex != kUndefinedFabricIndex); + + if (controller.fabricIndex == peerFabricIndex) { + delete mOTAImageTransferHandler; + mOTAImageTransferHandler = nullptr; + } +} + +bool MTROTAUnsolicitedBDXMessageHandler::IsInAnOngoingTransfer() +{ + return (mOTAImageTransferHandler != nullptr); +} + +CHIP_ERROR MTROTAUnsolicitedBDXMessageHandler::OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, const SessionHandle & session, + ExchangeDelegate * _Nonnull & newDelegate) +{ + assertChipStackLockedByCurrentThread(); + + ChipLogDetail(BDX, "MTROTAUnsolicitedBDXMessageHandler: OnUnsolicitedMessageReceived: message " ChipLogFormatMessageType " protocol " ChipLogFormatProtocolId, + payloadHeader.GetMessageType(), ChipLogValueProtocolId(payloadHeader.GetProtocolID())); + + if (IsInAnOngoingTransfer()) { + ChipLogDetail(BDX, "Already in an ongoing transfer. Return"); + return CHIP_ERROR_BUSY; + } + + VerifyOrReturnError(mExchangeMgr != nullptr, CHIP_ERROR_INCORRECT_STATE); + + // Only proceed if there is a valid fabric index for the SessionHandle. + if (session->IsSecureSession() && session->AsSecureSession() != nullptr && session->AsSecureSession()->GetFabricIndex() != kUndefinedFabricIndex) { + + // If we receive a ReceiveInit BDX message, create a new MTROTAImageTransferHandler and register it + // as the handler for all BDX messages that will come over this exchange. + if (payloadHeader.HasMessageType(MessageType::ReceiveInit)) { + newDelegate = new MTROTAImageTransferHandler(mSystemLayer); + return CHIP_NO_ERROR; + } + } + return CHIP_ERROR_INCORRECT_STATE; +} + +void MTROTAUnsolicitedBDXMessageHandler::OnExchangeCreationFailed(ExchangeDelegate * delegate) +{ + assertChipStackLockedByCurrentThread(); + auto * otaTransferHandler = static_cast(delegate); + VerifyOrReturn(otaTransferHandler != nullptr); + + delete otaTransferHandler; +} + +void MTROTAUnsolicitedBDXMessageHandler::OnTransferHandlerCreated(MTROTAImageTransferHandler * imageTransferHandler) +{ + assertChipStackLockedByCurrentThread(); + + // TODO: #36181 - Store the imageTransferHandler in a set of MTROTAImageTransferHandler objects. + mOTAImageTransferHandler = imageTransferHandler; +} + +void MTROTAUnsolicitedBDXMessageHandler::OnTransferHandlerDestroyed(MTROTAImageTransferHandler * imageTransferHandler) +{ + assertChipStackLockedByCurrentThread(); + + // TODO: #36181 - Remove the object matching imageTransferHandler in the set of MTROTAImageTransferHandler objects. + if (mOTAImageTransferHandler == imageTransferHandler) { + mOTAImageTransferHandler = nullptr; + } +} diff --git a/src/darwin/Framework/CHIP/MTRP256KeypairBridge.h b/src/darwin/Framework/CHIP/MTRP256KeypairBridge.h index 4683326926ae0f..4f4e58e41a46dc 100644 --- a/src/darwin/Framework/CHIP/MTRP256KeypairBridge.h +++ b/src/darwin/Framework/CHIP/MTRP256KeypairBridge.h @@ -47,14 +47,15 @@ class MTRP256KeypairBridge : public chip::Crypto::P256Keypair const chip::Crypto::P256PublicKey & Pubkey() const override { return mPubkey; }; - // On success, writes to *pubKey. + // On success, writes to *matterPubKey. static CHIP_ERROR MatterPubKeyFromSecKeyRef(SecKeyRef pubkeyRef, chip::Crypto::P256PublicKey * matterPubKey); + // On success, writes to *matterPubKey. + static CHIP_ERROR MatterPubKeyFromMTRKeypair(id keyPair, chip::Crypto::P256PublicKey * matterPubKey); + private: id _Nullable mKeypair; chip::Crypto::P256PublicKey mPubkey; - - CHIP_ERROR setPubkey(); }; NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRP256KeypairBridge.mm b/src/darwin/Framework/CHIP/MTRP256KeypairBridge.mm index 03a396e27dffe5..f124622591ab30 100644 --- a/src/darwin/Framework/CHIP/MTRP256KeypairBridge.mm +++ b/src/darwin/Framework/CHIP/MTRP256KeypairBridge.mm @@ -36,7 +36,7 @@ } mKeypair = keypair; - return setPubkey(); + return MatterPubKeyFromMTRKeypair(mKeypair, &mPubkey); } CHIP_ERROR MTRP256KeypairBridge::Initialize(ECPKeyTarget key_target) @@ -132,18 +132,6 @@ return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; } -CHIP_ERROR MTRP256KeypairBridge::setPubkey() -{ - if ([mKeypair respondsToSelector:@selector(copyPublicKey)]) { - SecKeyRef publicKey = [mKeypair copyPublicKey]; - auto copyResult = MatterPubKeyFromSecKeyRef(publicKey, &mPubkey); - CFRelease(publicKey); - return copyResult; - } else { - return MatterPubKeyFromSecKeyRef([mKeypair publicKey], &mPubkey); - } -} - CHIP_ERROR MTRP256KeypairBridge::MatterPubKeyFromSecKeyRef(SecKeyRef pubkeyRef, P256PublicKey * matterPubKey) { if (!pubkeyRef) { @@ -165,3 +153,24 @@ return CHIP_NO_ERROR; } + +CHIP_ERROR MTRP256KeypairBridge::MatterPubKeyFromMTRKeypair(id keyPair, chip::Crypto::P256PublicKey * matterPubKey) +{ + SecKeyRef publicKey; + if ([keyPair respondsToSelector:@selector(copyPublicKey)]) { + publicKey = [keyPair copyPublicKey]; + } else { + publicKey = [keyPair publicKey]; + if (publicKey) { + CFRetain(publicKey); + } + } + + CHIP_ERROR err = MatterPubKeyFromSecKeyRef(publicKey, matterPubKey); + + if (publicKey) { + CFRelease(publicKey); + } + + return err; +} diff --git a/src/darwin/Framework/CHIP/templates/MTRBaseClusters-src.zapt b/src/darwin/Framework/CHIP/templates/MTRBaseClusters-src.zapt index 0b8529b9c566c5..f90acdd4fd17e8 100644 --- a/src/darwin/Framework/CHIP/templates/MTRBaseClusters-src.zapt +++ b/src/darwin/Framework/CHIP/templates/MTRBaseClusters-src.zapt @@ -9,6 +9,7 @@ #import "MTRClusterStateCacheContainer_Internal.h" #import "MTRCommandPayloadsObjc.h" #import "MTRDevice_Internal.h" +#import "MTRLogging_Internal.h" #import "MTRStructsObjc.h" #import "NSStringSpanConversion.h" #import "NSDataSpanConversion.h" diff --git a/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc-src.zapt b/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc-src.zapt index 4179d5a905ce07..41af262e030b59 100644 --- a/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc-src.zapt +++ b/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc-src.zapt @@ -4,6 +4,7 @@ #import "MTRCommandPayloads_Internal.h" #import "MTRCommandPayloadExtensions_Internal.h" #import "MTRBaseDevice_Internal.h" +#import "MTRDefines_Internal.h" #import "MTRError_Internal.h" #import "MTRLogging_Internal.h" #import "NSStringSpanConversion.h" diff --git a/src/darwin/Framework/CHIP/templates/partials/encode_value.zapt b/src/darwin/Framework/CHIP/templates/partials/encode_value.zapt index f2f4d076b72bfc..16e2b3e1234417 100644 --- a/src/darwin/Framework/CHIP/templates/partials/encode_value.zapt +++ b/src/darwin/Framework/CHIP/templates/partials/encode_value.zapt @@ -27,11 +27,12 @@ } listFreer.add(listHolder_{{depth}}); for (size_t i_{{depth}} = 0; i_{{depth}} < {{source}}.count; ++i_{{depth}}) { - if ( ! [{{source}}[i_{{depth}}] isKindOfClass: [{{asObjectiveCClass type cluster forceNotList=true}} class]] ) { + auto element_{{depth}} = MTR_SAFE_CAST({{source}}[i_{{depth}}], {{asObjectiveCClass type cluster forceNotList=true}}); + if (!element_{{depth}}) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", {{source}}[i_{{depth}}], NSStringFromClass({{asObjectiveCClass type cluster forceNotList=true}}.class)); {{errorCode}} } - auto element_{{depth}} = ({{asObjectiveCClass type cluster forceNotList=true}} *){{source}}[i_{{depth}}]; {{>encode_value target=(concat "listHolder_" depth "->mList[i_" depth "]") source=(concat "element_" depth) cluster=cluster errorCode=errorCode depth=(incrementDepth depth) isArray=false}} } {{target}} = ListType_{{depth}}(listHolder_{{depth}}->mList, {{source}}.count); diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm index ea02951aa50907..47d9cb14157fe9 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm @@ -25,6 +25,7 @@ #import "MTRCommandPayloadsObjc.h" #import "MTRDefines_Internal.h" #import "MTRDevice_Internal.h" +#import "MTRLogging_Internal.h" #import "MTRStructsObjc.h" #import "NSDataSpanConversion.h" #import "NSStringSpanConversion.h" @@ -5173,11 +5174,12 @@ - (void)writeAttributeBindingWithValue:(NSArray * _Nonnull)value params:(MTRWrit } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRBindingClusterTargetStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRBindingClusterTargetStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRBindingClusterTargetStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRBindingClusterTargetStruct *)value[i_0]; if (element_0.node != nil) { auto & definedValue_2 = listHolder_0->mList[i_0].node.Emplace(); definedValue_2 = element_0.node.unsignedLongLongValue; @@ -5712,11 +5714,12 @@ - (void)writeAttributeACLWithValue:(NSArray * _Nonnull)value params:(MTRWritePar } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRAccessControlClusterAccessControlEntryStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRAccessControlClusterAccessControlEntryStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRAccessControlClusterAccessControlEntryStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRAccessControlClusterAccessControlEntryStruct *)value[i_0]; listHolder_0->mList[i_0].privilege = static_castmList[i_0].privilege)>>(element_0.privilege.unsignedCharValue); listHolder_0->mList[i_0].authMode = static_castmList[i_0].authMode)>>(element_0.authMode.unsignedCharValue); if (element_0.subjects == nil) { @@ -5733,11 +5736,12 @@ - (void)writeAttributeACLWithValue:(NSArray * _Nonnull)value params:(MTRWritePar } listFreer.add(listHolder_3); for (size_t i_3 = 0; i_3 < element_0.subjects.count; ++i_3) { - if ( ! [element_0.subjects[i_3] isKindOfClass: [NSNumber class]] ) { + auto element_3 = MTR_SAFE_CAST(element_0.subjects[i_3], NSNumber); + if (!element_3) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.subjects[i_3], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_3 = (NSNumber *)element_0.subjects[i_3]; listHolder_3->mList[i_3] = element_3.unsignedLongLongValue; } nonNullValue_2 = ListType_3(listHolder_3->mList, element_0.subjects.count); @@ -5760,11 +5764,12 @@ - (void)writeAttributeACLWithValue:(NSArray * _Nonnull)value params:(MTRWritePar } listFreer.add(listHolder_3); for (size_t i_3 = 0; i_3 < element_0.targets.count; ++i_3) { - if ( ! [element_0.targets[i_3] isKindOfClass: [MTRAccessControlClusterAccessControlTargetStruct class]] ) { + auto element_3 = MTR_SAFE_CAST(element_0.targets[i_3], MTRAccessControlClusterAccessControlTargetStruct); + if (!element_3) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.targets[i_3], NSStringFromClass(MTRAccessControlClusterAccessControlTargetStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_3 = (MTRAccessControlClusterAccessControlTargetStruct *)element_0.targets[i_3]; if (element_3.cluster == nil) { listHolder_3->mList[i_3].cluster.SetNull(); } else { @@ -5870,11 +5875,12 @@ - (void)writeAttributeExtensionWithValue:(NSArray * _Nonnull)value params:(MTRWr } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRAccessControlClusterAccessControlExtensionStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRAccessControlClusterAccessControlExtensionStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRAccessControlClusterAccessControlExtensionStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRAccessControlClusterAccessControlExtensionStruct *)value[i_0]; listHolder_0->mList[i_0].data = AsByteSpan(element_0.data); listHolder_0->mList[i_0].fabricIndex = element_0.fabricIndex.unsignedCharValue; } @@ -10171,11 +10177,12 @@ - (void)writeAttributeDefaultOTAProvidersWithValue:(NSArray * _Nonnull)value par } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTROTASoftwareUpdateRequestorClusterProviderLocation class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTROTASoftwareUpdateRequestorClusterProviderLocation); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTROTASoftwareUpdateRequestorClusterProviderLocation.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTROTASoftwareUpdateRequestorClusterProviderLocation *)value[i_0]; listHolder_0->mList[i_0].providerNodeID = element_0.providerNodeID.unsignedLongLongValue; listHolder_0->mList[i_0].endpoint = element_0.endpoint.unsignedShortValue; listHolder_0->mList[i_0].fabricIndex = element_0.fabricIndex.unsignedCharValue; @@ -32215,11 +32222,12 @@ - (void)writeAttributeGroupKeyMapWithValue:(NSArray * _Nonnull)value params:(MTR } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRGroupKeyManagementClusterGroupKeyMapStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRGroupKeyManagementClusterGroupKeyMapStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRGroupKeyManagementClusterGroupKeyMapStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRGroupKeyManagementClusterGroupKeyMapStruct *)value[i_0]; listHolder_0->mList[i_0].groupId = element_0.groupId.unsignedShortValue; listHolder_0->mList[i_0].groupKeySetID = element_0.groupKeySetID.unsignedShortValue; listHolder_0->mList[i_0].fabricIndex = element_0.fabricIndex.unsignedCharValue; @@ -33396,11 +33404,12 @@ - (void)writeAttributeLabelListWithValue:(NSArray * _Nonnull)value params:(MTRWr } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRUserLabelClusterLabelStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRUserLabelClusterLabelStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRUserLabelClusterLabelStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRUserLabelClusterLabelStruct *)value[i_0]; listHolder_0->mList[i_0].label = AsCharSpan(element_0.label); listHolder_0->mList[i_0].value = AsCharSpan(element_0.value); } @@ -64721,11 +64730,12 @@ - (void)writeAttributePresetsWithValue:(NSArray * _Nonnull)value params:(MTRWrit } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRThermostatClusterPresetStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRThermostatClusterPresetStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRThermostatClusterPresetStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRThermostatClusterPresetStruct *)value[i_0]; if (element_0.presetHandle == nil) { listHolder_0->mList[i_0].presetHandle.SetNull(); } else { @@ -64835,11 +64845,12 @@ - (void)writeAttributeSchedulesWithValue:(NSArray * _Nonnull)value params:(MTRWr } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRThermostatClusterScheduleStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRThermostatClusterScheduleStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRThermostatClusterScheduleStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRThermostatClusterScheduleStruct *)value[i_0]; if (element_0.scheduleHandle == nil) { listHolder_0->mList[i_0].scheduleHandle.SetNull(); } else { @@ -64865,11 +64876,12 @@ - (void)writeAttributeSchedulesWithValue:(NSArray * _Nonnull)value params:(MTRWr } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.transitions.count; ++i_2) { - if ( ! [element_0.transitions[i_2] isKindOfClass: [MTRThermostatClusterScheduleTransitionStruct class]] ) { + auto element_2 = MTR_SAFE_CAST(element_0.transitions[i_2], MTRThermostatClusterScheduleTransitionStruct); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.transitions[i_2], NSStringFromClass(MTRThermostatClusterScheduleTransitionStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (MTRThermostatClusterScheduleTransitionStruct *)element_0.transitions[i_2]; listHolder_2->mList[i_2].dayOfWeek = static_castmList[i_2].dayOfWeek)>>(element_2.dayOfWeek.unsignedCharValue); listHolder_2->mList[i_2].transitionTime = element_2.transitionTime.unsignedShortValue; if (element_2.presetHandle != nil) { @@ -97820,11 +97832,12 @@ - (void)writeAttributeTriggersWithValue:(NSArray * _Nonnull)value params:(MTRWri } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRZoneManagementClusterZoneTriggerControlStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRZoneManagementClusterZoneTriggerControlStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRZoneManagementClusterZoneTriggerControlStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRZoneManagementClusterZoneTriggerControlStruct *)value[i_0]; listHolder_0->mList[i_0].initialDuration = element_0.initialDuration.unsignedShortValue; listHolder_0->mList[i_0].augmentationDuration = element_0.augmentationDuration.unsignedShortValue; listHolder_0->mList[i_0].maxDuration = element_0.maxDuration.unsignedIntValue; @@ -104448,11 +104461,12 @@ - (void)writeAttributeListInt8uWithValue:(NSArray * _Nonnull)value params:(MTRWr } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [NSNumber class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *)value[i_0]; listHolder_0->mList[i_0] = element_0.unsignedCharValue; } cppValue = ListType_0(listHolder_0->mList, value.count); @@ -104533,11 +104547,12 @@ - (void)writeAttributeListOctetStringWithValue:(NSArray * _Nonnull)value params: } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [NSData class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], NSData); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(NSData.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSData *)value[i_0]; listHolder_0->mList[i_0] = AsByteSpan(element_0); } cppValue = ListType_0(listHolder_0->mList, value.count); @@ -104618,11 +104633,12 @@ - (void)writeAttributeListStructOctetStringWithValue:(NSArray * _Nonnull)value p } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRUnitTestingClusterTestListStructOctet class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRUnitTestingClusterTestListStructOctet); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRUnitTestingClusterTestListStructOctet.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRUnitTestingClusterTestListStructOctet *)value[i_0]; listHolder_0->mList[i_0].member1 = element_0.member1.unsignedLongLongValue; listHolder_0->mList[i_0].member2 = AsByteSpan(element_0.member2); } @@ -105088,11 +105104,12 @@ - (void)writeAttributeListNullablesAndOptionalsStructWithValue:(NSArray * _Nonnu } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRUnitTestingClusterNullablesAndOptionalsStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRUnitTestingClusterNullablesAndOptionalsStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRUnitTestingClusterNullablesAndOptionalsStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRUnitTestingClusterNullablesAndOptionalsStruct *)value[i_0]; if (element_0.nullableInt == nil) { listHolder_0->mList[i_0].nullableInt.SetNull(); } else { @@ -105197,11 +105214,12 @@ - (void)writeAttributeListNullablesAndOptionalsStructWithValue:(NSArray * _Nonnu } listFreer.add(listHolder_3); for (size_t i_3 = 0; i_3 < element_0.nullableList.count; ++i_3) { - if ( ! [element_0.nullableList[i_3] isKindOfClass: [NSNumber class]] ) { + auto element_3 = MTR_SAFE_CAST(element_0.nullableList[i_3], NSNumber); + if (!element_3) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.nullableList[i_3], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_3 = (NSNumber *)element_0.nullableList[i_3]; listHolder_3->mList[i_3] = static_castmList[i_3])>>(element_3.unsignedCharValue); } nonNullValue_2 = ListType_3(listHolder_3->mList, element_0.nullableList.count); @@ -105222,11 +105240,12 @@ - (void)writeAttributeListNullablesAndOptionalsStructWithValue:(NSArray * _Nonnu } listFreer.add(listHolder_3); for (size_t i_3 = 0; i_3 < element_0.optionalList.count; ++i_3) { - if ( ! [element_0.optionalList[i_3] isKindOfClass: [NSNumber class]] ) { + auto element_3 = MTR_SAFE_CAST(element_0.optionalList[i_3], NSNumber); + if (!element_3) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.optionalList[i_3], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_3 = (NSNumber *)element_0.optionalList[i_3]; listHolder_3->mList[i_3] = static_castmList[i_3])>>(element_3.unsignedCharValue); } definedValue_2 = ListType_3(listHolder_3->mList, element_0.optionalList.count); @@ -105251,11 +105270,12 @@ - (void)writeAttributeListNullablesAndOptionalsStructWithValue:(NSArray * _Nonnu } listFreer.add(listHolder_4); for (size_t i_4 = 0; i_4 < element_0.nullableOptionalList.count; ++i_4) { - if ( ! [element_0.nullableOptionalList[i_4] isKindOfClass: [NSNumber class]] ) { + auto element_4 = MTR_SAFE_CAST(element_0.nullableOptionalList[i_4], NSNumber); + if (!element_4) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.nullableOptionalList[i_4], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_4 = (NSNumber *)element_0.nullableOptionalList[i_4]; listHolder_4->mList[i_4] = static_castmList[i_4])>>(element_4.unsignedCharValue); } nonNullValue_3 = ListType_4(listHolder_4->mList, element_0.nullableOptionalList.count); @@ -105739,11 +105759,12 @@ - (void)writeAttributeListLongOctetStringWithValue:(NSArray * _Nonnull)value par } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [NSData class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], NSData); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(NSData.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSData *)value[i_0]; listHolder_0->mList[i_0] = AsByteSpan(element_0); } cppValue = ListType_0(listHolder_0->mList, value.count); @@ -105824,11 +105845,12 @@ - (void)writeAttributeListFabricScopedWithValue:(NSArray * _Nonnull)value params } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRUnitTestingClusterTestFabricScoped class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRUnitTestingClusterTestFabricScoped); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRUnitTestingClusterTestFabricScoped.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRUnitTestingClusterTestFabricScoped *)value[i_0]; listHolder_0->mList[i_0].fabricSensitiveInt8u = element_0.fabricSensitiveInt8u.unsignedCharValue; if (element_0.optionalFabricSensitiveInt8u != nil) { auto & definedValue_2 = listHolder_0->mList[i_0].optionalFabricSensitiveInt8u.Emplace(); @@ -105872,11 +105894,12 @@ - (void)writeAttributeListFabricScopedWithValue:(NSArray * _Nonnull)value params } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.fabricSensitiveInt8uList.count; ++i_2) { - if ( ! [element_0.fabricSensitiveInt8uList[i_2] isKindOfClass: [NSNumber class]] ) { + auto element_2 = MTR_SAFE_CAST(element_0.fabricSensitiveInt8uList[i_2], NSNumber); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.fabricSensitiveInt8uList[i_2], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (NSNumber *)element_0.fabricSensitiveInt8uList[i_2]; listHolder_2->mList[i_2] = element_2.unsignedCharValue; } listHolder_0->mList[i_0].fabricSensitiveInt8uList = ListType_2(listHolder_2->mList, element_0.fabricSensitiveInt8uList.count); diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm index 6d8ddd60910f47..318455a23b9210 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm @@ -20,6 +20,7 @@ #import "MTRBaseDevice_Internal.h" #import "MTRCommandPayloadExtensions_Internal.h" #import "MTRCommandPayloads_Internal.h" +#import "MTRDefines_Internal.h" #import "MTRError_Internal.h" #import "MTRLogging_Internal.h" #import "NSDataSpanConversion.h" @@ -641,11 +642,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.groupList.count; ++i_0) { - if (![self.groupList[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.groupList[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.groupList[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.groupList[i_0]; listHolder_0->mList[i_0] = element_0.unsignedShortValue; } encodableStruct.groupList = ListType_0(listHolder_0->mList, self.groupList.count); @@ -2559,11 +2561,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arl.count; ++i_0) { - if (![self.arl[i_0] isKindOfClass:[MTRAccessControlClusterCommissioningAccessRestrictionEntryStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.arl[i_0], MTRAccessControlClusterCommissioningAccessRestrictionEntryStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arl[i_0], NSStringFromClass(MTRAccessControlClusterCommissioningAccessRestrictionEntryStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRAccessControlClusterCommissioningAccessRestrictionEntryStruct *) self.arl[i_0]; listHolder_0->mList[i_0].endpoint = element_0.endpoint.unsignedShortValue; listHolder_0->mList[i_0].cluster = element_0.cluster.unsignedIntValue; { @@ -2576,11 +2579,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.restrictions.count; ++i_2) { - if (![element_0.restrictions[i_2] isKindOfClass:[MTRAccessControlClusterAccessRestrictionStruct class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.restrictions[i_2], MTRAccessControlClusterAccessRestrictionStruct); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.restrictions[i_2], NSStringFromClass(MTRAccessControlClusterAccessRestrictionStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (MTRAccessControlClusterAccessRestrictionStruct *) element_0.restrictions[i_2]; listHolder_2->mList[i_2].type = static_castmList[i_2].type)>>(element_2.type.unsignedCharValue); if (element_2.id == nil) { listHolder_2->mList[i_2].id.SetNull(); @@ -3910,11 +3914,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.protocolsSupported.count; ++i_0) { - if (![self.protocolsSupported[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.protocolsSupported[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.protocolsSupported[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.protocolsSupported[i_0]; listHolder_0->mList[i_0] = static_castmList[i_0])>>(element_0.unsignedCharValue); } encodableStruct.protocolsSupported = ListType_0(listHolder_0->mList, self.protocolsSupported.count); @@ -7601,11 +7606,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.timeZone.count; ++i_0) { - if (![self.timeZone[i_0] isKindOfClass:[MTRTimeSynchronizationClusterTimeZoneStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.timeZone[i_0], MTRTimeSynchronizationClusterTimeZoneStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.timeZone[i_0], NSStringFromClass(MTRTimeSynchronizationClusterTimeZoneStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRTimeSynchronizationClusterTimeZoneStruct *) self.timeZone[i_0]; listHolder_0->mList[i_0].offset = element_0.offset.intValue; listHolder_0->mList[i_0].validAt = element_0.validAt.unsignedLongLongValue; if (element_0.name != nil) { @@ -7785,11 +7791,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.dstOffset.count; ++i_0) { - if (![self.dstOffset[i_0] isKindOfClass:[MTRTimeSynchronizationClusterDSTOffsetStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.dstOffset[i_0], MTRTimeSynchronizationClusterDSTOffsetStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.dstOffset[i_0], NSStringFromClass(MTRTimeSynchronizationClusterDSTOffsetStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRTimeSynchronizationClusterDSTOffsetStruct *) self.dstOffset[i_0]; listHolder_0->mList[i_0].offset = element_0.offset.intValue; listHolder_0->mList[i_0].validStarting = element_0.validStarting.unsignedLongLongValue; if (element_0.validUntil == nil) { @@ -13509,11 +13516,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.extensionFieldSets.count; ++i_0) { - if (![self.extensionFieldSets[i_0] isKindOfClass:[MTRScenesManagementClusterExtensionFieldSet class]]) { + auto element_0 = MTR_SAFE_CAST(self.extensionFieldSets[i_0], MTRScenesManagementClusterExtensionFieldSet); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.extensionFieldSets[i_0], NSStringFromClass(MTRScenesManagementClusterExtensionFieldSet.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRScenesManagementClusterExtensionFieldSet *) self.extensionFieldSets[i_0]; listHolder_0->mList[i_0].clusterID = element_0.clusterID.unsignedIntValue; { using ListType_2 = std::remove_reference_tmList[i_0].attributeValueList)>; @@ -13525,11 +13533,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.attributeValueList.count; ++i_2) { - if (![element_0.attributeValueList[i_2] isKindOfClass:[MTRScenesManagementClusterAttributeValuePairStruct class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.attributeValueList[i_2], MTRScenesManagementClusterAttributeValuePairStruct); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.attributeValueList[i_2], NSStringFromClass(MTRScenesManagementClusterAttributeValuePairStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (MTRScenesManagementClusterAttributeValuePairStruct *) element_0.attributeValueList[i_2]; listHolder_2->mList[i_2].attributeID = element_2.attributeID.unsignedIntValue; if (element_2.valueUnsigned8 != nil) { auto & definedValue_4 = listHolder_2->mList[i_2].valueUnsigned8.Emplace(); @@ -15884,11 +15893,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.event.transitions.count; ++i_1) { - if (![self.event.transitions[i_1] isKindOfClass:[MTRDemandResponseLoadControlClusterLoadControlEventTransitionStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.event.transitions[i_1], MTRDemandResponseLoadControlClusterLoadControlEventTransitionStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.event.transitions[i_1], NSStringFromClass(MTRDemandResponseLoadControlClusterLoadControlEventTransitionStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRDemandResponseLoadControlClusterLoadControlEventTransitionStruct *) self.event.transitions[i_1]; listHolder_1->mList[i_1].duration = element_1.duration.unsignedShortValue; listHolder_1->mList[i_1].control = static_castmList[i_1].control)>>(element_1.control.unsignedShortValue); if (element_1.temperatureControl != nil) { @@ -16246,11 +16256,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.responses.count; ++i_1) { - if (![self.responses[i_1] isKindOfClass:[MTRMessagesClusterMessageResponseOptionStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.responses[i_1], MTRMessagesClusterMessageResponseOptionStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.responses[i_1], NSStringFromClass(MTRMessagesClusterMessageResponseOptionStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRMessagesClusterMessageResponseOptionStruct *) self.responses[i_1]; if (element_1.messageResponseID != nil) { auto & definedValue_3 = listHolder_1->mList[i_1].messageResponseID.Emplace(); definedValue_3 = element_1.messageResponseID.unsignedIntValue; @@ -16354,11 +16365,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.messageIDs.count; ++i_0) { - if (![self.messageIDs[i_0] isKindOfClass:[NSData class]]) { + auto element_0 = MTR_SAFE_CAST(self.messageIDs[i_0], NSData); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.messageIDs[i_0], NSStringFromClass(NSData.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSData *) self.messageIDs[i_0]; listHolder_0->mList[i_0] = AsByteSpan(element_0); } encodableStruct.messageIDs = ListType_0(listHolder_0->mList, self.messageIDs.count); @@ -16870,11 +16882,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.slotAdjustments.count; ++i_0) { - if (![self.slotAdjustments[i_0] isKindOfClass:[MTRDeviceEnergyManagementClusterSlotAdjustmentStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.slotAdjustments[i_0], MTRDeviceEnergyManagementClusterSlotAdjustmentStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.slotAdjustments[i_0], NSStringFromClass(MTRDeviceEnergyManagementClusterSlotAdjustmentStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRDeviceEnergyManagementClusterSlotAdjustmentStruct *) self.slotAdjustments[i_0]; listHolder_0->mList[i_0].slotIndex = element_0.slotIndex.unsignedCharValue; if (element_0.nominalPower != nil) { auto & definedValue_2 = listHolder_0->mList[i_0].nominalPower.Emplace(); @@ -16981,11 +16994,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.constraints.count; ++i_0) { - if (![self.constraints[i_0] isKindOfClass:[MTRDeviceEnergyManagementClusterConstraintsStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.constraints[i_0], MTRDeviceEnergyManagementClusterConstraintsStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.constraints[i_0], NSStringFromClass(MTRDeviceEnergyManagementClusterConstraintsStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRDeviceEnergyManagementClusterConstraintsStruct *) self.constraints[i_0]; listHolder_0->mList[i_0].startTime = element_0.startTime.unsignedIntValue; listHolder_0->mList[i_0].duration = element_0.duration.unsignedIntValue; if (element_0.nominalPower != nil) { @@ -17622,11 +17636,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.chargingTargetSchedules.count; ++i_0) { - if (![self.chargingTargetSchedules[i_0] isKindOfClass:[MTREnergyEVSEClusterChargingTargetScheduleStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.chargingTargetSchedules[i_0], MTREnergyEVSEClusterChargingTargetScheduleStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.chargingTargetSchedules[i_0], NSStringFromClass(MTREnergyEVSEClusterChargingTargetScheduleStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTREnergyEVSEClusterChargingTargetScheduleStruct *) self.chargingTargetSchedules[i_0]; listHolder_0->mList[i_0].dayOfWeekForSequence = static_castmList[i_0].dayOfWeekForSequence)>>(element_0.dayOfWeekForSequence.unsignedCharValue); { using ListType_2 = std::remove_reference_tmList[i_0].chargingTargets)>; @@ -17638,11 +17653,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.chargingTargets.count; ++i_2) { - if (![element_0.chargingTargets[i_2] isKindOfClass:[MTREnergyEVSEClusterChargingTargetStruct class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.chargingTargets[i_2], MTREnergyEVSEClusterChargingTargetStruct); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.chargingTargets[i_2], NSStringFromClass(MTREnergyEVSEClusterChargingTargetStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (MTREnergyEVSEClusterChargingTargetStruct *) element_0.chargingTargets[i_2]; listHolder_2->mList[i_2].targetTimeMinutesPastMidnight = element_2.targetTimeMinutesPastMidnight.unsignedShortValue; if (element_2.targetSoC != nil) { auto & definedValue_4 = listHolder_2->mList[i_2].targetSoC.Emplace(); @@ -21675,11 +21691,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.newAreas.count; ++i_0) { - if (![self.newAreas[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.newAreas[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.newAreas[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.newAreas[i_0]; listHolder_0->mList[i_0] = element_0.unsignedIntValue; } encodableStruct.newAreas = ListType_0(listHolder_0->mList, self.newAreas.count); @@ -22259,11 +22276,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.transitions.count; ++i_0) { - if (![self.transitions[i_0] isKindOfClass:[MTRThermostatClusterWeeklyScheduleTransitionStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.transitions[i_0], MTRThermostatClusterWeeklyScheduleTransitionStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.transitions[i_0], NSStringFromClass(MTRThermostatClusterWeeklyScheduleTransitionStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRThermostatClusterWeeklyScheduleTransitionStruct *) self.transitions[i_0]; listHolder_0->mList[i_0].transitionTime = element_0.transitionTime.unsignedShortValue; if (element_0.heatSetpoint == nil) { listHolder_0->mList[i_0].heatSetpoint.SetNull(); @@ -22812,11 +22830,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.attributeRequests.count; ++i_0) { - if (![self.attributeRequests[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.attributeRequests[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.attributeRequests[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.attributeRequests[i_0]; listHolder_0->mList[i_0] = element_0.unsignedIntValue; } encodableStruct.attributeRequests = ListType_0(listHolder_0->mList, self.attributeRequests.count); @@ -26190,11 +26209,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.channelList.count; ++i_1) { - if (![self.channelList[i_1] isKindOfClass:[MTRChannelClusterChannelInfoStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.channelList[i_1], MTRChannelClusterChannelInfoStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.channelList[i_1], NSStringFromClass(MTRChannelClusterChannelInfoStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRChannelClusterChannelInfoStruct *) self.channelList[i_1]; listHolder_1->mList[i_1].majorNumber = element_1.majorNumber.unsignedShortValue; listHolder_1->mList[i_1].minorNumber = element_1.minorNumber.unsignedShortValue; if (element_1.name != nil) { @@ -26261,11 +26281,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.externalIDList.count; ++i_1) { - if (![self.externalIDList[i_1] isKindOfClass:[MTRChannelClusterAdditionalInfoStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.externalIDList[i_1], MTRChannelClusterAdditionalInfoStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.externalIDList[i_1], NSStringFromClass(MTRChannelClusterAdditionalInfoStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRChannelClusterAdditionalInfoStruct *) self.externalIDList[i_1]; listHolder_1->mList[i_1].name = AsCharSpan(element_1.name); listHolder_1->mList[i_1].value = AsCharSpan(element_1.value); } @@ -26827,11 +26848,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.externalIDList.count; ++i_0) { - if (![self.externalIDList[i_0] isKindOfClass:[MTRChannelClusterAdditionalInfoStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.externalIDList[i_0], MTRChannelClusterAdditionalInfoStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.externalIDList[i_0], NSStringFromClass(MTRChannelClusterAdditionalInfoStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRChannelClusterAdditionalInfoStruct *) self.externalIDList[i_0]; listHolder_0->mList[i_0].name = AsCharSpan(element_0.name); listHolder_0->mList[i_0].value = AsCharSpan(element_0.value); } @@ -26946,11 +26968,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.externalIDList.count; ++i_0) { - if (![self.externalIDList[i_0] isKindOfClass:[MTRChannelClusterAdditionalInfoStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.externalIDList[i_0], MTRChannelClusterAdditionalInfoStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.externalIDList[i_0], NSStringFromClass(MTRChannelClusterAdditionalInfoStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRChannelClusterAdditionalInfoStruct *) self.externalIDList[i_0]; listHolder_0->mList[i_0].name = AsCharSpan(element_0.name); listHolder_0->mList[i_0].value = AsCharSpan(element_0.value); } @@ -28964,11 +28987,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.search.parameterList.count; ++i_1) { - if (![self.search.parameterList[i_1] isKindOfClass:[MTRContentLauncherClusterParameterStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.search.parameterList[i_1], MTRContentLauncherClusterParameterStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.search.parameterList[i_1], NSStringFromClass(MTRContentLauncherClusterParameterStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRContentLauncherClusterParameterStruct *) self.search.parameterList[i_1]; listHolder_1->mList[i_1].type = static_castmList[i_1].type)>>(element_1.type.unsignedCharValue); listHolder_1->mList[i_1].value = AsCharSpan(element_1.value); if (element_1.externalIDList != nil) { @@ -28983,11 +29007,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_4); for (size_t i_4 = 0; i_4 < element_1.externalIDList.count; ++i_4) { - if (![element_1.externalIDList[i_4] isKindOfClass:[MTRContentLauncherClusterAdditionalInfoStruct class]]) { + auto element_4 = MTR_SAFE_CAST(element_1.externalIDList[i_4], MTRContentLauncherClusterAdditionalInfoStruct); + if (!element_4) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_1.externalIDList[i_4], NSStringFromClass(MTRContentLauncherClusterAdditionalInfoStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_4 = (MTRContentLauncherClusterAdditionalInfoStruct *) element_1.externalIDList[i_4]; listHolder_4->mList[i_4].name = AsCharSpan(element_4.name); listHolder_4->mList[i_4].value = AsCharSpan(element_4.value); } @@ -29030,11 +29055,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_4); for (size_t i_4 = 0; i_4 < self.playbackPreferences.textTrack.characteristics.count; ++i_4) { - if (![self.playbackPreferences.textTrack.characteristics[i_4] isKindOfClass:[NSNumber class]]) { + auto element_4 = MTR_SAFE_CAST(self.playbackPreferences.textTrack.characteristics[i_4], NSNumber); + if (!element_4) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.playbackPreferences.textTrack.characteristics[i_4], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_4 = (NSNumber *) self.playbackPreferences.textTrack.characteristics[i_4]; listHolder_4->mList[i_4] = static_castmList[i_4])>>(element_4.unsignedCharValue); } definedValue_3 = ListType_4(listHolder_4->mList, self.playbackPreferences.textTrack.characteristics.count); @@ -29056,11 +29082,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_3); for (size_t i_3 = 0; i_3 < self.playbackPreferences.audioTracks.count; ++i_3) { - if (![self.playbackPreferences.audioTracks[i_3] isKindOfClass:[MTRContentLauncherClusterTrackPreferenceStruct class]]) { + auto element_3 = MTR_SAFE_CAST(self.playbackPreferences.audioTracks[i_3], MTRContentLauncherClusterTrackPreferenceStruct); + if (!element_3) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.playbackPreferences.audioTracks[i_3], NSStringFromClass(MTRContentLauncherClusterTrackPreferenceStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_3 = (MTRContentLauncherClusterTrackPreferenceStruct *) self.playbackPreferences.audioTracks[i_3]; listHolder_3->mList[i_3].languageCode = AsCharSpan(element_3.languageCode); if (element_3.characteristics != nil) { auto & definedValue_5 = listHolder_3->mList[i_3].characteristics.Emplace(); @@ -29074,11 +29101,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_6); for (size_t i_6 = 0; i_6 < element_3.characteristics.count; ++i_6) { - if (![element_3.characteristics[i_6] isKindOfClass:[NSNumber class]]) { + auto element_6 = MTR_SAFE_CAST(element_3.characteristics[i_6], NSNumber); + if (!element_6) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_3.characteristics[i_6], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_6 = (NSNumber *) element_3.characteristics[i_6]; listHolder_6->mList[i_6] = static_castmList[i_6])>>(element_6.unsignedCharValue); } definedValue_5 = ListType_6(listHolder_6->mList, element_3.characteristics.count); @@ -31387,11 +31415,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.zone.vertices.count; ++i_1) { - if (![self.zone.vertices[i_1] isKindOfClass:[MTRZoneManagementClusterTwoDCartesianVertexStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.zone.vertices[i_1], MTRZoneManagementClusterTwoDCartesianVertexStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.zone.vertices[i_1], NSStringFromClass(MTRZoneManagementClusterTwoDCartesianVertexStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRZoneManagementClusterTwoDCartesianVertexStruct *) self.zone.vertices[i_1]; listHolder_1->mList[i_1].x = element_1.x.unsignedShortValue; listHolder_1->mList[i_1].y = element_1.y.unsignedShortValue; } @@ -31579,11 +31608,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.zone.vertices.count; ++i_1) { - if (![self.zone.vertices[i_1] isKindOfClass:[MTRZoneManagementClusterTwoDCartesianVertexStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.zone.vertices[i_1], MTRZoneManagementClusterTwoDCartesianVertexStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.zone.vertices[i_1], NSStringFromClass(MTRZoneManagementClusterTwoDCartesianVertexStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRZoneManagementClusterTwoDCartesianVertexStruct *) self.zone.vertices[i_1]; listHolder_1->mList[i_1].x = element_1.x.unsignedShortValue; listHolder_1->mList[i_1].y = element_1.y.unsignedShortValue; } @@ -32929,11 +32959,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.streamPriorities.count; ++i_0) { - if (![self.streamPriorities[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.streamPriorities[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.streamPriorities[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.streamPriorities[i_0]; listHolder_0->mList[i_0] = static_castmList[i_0])>>(element_0.unsignedCharValue); } encodableStruct.streamPriorities = ListType_0(listHolder_0->mList, self.streamPriorities.count); @@ -33250,11 +33281,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.iceServers.count; ++i_1) { - if (![self.iceServers[i_1] isKindOfClass:[MTRWebRTCTransportProviderClusterICEServerStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.iceServers[i_1], MTRWebRTCTransportProviderClusterICEServerStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.iceServers[i_1], NSStringFromClass(MTRWebRTCTransportProviderClusterICEServerStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRWebRTCTransportProviderClusterICEServerStruct *) self.iceServers[i_1]; { using ListType_3 = std::remove_reference_tmList[i_1].urls)>; using ListMemberType_3 = ListMemberTypeGetter::Type; @@ -33265,11 +33297,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_3); for (size_t i_3 = 0; i_3 < element_1.urls.count; ++i_3) { - if (![element_1.urls[i_3] isKindOfClass:[NSString class]]) { + auto element_3 = MTR_SAFE_CAST(element_1.urls[i_3], NSString); + if (!element_3) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_1.urls[i_3], NSStringFromClass(NSString.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_3 = (NSString *) element_1.urls[i_3]; listHolder_3->mList[i_3] = AsCharSpan(element_3); } listHolder_1->mList[i_1].urls = ListType_3(listHolder_3->mList, element_1.urls.count); @@ -33568,11 +33601,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.iceServers.count; ++i_1) { - if (![self.iceServers[i_1] isKindOfClass:[MTRWebRTCTransportProviderClusterICEServerStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.iceServers[i_1], MTRWebRTCTransportProviderClusterICEServerStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.iceServers[i_1], NSStringFromClass(MTRWebRTCTransportProviderClusterICEServerStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRWebRTCTransportProviderClusterICEServerStruct *) self.iceServers[i_1]; { using ListType_3 = std::remove_reference_tmList[i_1].urls)>; using ListMemberType_3 = ListMemberTypeGetter::Type; @@ -33583,11 +33617,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_3); for (size_t i_3 = 0; i_3 < element_1.urls.count; ++i_3) { - if (![element_1.urls[i_3] isKindOfClass:[NSString class]]) { + auto element_3 = MTR_SAFE_CAST(element_1.urls[i_3], NSString); + if (!element_3) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_1.urls[i_3], NSStringFromClass(NSString.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_3 = (NSString *) element_1.urls[i_3]; listHolder_3->mList[i_3] = AsCharSpan(element_3); } listHolder_1->mList[i_1].urls = ListType_3(listHolder_3->mList, element_1.urls.count); @@ -34077,11 +34112,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.iceServers.count; ++i_1) { - if (![self.iceServers[i_1] isKindOfClass:[MTRWebRTCTransportRequestorClusterICEServerStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.iceServers[i_1], MTRWebRTCTransportRequestorClusterICEServerStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.iceServers[i_1], NSStringFromClass(MTRWebRTCTransportRequestorClusterICEServerStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRWebRTCTransportRequestorClusterICEServerStruct *) self.iceServers[i_1]; { using ListType_3 = std::remove_reference_tmList[i_1].urls)>; using ListMemberType_3 = ListMemberTypeGetter::Type; @@ -34092,11 +34128,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_3); for (size_t i_3 = 0; i_3 < element_1.urls.count; ++i_3) { - if (![element_1.urls[i_3] isKindOfClass:[NSString class]]) { + auto element_3 = MTR_SAFE_CAST(element_1.urls[i_3], NSString); + if (!element_3) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_1.urls[i_3], NSStringFromClass(NSString.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_3 = (NSString *) element_1.urls[i_3]; listHolder_3->mList[i_3] = AsCharSpan(element_3); } listHolder_1->mList[i_1].urls = ListType_3(listHolder_3->mList, element_1.urls.count); @@ -36079,11 +36116,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arg1.count; ++i_0) { - if (![self.arg1[i_0] isKindOfClass:[MTRUnitTestingClusterNestedStructList class]]) { + auto element_0 = MTR_SAFE_CAST(self.arg1[i_0], MTRUnitTestingClusterNestedStructList); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1[i_0], NSStringFromClass(MTRUnitTestingClusterNestedStructList.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRUnitTestingClusterNestedStructList *) self.arg1[i_0]; listHolder_0->mList[i_0].a = element_0.a.unsignedCharValue; listHolder_0->mList[i_0].b = element_0.b.boolValue; listHolder_0->mList[i_0].c.a = element_0.c.a.unsignedCharValue; @@ -36108,11 +36146,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.d.count; ++i_2) { - if (![element_0.d[i_2] isKindOfClass:[MTRUnitTestingClusterSimpleStruct class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.d[i_2], MTRUnitTestingClusterSimpleStruct); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.d[i_2], NSStringFromClass(MTRUnitTestingClusterSimpleStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (MTRUnitTestingClusterSimpleStruct *) element_0.d[i_2]; listHolder_2->mList[i_2].a = element_2.a.unsignedCharValue; listHolder_2->mList[i_2].b = element_2.b.boolValue; listHolder_2->mList[i_2].c = static_castmList[i_2].c)>>(element_2.c.unsignedCharValue); @@ -36141,11 +36180,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.e.count; ++i_2) { - if (![element_0.e[i_2] isKindOfClass:[NSNumber class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.e[i_2], NSNumber); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.e[i_2], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (NSNumber *) element_0.e[i_2]; listHolder_2->mList[i_2] = element_2.unsignedIntValue; } listHolder_0->mList[i_0].e = ListType_2(listHolder_2->mList, element_0.e.count); @@ -36163,11 +36203,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.f.count; ++i_2) { - if (![element_0.f[i_2] isKindOfClass:[NSData class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.f[i_2], NSData); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.f[i_2], NSStringFromClass(NSData.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (NSData *) element_0.f[i_2]; listHolder_2->mList[i_2] = AsByteSpan(element_2); } listHolder_0->mList[i_0].f = ListType_2(listHolder_2->mList, element_0.f.count); @@ -36185,11 +36226,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.g.count; ++i_2) { - if (![element_0.g[i_2] isKindOfClass:[NSNumber class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.g[i_2], NSNumber); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.g[i_2], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (NSNumber *) element_0.g[i_2]; listHolder_2->mList[i_2] = element_2.unsignedCharValue; } listHolder_0->mList[i_0].g = ListType_2(listHolder_2->mList, element_0.g.count); @@ -36215,11 +36257,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arg2.count; ++i_0) { - if (![self.arg2[i_0] isKindOfClass:[MTRUnitTestingClusterSimpleStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.arg2[i_0], MTRUnitTestingClusterSimpleStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg2[i_0], NSStringFromClass(MTRUnitTestingClusterSimpleStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRUnitTestingClusterSimpleStruct *) self.arg2[i_0]; listHolder_0->mList[i_0].a = element_0.a.unsignedCharValue; listHolder_0->mList[i_0].b = element_0.b.boolValue; listHolder_0->mList[i_0].c = static_castmList[i_0].c)>>(element_0.c.unsignedCharValue); @@ -36250,11 +36293,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arg3.count; ++i_0) { - if (![self.arg3[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.arg3[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg3[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.arg3[i_0]; listHolder_0->mList[i_0] = static_castmList[i_0])>>(element_0.unsignedCharValue); } encodableStruct.arg3 = ListType_0(listHolder_0->mList, self.arg3.count); @@ -36274,11 +36318,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arg4.count; ++i_0) { - if (![self.arg4[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.arg4[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg4[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.arg4[i_0]; listHolder_0->mList[i_0] = element_0.boolValue; } encodableStruct.arg4 = ListType_0(listHolder_0->mList, self.arg4.count); @@ -37257,11 +37302,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arg1.count; ++i_0) { - if (![self.arg1[i_0] isKindOfClass:[MTRUnitTestingClusterSimpleStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.arg1[i_0], MTRUnitTestingClusterSimpleStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1[i_0], NSStringFromClass(MTRUnitTestingClusterSimpleStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRUnitTestingClusterSimpleStruct *) self.arg1[i_0]; listHolder_0->mList[i_0].a = element_0.a.unsignedCharValue; listHolder_0->mList[i_0].b = element_0.b.boolValue; listHolder_0->mList[i_0].c = static_castmList[i_0].c)>>(element_0.c.unsignedCharValue); @@ -37477,11 +37523,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arg1.count; ++i_0) { - if (![self.arg1[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.arg1[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.arg1[i_0]; listHolder_0->mList[i_0] = element_0.unsignedCharValue; } encodableStruct.arg1 = ListType_0(listHolder_0->mList, self.arg1.count); @@ -37683,11 +37730,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.arg1.d.count; ++i_1) { - if (![self.arg1.d[i_1] isKindOfClass:[MTRUnitTestingClusterSimpleStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.arg1.d[i_1], MTRUnitTestingClusterSimpleStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1.d[i_1], NSStringFromClass(MTRUnitTestingClusterSimpleStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRUnitTestingClusterSimpleStruct *) self.arg1.d[i_1]; listHolder_1->mList[i_1].a = element_1.a.unsignedCharValue; listHolder_1->mList[i_1].b = element_1.b.boolValue; listHolder_1->mList[i_1].c = static_castmList[i_1].c)>>(element_1.c.unsignedCharValue); @@ -37716,11 +37764,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.arg1.e.count; ++i_1) { - if (![self.arg1.e[i_1] isKindOfClass:[NSNumber class]]) { + auto element_1 = MTR_SAFE_CAST(self.arg1.e[i_1], NSNumber); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1.e[i_1], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (NSNumber *) self.arg1.e[i_1]; listHolder_1->mList[i_1] = element_1.unsignedIntValue; } encodableStruct.arg1.e = ListType_1(listHolder_1->mList, self.arg1.e.count); @@ -37738,11 +37787,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.arg1.f.count; ++i_1) { - if (![self.arg1.f[i_1] isKindOfClass:[NSData class]]) { + auto element_1 = MTR_SAFE_CAST(self.arg1.f[i_1], NSData); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1.f[i_1], NSStringFromClass(NSData.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (NSData *) self.arg1.f[i_1]; listHolder_1->mList[i_1] = AsByteSpan(element_1); } encodableStruct.arg1.f = ListType_1(listHolder_1->mList, self.arg1.f.count); @@ -37760,11 +37810,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.arg1.g.count; ++i_1) { - if (![self.arg1.g[i_1] isKindOfClass:[NSNumber class]]) { + auto element_1 = MTR_SAFE_CAST(self.arg1.g[i_1], NSNumber); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1.g[i_1], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (NSNumber *) self.arg1.g[i_1]; listHolder_1->mList[i_1] = element_1.unsignedCharValue; } encodableStruct.arg1.g = ListType_1(listHolder_1->mList, self.arg1.g.count); @@ -37952,11 +38003,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arg1.count; ++i_0) { - if (![self.arg1[i_0] isKindOfClass:[MTRUnitTestingClusterNestedStructList class]]) { + auto element_0 = MTR_SAFE_CAST(self.arg1[i_0], MTRUnitTestingClusterNestedStructList); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1[i_0], NSStringFromClass(MTRUnitTestingClusterNestedStructList.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRUnitTestingClusterNestedStructList *) self.arg1[i_0]; listHolder_0->mList[i_0].a = element_0.a.unsignedCharValue; listHolder_0->mList[i_0].b = element_0.b.boolValue; listHolder_0->mList[i_0].c.a = element_0.c.a.unsignedCharValue; @@ -37981,11 +38033,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.d.count; ++i_2) { - if (![element_0.d[i_2] isKindOfClass:[MTRUnitTestingClusterSimpleStruct class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.d[i_2], MTRUnitTestingClusterSimpleStruct); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.d[i_2], NSStringFromClass(MTRUnitTestingClusterSimpleStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (MTRUnitTestingClusterSimpleStruct *) element_0.d[i_2]; listHolder_2->mList[i_2].a = element_2.a.unsignedCharValue; listHolder_2->mList[i_2].b = element_2.b.boolValue; listHolder_2->mList[i_2].c = static_castmList[i_2].c)>>(element_2.c.unsignedCharValue); @@ -38014,11 +38067,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.e.count; ++i_2) { - if (![element_0.e[i_2] isKindOfClass:[NSNumber class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.e[i_2], NSNumber); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.e[i_2], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (NSNumber *) element_0.e[i_2]; listHolder_2->mList[i_2] = element_2.unsignedIntValue; } listHolder_0->mList[i_0].e = ListType_2(listHolder_2->mList, element_0.e.count); @@ -38036,11 +38090,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.f.count; ++i_2) { - if (![element_0.f[i_2] isKindOfClass:[NSData class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.f[i_2], NSData); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.f[i_2], NSStringFromClass(NSData.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (NSData *) element_0.f[i_2]; listHolder_2->mList[i_2] = AsByteSpan(element_2); } listHolder_0->mList[i_0].f = ListType_2(listHolder_2->mList, element_0.f.count); @@ -38058,11 +38113,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.g.count; ++i_2) { - if (![element_0.g[i_2] isKindOfClass:[NSNumber class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.g[i_2], NSNumber); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.g[i_2], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (NSNumber *) element_0.g[i_2]; listHolder_2->mList[i_2] = element_2.unsignedCharValue; } listHolder_0->mList[i_0].g = ListType_2(listHolder_2->mList, element_0.g.count); @@ -38249,11 +38305,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arg1.count; ++i_0) { - if (![self.arg1[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.arg1[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.arg1[i_0]; listHolder_0->mList[i_0] = element_0.unsignedCharValue; } encodableStruct.arg1 = ListType_0(listHolder_0->mList, self.arg1.count); @@ -38868,11 +38925,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.nullableList.count; ++i_1) { - if (![self.nullableList[i_1] isKindOfClass:[NSNumber class]]) { + auto element_1 = MTR_SAFE_CAST(self.nullableList[i_1], NSNumber); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.nullableList[i_1], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (NSNumber *) self.nullableList[i_1]; listHolder_1->mList[i_1] = static_castmList[i_1])>>(element_1.unsignedCharValue); } nonNullValue_0 = ListType_1(listHolder_1->mList, self.nullableList.count); @@ -38895,11 +38953,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.optionalList.count; ++i_1) { - if (![self.optionalList[i_1] isKindOfClass:[NSNumber class]]) { + auto element_1 = MTR_SAFE_CAST(self.optionalList[i_1], NSNumber); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.optionalList[i_1], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (NSNumber *) self.optionalList[i_1]; listHolder_1->mList[i_1] = static_castmList[i_1])>>(element_1.unsignedCharValue); } definedValue_0 = ListType_1(listHolder_1->mList, self.optionalList.count); @@ -38926,11 +38985,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < self.nullableOptionalList.count; ++i_2) { - if (![self.nullableOptionalList[i_2] isKindOfClass:[NSNumber class]]) { + auto element_2 = MTR_SAFE_CAST(self.nullableOptionalList[i_2], NSNumber); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.nullableOptionalList[i_2], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (NSNumber *) self.nullableOptionalList[i_2]; listHolder_2->mList[i_2] = static_castmList[i_2])>>(element_2.unsignedCharValue); } nonNullValue_1 = ListType_2(listHolder_2->mList, self.nullableOptionalList.count); diff --git a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj index fa1634da4b9267..13f0eb8e203e7b 100644 --- a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj +++ b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj @@ -422,6 +422,10 @@ B4FCD5722B603A6300832859 /* DownloadLogCommand.mm in Sources */ = {isa = PBXBuildFile; fileRef = B4FCD56F2B603A6300832859 /* DownloadLogCommand.mm */; }; B4FCD5732B611EB300832859 /* MTRDiagnosticLogsDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = B4C8E6B32B3453AD00FCD54D /* MTRDiagnosticLogsDownloader.h */; }; BA09EB43247477BA00605257 /* libCHIP.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BA09EB3F2474762900605257 /* libCHIP.a */; }; + CF3B63CF2CA31E71003C1C87 /* MTROTAImageTransferHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = CF3B63CB2CA31E71003C1C87 /* MTROTAImageTransferHandler.h */; }; + CF3B63D02CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = CF3B63CC2CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.h */; }; + CF3B63D12CA31E71003C1C87 /* MTROTAImageTransferHandler.mm in Sources */ = {isa = PBXBuildFile; fileRef = CF3B63CD2CA31E71003C1C87 /* MTROTAImageTransferHandler.mm */; }; + CF3B63D22CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.mm in Sources */ = {isa = PBXBuildFile; fileRef = CF3B63CE2CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.mm */; }; D4288E872C8A273F002FEC53 /* MTRDevice_XPC_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = D4288E862C8A273F002FEC53 /* MTRDevice_XPC_Internal.h */; }; D444F9A72C6E8F9D007761E5 /* MTRXPCServerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D444F9A62C6E8F9D007761E5 /* MTRXPCServerProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D444F9AA2C6E9A08007761E5 /* MTRXPCClientProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D444F9A82C6E99CA007761E5 /* MTRXPCClientProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -901,6 +905,10 @@ B4FCD56F2B603A6300832859 /* DownloadLogCommand.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DownloadLogCommand.mm; sourceTree = ""; }; BA09EB3F2474762900605257 /* libCHIP.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libCHIP.a; path = lib/libCHIP.a; sourceTree = BUILT_PRODUCTS_DIR; }; BA107AEE2470CFBB004287EB /* chip_xcode_build_connector.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = chip_xcode_build_connector.sh; sourceTree = ""; }; + CF3B63CB2CA31E71003C1C87 /* MTROTAImageTransferHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTROTAImageTransferHandler.h; sourceTree = ""; }; + CF3B63CC2CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTROTAUnsolicitedBDXMessageHandler.h; sourceTree = ""; }; + CF3B63CD2CA31E71003C1C87 /* MTROTAImageTransferHandler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTROTAImageTransferHandler.mm; sourceTree = ""; }; + CF3B63CE2CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTROTAUnsolicitedBDXMessageHandler.mm; sourceTree = ""; }; D4288E862C8A273F002FEC53 /* MTRDevice_XPC_Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRDevice_XPC_Internal.h; sourceTree = ""; }; D437613E285BDC0D0051FEA2 /* MTRErrorTestUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRErrorTestUtils.h; sourceTree = ""; }; D437613F285BDC0D0051FEA2 /* MTRTestKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRTestKeys.h; sourceTree = ""; }; @@ -1371,6 +1379,10 @@ B202528F2459E34F00F97062 /* CHIP */ = { isa = PBXGroup; children = ( + CF3B63CB2CA31E71003C1C87 /* MTROTAImageTransferHandler.h */, + CF3B63CD2CA31E71003C1C87 /* MTROTAImageTransferHandler.mm */, + CF3B63CC2CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.h */, + CF3B63CE2CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.mm */, D444F9A12C6E8058007761E5 /* XPC Protocol */, 88E07D602B9A89A4005FD53E /* MTRMetricKeys.h */, 88FA798B2B7B257100CD4B6F /* MTRMetricsCollector.h */, @@ -1835,6 +1847,7 @@ B2E0D7B2245B0B5C003C5B48 /* MTRManualSetupPayloadParser.h in Headers */, 5109E9C02CCAD64F0006884B /* MTRDeviceDataValidation.h in Headers */, 3CF134A7289D8ADA0017A19E /* MTRCSRInfo.h in Headers */, + CF3B63D02CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.h in Headers */, 88E07D612B9A89A4005FD53E /* MTRMetricKeys.h in Headers */, 3D4733B32BE2D1DA003DC19B /* MTRUtilities.h in Headers */, B2E0D7B1245B0B5C003C5B48 /* Matter.h in Headers */, @@ -1882,6 +1895,7 @@ 9B231B042C62EF650030EB37 /* (null) in Headers */, 515BE4ED2B72C0C5000BC1FD /* MTRUnfairLock.h in Headers */, 998F286F26D55EC5001846C6 /* MTRP256KeypairBridge.h in Headers */, + CF3B63CF2CA31E71003C1C87 /* MTROTAImageTransferHandler.h in Headers */, 2C222ADF255C811800E446B9 /* MTRBaseDevice_Internal.h in Headers */, 514C7A022B64223400DD6D7B /* MTRServerEndpoint_Internal.h in Headers */, 511913FC28C100EF009235E9 /* MTRBaseSubscriptionCallback.h in Headers */, @@ -2163,6 +2177,7 @@ 997DED162695343400975E97 /* MTRThreadOperationalDataset.mm in Sources */, 515C1C6F284F9FFB00A48F0C /* MTRFramework.mm in Sources */, 51029DF6293AA6100087AFB0 /* MTROperationalCertificateIssuer.mm in Sources */, + CF3B63D22CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.mm in Sources */, 27A53C1827FBC6920053F131 /* MTRAttestationTrustStoreBridge.mm in Sources */, 7592BCF62CBEE98C00EB74A0 /* CodegenDataModelProvider_Read.cpp in Sources */, 7592BCF72CBEE98C00EB74A0 /* Instance.cpp in Sources */, @@ -2202,6 +2217,7 @@ 1EC4CE5D25CC26E900D7304F /* MTRBaseClusters.mm in Sources */, 514C79F62B62F0B900DD6D7B /* util.cpp in Sources */, 51565CB22A7AD77600469F18 /* MTRDeviceControllerDataStore.mm in Sources */, + CF3B63D12CA31E71003C1C87 /* MTROTAImageTransferHandler.mm in Sources */, 51D0B12F2B617800006E3511 /* MTRAccessGrant.mm in Sources */, 88E6C9482B6334ED001A1FE0 /* MTRMetrics.mm in Sources */, 1ED276E226C5812A00547A89 /* MTRCluster.mm in Sources */, diff --git a/src/platform/Ameba/SystemTimeSupport.cpp b/src/platform/Ameba/SystemTimeSupport.cpp index acf451d49858ab..8a5f59131d6632 100644 --- a/src/platform/Ameba/SystemTimeSupport.cpp +++ b/src/platform/Ameba/SystemTimeSupport.cpp @@ -58,26 +58,32 @@ Milliseconds64 ClockImpl::GetMonotonicMilliseconds64(void) CHIP_ERROR ClockImpl::GetClock_RealTime(Clock::Microseconds64 & curTime) { - // TODO(19081): This platform does not properly error out if wall clock has - // not been set. For now, short circuit this. - return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; -#if 0 - time_t seconds; - struct rtkTimeVal tv; +#if CONFIG_ENABLE_AMEBA_SNTP + time_t seconds = 0, uSeconds = 0; - seconds = matter_rtc_read(); - - tv.tv_sec = (uint32_t) seconds; - tv.tv_usec = 0; + if (matter_sntp_rtc_is_sync()) // if RTC is already sync with SNTP, read directly from RTC + { + seconds = matter_rtc_read(); // ameba rtc precission is in seconds only + } + else // read from SNTP and sync RTC with SNTP + { + matter_sntp_get_current_time(&seconds, &uSeconds); + } - if (tv.tv_sec < CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD) + if (seconds < CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD) { return CHIP_ERROR_REAL_TIME_NOT_SYNCED; } - static_assert(CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD >= 0, "We might be letting through negative tv_sec values!"); - curTime = Microseconds64((static_cast(tv.tv_sec) * UINT64_C(1000000)) + static_cast(tv.tv_usec)); + if (uSeconds < 0) + { + return CHIP_ERROR_REAL_TIME_NOT_SYNCED; + } + static_assert(CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD >= 0, "We might be letting through negative uSeconds values!"); + curTime = Microseconds64((static_cast(seconds) * UINT64_C(1000000)) + static_cast(uSeconds)); return CHIP_NO_ERROR; +#else + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; #endif } @@ -105,9 +111,16 @@ CHIP_ERROR InitClock_RealTime() Clock::Microseconds64((static_cast(CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD) * UINT64_C(1000000))); // Use CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD as the initial value of RealTime. // Then the RealTime obtained from GetClock_RealTime will be always valid. - // - // TODO(19081): This is broken because it causes the platform to report - // that it does have wall clock time when it actually doesn't. +#if CONFIG_ENABLE_AMEBA_SNTP + time_t seconds = 0, uSeconds = 0; + + matter_sntp_init(); + matter_sntp_get_current_time(&seconds, &uSeconds); // try to read from SNTP and sync RTC with SNTP + if ((seconds > CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD) && (uSeconds > 0)) + { + curTime = Microseconds64((static_cast(seconds) * UINT64_C(1000000)) + static_cast(uSeconds)); + } +#endif return System::SystemClock().SetClock_RealTime(curTime); } diff --git a/src/platform/Darwin/BleConnectionDelegateImpl.mm b/src/platform/Darwin/BleConnectionDelegateImpl.mm index b0c1e2ef70a4bb..7b5d68bab13523 100644 --- a/src/platform/Darwin/BleConnectionDelegateImpl.mm +++ b/src/platform/Darwin/BleConnectionDelegateImpl.mm @@ -447,6 +447,7 @@ - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPerip MATTER_LOG_METRIC_BEGIN(kMetricBLEDiscoveredServices); [peripheral setDelegate:self]; [peripheral discoverServices:nil]; + [self stopScanning]; } // End CBCentralManagerDelegate @@ -734,7 +735,7 @@ - (void)updateWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscrimi MATTER_LOG_METRIC_BEGIN(kMetricBLEDiscoveredMatchingPeripheral); ChipLogProgress(Ble, "Connecting to cached device: %p", peripheral); [self connect:peripheral]; - [self stopScanning]; + // The cached peripheral might be obsolete, so continue scanning until didConnectPeripheral is triggered. } else { [self setupTimer:kScanningWithDiscriminatorTimeoutInSeconds]; } diff --git a/src/platform/ESP32/ESP32SecureCertDataProvider.cpp b/src/platform/ESP32/ESP32SecureCertDataProvider.cpp index e3bb02155bfc9b..c464c07c659e23 100644 --- a/src/platform/ESP32/ESP32SecureCertDataProvider.cpp +++ b/src/platform/ESP32/ESP32SecureCertDataProvider.cpp @@ -21,8 +21,8 @@ #include #include +#include #include -#include #include namespace chip { diff --git a/src/platform/Linux/BLEManagerImpl.cpp b/src/platform/Linux/BLEManagerImpl.cpp index 4ef45f88ea60fa..9f285e6192df9a 100644 --- a/src/platform/Linux/BLEManagerImpl.cpp +++ b/src/platform/Linux/BLEManagerImpl.cpp @@ -186,9 +186,8 @@ uint16_t BLEManagerImpl::_NumConnections() CHIP_ERROR BLEManagerImpl::ConfigureBle(uint32_t aAdapterId, bool aIsCentral) { - mAdapterId = aAdapterId; - mIsCentral = aIsCentral; - mpBLEAdvUUID = "0xFFF6"; + mAdapterId = aAdapterId; + mIsCentral = aIsCentral; return CHIP_NO_ERROR; } @@ -578,7 +577,7 @@ void BLEManagerImpl::DriveBLEState() // Configure advertising data if it hasn't been done yet. if (!mFlags.Has(Flags::kAdvertisingConfigured)) { - SuccessOrExit(err = mBLEAdvertisement.Init(mAdapter.get(), mpBLEAdvUUID, mDeviceName)); + SuccessOrExit(err = mBLEAdvertisement.Init(mAdapter.get(), Ble::CHIP_BLE_SERVICE_SHORT_UUID_STR, mDeviceName)); mFlags.Set(Flags::kAdvertisingConfigured); } diff --git a/src/platform/Linux/BLEManagerImpl.h b/src/platform/Linux/BLEManagerImpl.h index e216a09b8e46f1..d4aeaa3b8998aa 100644 --- a/src/platform/Linux/BLEManagerImpl.h +++ b/src/platform/Linux/BLEManagerImpl.h @@ -199,7 +199,6 @@ class BLEManagerImpl final : public BLEManager, BluezEndpoint mEndpoint{ mBluezObjectManager }; BluezAdvertisement mBLEAdvertisement{ mEndpoint }; - const char * mpBLEAdvUUID = nullptr; ChipDeviceScanner mDeviceScanner{ mBluezObjectManager }; BLEScanConfig mBLEScanConfig; diff --git a/src/platform/Linux/bluez/BluezObjectManager.cpp b/src/platform/Linux/bluez/BluezObjectManager.cpp index 2d555edc562be8..3a694dd64601d3 100644 --- a/src/platform/Linux/bluez/BluezObjectManager.cpp +++ b/src/platform/Linux/bluez/BluezObjectManager.cpp @@ -62,6 +62,11 @@ CHIP_ERROR BluezObjectManager::Init() void BluezObjectManager::Shutdown() { + // If the D-Bus connection or the object manager are not initialized, + // there is nothing to shutdown. This check prevents unnecessary call + // to the GLibMatterContextInvokeSync function. + VerifyOrReturn(mConnection || mObjectManager); + // Run endpoint cleanup on the CHIPoBluez thread. This is necessary because the // cleanup function releases the D-Bus manager client object, which handles D-Bus // signals. Otherwise, we will face race condition when the D-Bus signal is in diff --git a/src/platform/NuttX/BLEManagerImpl.cpp b/src/platform/NuttX/BLEManagerImpl.cpp index 6672b5d4bdd295..b8d7c64d0004b1 100644 --- a/src/platform/NuttX/BLEManagerImpl.cpp +++ b/src/platform/NuttX/BLEManagerImpl.cpp @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include #include @@ -197,9 +197,8 @@ uint16_t BLEManagerImpl::_NumConnections() CHIP_ERROR BLEManagerImpl::ConfigureBle(uint32_t aAdapterId, bool aIsCentral) { - mAdapterId = aAdapterId; - mIsCentral = aIsCentral; - mpBLEAdvUUID = "0xFFF6"; + mAdapterId = aAdapterId; + mIsCentral = aIsCentral; return CHIP_NO_ERROR; } @@ -587,7 +586,7 @@ void BLEManagerImpl::DriveBLEState() // Configure advertising data if it hasn't been done yet. if (!mFlags.Has(Flags::kAdvertisingConfigured)) { - SuccessOrExit(err = mBLEAdvertisement.Init(mEndpoint, mpBLEAdvUUID, mDeviceName)); + SuccessOrExit(err = mBLEAdvertisement.Init(mEndpoint, Ble::CHIP_BLE_SERVICE_SHORT_UUID_STR, mDeviceName)); mFlags.Set(Flags::kAdvertisingConfigured); } diff --git a/src/platform/NuttX/BLEManagerImpl.h b/src/platform/NuttX/BLEManagerImpl.h index f6f6db6c3a3b3f..e8aca8b7c7b304 100644 --- a/src/platform/NuttX/BLEManagerImpl.h +++ b/src/platform/NuttX/BLEManagerImpl.h @@ -189,7 +189,6 @@ class BLEManagerImpl final : public BLEManager, BluezEndpoint mEndpoint; BluezAdvertisement mBLEAdvertisement; - const char * mpBLEAdvUUID = nullptr; ChipDeviceScanner mDeviceScanner; BLEScanConfig mBLEScanConfig; diff --git a/src/platform/nxp/common/DnssdImpl.cpp b/src/platform/nxp/common/DnssdImpl.cpp index 5b35693534059f..65061aa80c4266 100644 --- a/src/platform/nxp/common/DnssdImpl.cpp +++ b/src/platform/nxp/common/DnssdImpl.cpp @@ -99,7 +99,7 @@ CHIP_ERROR ChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, chi chip::Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context, intptr_t * browseIdentifier) { - if (ConnectivityMgr().IsWiFiStationConnected()) //|| ESP32Utils::HasIPv6LinkLocalAddress(ESP32Utils::kDefaultEthernetNetifKey)) + if (ConnectivityMgr().IsWiFiStationConnected()) { ReturnErrorOnFailure(NxpChipDnssdBrowse(type, protocol, addressType, interface, callback, context, browseIdentifier)); } @@ -119,7 +119,7 @@ CHIP_ERROR ChipDnssdStopBrowse(intptr_t browseIdentifier) CHIP_ERROR ChipDnssdResolve(DnssdService * service, chip::Inet::InterfaceId interface, DnssdResolveCallback callback, void * context) { - if (ConnectivityMgr().IsWiFiStationConnected()) //|| ESP32Utils::HasIPv6LinkLocalAddress(ESP32Utils::kDefaultEthernetNetifKey)) + if (ConnectivityMgr().IsWiFiStationConnected()) { ReturnErrorOnFailure(NxpChipDnssdResolve(service, interface, callback, context)); } diff --git a/src/platform/nxp/common/DnssdImplBr.cpp b/src/platform/nxp/common/DnssdImplBr.cpp index 5eab86fe197963..e65ae2d5ef331b 100644 --- a/src/platform/nxp/common/DnssdImplBr.cpp +++ b/src/platform/nxp/common/DnssdImplBr.cpp @@ -28,6 +28,8 @@ #include #include +#include + using namespace ::chip::DeviceLayer; using namespace chip::DeviceLayer::Internal; @@ -363,6 +365,11 @@ CHIP_ERROR NxpChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, if (type == nullptr || callback == nullptr) return CHIP_ERROR_INVALID_ARGUMENT; + if (mBrowseContext != nullptr) + { + NxpChipDnssdStopBrowse(reinterpret_cast(mBrowseContext)); + } + mBrowseContext = Platform::New(context, callback); VerifyOrReturnError(mBrowseContext != nullptr, CHIP_ERROR_NO_MEMORY); @@ -412,7 +419,8 @@ CHIP_ERROR NxpChipDnssdStopBrowse(intptr_t browseIdentifier) // that has been freed in DispatchBrowseEmpty. if ((true == bBrowseInProgress) && (browseContext)) { - browseContext->error = MapOpenThreadError(otMdnsStopBrowser(thrInstancePtr, &browseContext->mBrowseInfo)); + error = otMdnsStopBrowser(thrInstancePtr, &browseContext->mBrowseInfo); + browseContext->error = MapOpenThreadError(error); // browse context will be freed in DispatchBrowseEmpty DispatchBrowseEmpty(reinterpret_cast(browseContext)); @@ -430,6 +438,13 @@ CHIP_ERROR NxpChipDnssdResolve(DnssdService * browseResult, Inet::InterfaceId in otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); + if (mResolveContext != nullptr) + { + // In case there is an ongoing query and NxpChipDnssdResolveNoLongerNeeded has not been called yet + // free the allocated context and do a proper cleanup of the previous transaction + NxpChipDnssdResolveNoLongerNeeded(mResolveContext->mMdnsService.mName); + } + mResolveContext = Platform::New(context, callback); VerifyOrReturnError(mResolveContext != nullptr, CHIP_ERROR_NO_MEMORY); @@ -450,12 +465,16 @@ CHIP_ERROR NxpChipDnssdResolve(DnssdService * browseResult, Inet::InterfaceId in mResolveContext->mSrvInfo.mServiceInstance = mResolveContext->mMdnsService.mName; mResolveContext->mSrvInfo.mServiceType = mResolveContext->mServiceType; - return MapOpenThreadError(otMdnsStartSrvResolver(thrInstancePtr, &mResolveContext->mSrvInfo)); + error = MapOpenThreadError(otMdnsStartSrvResolver(thrInstancePtr, &mResolveContext->mSrvInfo)); } - else + + if (error != CHIP_NO_ERROR) { - return error; + Platform::Delete(mResolveContext); + mResolveContext = nullptr; } + + return error; } void NxpChipDnssdResolveNoLongerNeeded(const char * instanceName) { diff --git a/src/platform/nxp/k32w0/KeyValueStoreManagerImpl.cpp b/src/platform/nxp/k32w0/KeyValueStoreManagerImpl.cpp index 34666e491ab43e..0ba86d0c4bb967 100644 --- a/src/platform/nxp/k32w0/KeyValueStoreManagerImpl.cpp +++ b/src/platform/nxp/k32w0/KeyValueStoreManagerImpl.cpp @@ -130,35 +130,19 @@ CHIP_ERROR KeyValueStoreManagerImpl::Init() CHIP_ERROR err = CHIP_NO_ERROR; err = sKeysStorage.Init(Internal::RamStorage::kRamBufferInitialSize); - if (err != CHIP_NO_ERROR) - { - ChipLogProgress(DeviceLayer, "Cannot init KVS keys storage with id: %d. Error: %s", kNvmId_KvsKeys, ErrorStr(err)); - } + ReturnErrorOnFailure(err); err = sValuesStorage.Init(Internal::RamStorage::kRamBufferInitialSize, true); - if (err != CHIP_NO_ERROR) - { - ChipLogProgress(DeviceLayer, "Cannot init KVS values storage with id: %d. Error: %s", kNvmId_KvsValues, ErrorStr(err)); - } + ReturnErrorOnFailure(err); err = sSubscriptionStorage.Init(Internal::RamStorage::kRamBufferInitialSize); - if (err != CHIP_NO_ERROR) - { - ChipLogProgress(DeviceLayer, "Cannot init KVS subscription storage with id: %d. Error: %s", kNvmId_KvsSubscription, - ErrorStr(err)); - } + ReturnErrorOnFailure(err); err = sGroupsStorage.Init(Internal::RamStorage::kRamBufferInitialSize, true); - if (err != CHIP_NO_ERROR) - { - ChipLogProgress(DeviceLayer, "Cannot init KVS groups storage with id: %d. Error: %s", kNvmId_KvsGroups, ErrorStr(err)); - } + ReturnErrorOnFailure(err); err = sAclStorage.Init(Internal::RamStorage::kRamBufferInitialSize, true); - if (err != CHIP_NO_ERROR) - { - ChipLogProgress(DeviceLayer, "Cannot init KVS acl storage with id: %d. Error: %s", kNvmId_KvsAcl, ErrorStr(err)); - } + ReturnErrorOnFailure(err); #if CONFIG_CHIP_K32W0_KVS_MOVE_KEYS_TO_SPECIFIC_STORAGE ChipLogProgress(DeviceLayer, "Moving some keys to dedicated storage"); diff --git a/src/platform/nxp/mcxw71_k32w1/args.gni b/src/platform/nxp/mcxw71_k32w1/args.gni index 7ec8fdf3d56e57..50cfbaba96ecb3 100644 --- a/src/platform/nxp/mcxw71_k32w1/args.gni +++ b/src/platform/nxp/mcxw71_k32w1/args.gni @@ -21,7 +21,6 @@ openthread_root = nxp_platform = "mcxw71_k32w1" nxp_sdk_name = "mcxw71_k32w1_sdk" nxp_device_layer = "nxp/${nxp_platform}" -nxp_nvm_component = "nvs" nxp_use_lwip = false # ARM architecture flags will be set based on NXP board. diff --git a/src/platform/telink/CHIPDevicePlatformConfig.h b/src/platform/telink/CHIPDevicePlatformConfig.h index 989b9b2aaf3705..655ac128953bee 100644 --- a/src/platform/telink/CHIPDevicePlatformConfig.h +++ b/src/platform/telink/CHIPDevicePlatformConfig.h @@ -108,6 +108,12 @@ #define CHIP_DEVICE_CONFIG_ENABLE_ETHERNET 0 #endif // CHIP_DEVICE_CONFIG_ENABLE_ETHERNET +#if defined(CONFIG_SOC_RISCV_TELINK_TL321X) || defined(CONFIG_SOC_SERIES_RISCV_TELINK_B9X_RETENTION) +#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_CRIT_BUFFER_SIZE (256) +#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_INFO_BUFFER_SIZE (256) +#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (256) +#endif + #ifdef CONFIG_BT #define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE CONFIG_BT #else diff --git a/src/platform/telink/CHIPPlatformConfig.h b/src/platform/telink/CHIPPlatformConfig.h index edd68b95380a84..27b2104c2480c6 100644 --- a/src/platform/telink/CHIPPlatformConfig.h +++ b/src/platform/telink/CHIPPlatformConfig.h @@ -62,7 +62,19 @@ #define CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS 1 #endif // CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS -#ifdef CONFIG_PM +#ifdef CONFIG_SOC_RISCV_TELINK_TL321X + +#ifndef CHIP_CONFIG_MAX_GROUP_DATA_PEERS +#define CHIP_CONFIG_MAX_GROUP_DATA_PEERS 5 +#endif // CHIP_CONFIG_MAX_GROUP_DATA_PEERS + +#ifndef CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_ENTRIES_PER_FABRIC +#define CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_ENTRIES_PER_FABRIC 4 +#endif // CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_ENTRIES_PER_FABRIC + +#endif // CONFIG_SOC_RISCV_TELINK_TL321X + +#if defined CONFIG_PM || defined CONFIG_SOC_RISCV_TELINK_TL321X #ifndef CHIP_CONFIG_MAX_GROUP_DATA_PEERS #define CHIP_CONFIG_MAX_GROUP_DATA_PEERS 7 @@ -96,7 +108,7 @@ #define CHIP_CONFIG_DEVICE_MAX_ACTIVE_DEVICES 2 #endif // CHIP_CONFIG_DEVICE_MAX_ACTIVE_DEVICES -#endif // CONFIG_PM +#endif // CONFIG_PM || CONFIG_SOC_RISCV_TELINK_TL321X #ifndef CHIP_CONFIG_MAX_FABRICS #define CHIP_CONFIG_MAX_FABRICS 5 diff --git a/src/platform/telink/SystemPlatformConfig.h b/src/platform/telink/SystemPlatformConfig.h index 5a7b56e9afb5fd..9f77a54b223169 100644 --- a/src/platform/telink/SystemPlatformConfig.h +++ b/src/platform/telink/SystemPlatformConfig.h @@ -44,11 +44,18 @@ struct ChipDeviceEvent; #define CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_TIME 1 #endif // CHIP_SYSTEM_CONFIG_USE_POSIX_TIME_FUNCTS +#if defined(CONFIG_SOC_RISCV_TELINK_TL321X) || defined(CONFIG_SOC_SERIES_RISCV_TELINK_B9X_RETENTION) +#define CHIP_SYSTEM_PACKETBUFFER_FROM_CHIP_HEAP 1 +#define CHIP_SYSTEM_PACKETBUFFER_FROM_CHIP_POOL 0 +#define CHIP_SYSTEM_CONFIG_POOL_USE_HEAP 1 +#define CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX 1280 +#endif + #define CHIP_SYSTEM_CONFIG_USE_LWIP 0 #define CHIP_SYSTEM_CONFIG_USE_SOCKETS 1 // Reduce packet buffer pool size (default 15) to reduce ram consumption -#ifdef CONFIG_PM +#if defined CONFIG_PM || defined CONFIG_SOC_RISCV_TELINK_TL321X #define CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE 0 #else #define CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE 8 diff --git a/src/platform/telink/tl3218x.overlay b/src/platform/telink/tl3218x.overlay new file mode 100644 index 00000000000000..4c74bb14ea216c --- /dev/null +++ b/src/platform/telink/tl3218x.overlay @@ -0,0 +1,61 @@ +/ { + /* Short TL_Key3 (J6 pin 21) to ground */ + key_pool { + compatible = "gpio-keys"; + + inp { + gpios = <&gpiob 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&gpiob 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + }; + + key_matrix { + compatible = "gpio-keys"; + + col { + gpios = <&gpiob 6 GPIO_ACTIVE_HIGH>, + <&gpiob 7 GPIO_ACTIVE_HIGH>; + }; + + row { + gpios = <&gpiob 3 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, + <&gpiob 5 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; + }; + }; + + led_pool { + compatible = "gpio-leds"; + + out { + gpios = <&gpiod 0 GPIO_ACTIVE_HIGH>; + }; + }; + + pwm_pool { + compatible = "pwm-leds"; + out { + pwms = <&pwm0 2 PWM_MSEC(20) PWM_POLARITY_NORMAL>, + <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>, + <&pwm0 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + }; +}; + +&pwm0 { + /* On board RGB LEDs */ + pinctrl-ch0 = <&pwm_ch0_pb1_default>; + pinctrl-ch2 = <&pwm_ch1_pb2_default>; + pinctrl-ch1 = <&pwm_ch2_pb0_default>; +}; + +&pinctrl { + pwm_ch0_pb1_default: pwm_ch0_pb1_default { + pinmux = ; + }; + pwm_ch1_pb2_default: pwm_ch1_pb2_default { + pinmux = ; + }; + pwm_ch2_pb0_default: pwm_ch2_pb0_default { + pinmux = ; + }; +}; diff --git a/src/platform/telink/tl3218x_2m_flash.overlay b/src/platform/telink/tl3218x_2m_flash.overlay new file mode 100644 index 00000000000000..53114e6ac6054d --- /dev/null +++ b/src/platform/telink/tl3218x_2m_flash.overlay @@ -0,0 +1,39 @@ +&flash { + reg = <0x20000000 0x200000>; + + /delete-node/ partitions; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x13000>; + }; + slot0_partition: partition@13000 { + label = "image-0"; + reg = <0x13000 0xef000>; + }; + factory_partition: partition@102000 { + label = "factory-data"; + reg = <0x102000 0x800>; + }; + factory_rfu_partition: partition@102800 { + label = "factory-data-rfu"; + reg = <0x102800 0x800>; + }; + storage_partition: partition@103000 { + label = "storage"; + reg = <0x103000 0xc000>; + }; + slot1_partition: partition@10f000 { + label = "image-1"; + reg = <0x10f000 0xef000>; + }; + vendor_partition: partition@1fe000 { + label = "vendor-data"; + reg = <0x1fe000 0x2000>; + }; + }; +}; diff --git a/src/protocols/bdx/AsyncTransferFacilitator.cpp b/src/protocols/bdx/AsyncTransferFacilitator.cpp new file mode 100644 index 00000000000000..2e3a0f03794319 --- /dev/null +++ b/src/protocols/bdx/AsyncTransferFacilitator.cpp @@ -0,0 +1,196 @@ +/* + * 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. + */ + +#include "AsyncTransferFacilitator.h" + +#include +#include + +namespace chip { +namespace bdx { + +AsyncTransferFacilitator::~AsyncTransferFacilitator() {} + +CHIP_ERROR AsyncTransferFacilitator::Init(System::Layer * layer, Messaging::ExchangeContext * exchangeCtx, + System::Clock::Timeout timeout) +{ + VerifyOrReturnError(layer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(exchangeCtx != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(!mExchange, CHIP_ERROR_INCORRECT_STATE); + + mSystemLayer = layer; + mExchange.Grab(exchangeCtx); + mTimeout = timeout; + mProcessingOutputEvents = false; + mDestroySelfAfterProcessingEvents = false; + return CHIP_NO_ERROR; +} + +/** + * Get events one by one from the TransferSession and process them, + * until there are no more events to process. + */ +void AsyncTransferFacilitator::ProcessOutputEvents() +{ + if (mProcessingOutputEvents) + { + ChipLogDetail(BDX, + "ProcessOutputEvents: we are already in the middle of processing events, so nothing to do here; when we " + "unwind to the processing loop the events will get processed."); + return; + } + + mProcessingOutputEvents = true; + + // Get the next output event and handle it based on the type of event. + // If its of type kMsgToSend send it over the exchange, otherwise call the HandleTransferSessionOutput + // virtual method that must be implemeted by the subclass of this class to handle the BDX message. + TransferSession::OutputEvent outEvent; + + mTransfer.GetNextAction(outEvent); + while (outEvent.EventType != TransferSession::OutputEventType::kNone) + { + if (outEvent.EventType == TransferSession::OutputEventType::kMsgToSend) + { + CHIP_ERROR err = SendMessage(outEvent.msgTypeData, outEvent.MsgData); + + // If we failed to send the message across the exchange, just abort the transfer. + // We have no way to notify our peer we are doing that (we can't send them a + // message!) but eventually they will time out. + if (err != CHIP_NO_ERROR) + { + DestroySelf(); + return; + } + + // If we send out a status report across the exchange, that means there was an error. + // We've sent our report about that error and can now abort the transfer. Our peer + // will respond to the status report by tearing down their side. + if (outEvent.msgTypeData.HasMessageType(Protocols::SecureChannel::MsgType::StatusReport)) + { + mDestroySelfAfterProcessingEvents = true; + break; + } + } + else + { + HandleTransferSessionOutput(outEvent); + } + mTransfer.GetNextAction(outEvent); + } + + mProcessingOutputEvents = false; + + // If mDestroySelfAfterProcessingEvents is set (by our code above or by NotifyEventHandled), we need + // to call DestroySelf() after processing all pending output events. + if (mDestroySelfAfterProcessingEvents) + { + DestroySelf(); + } +} + +CHIP_ERROR AsyncTransferFacilitator::SendMessage(const TransferSession::MessageTypeData msgTypeData, + System::PacketBufferHandle & msgBuf) +{ + VerifyOrReturnError(mExchange, CHIP_ERROR_INCORRECT_STATE); + + Messaging::SendFlags sendFlags; + + // All messages that are sent expect a response, except for a StatusReport which would indicate an error and + // the end of the transfer. + if (!msgTypeData.HasMessageType(Protocols::SecureChannel::MsgType::StatusReport)) + { + sendFlags.Set(Messaging::SendMessageFlags::kExpectResponse); + } + + Messaging::ExchangeContext * ec = mExchange.Get(); + + // Set the response timeout on the exchange before sending the message. + ec->SetResponseTimeout(mTimeout); + return ec->SendMessage(msgTypeData.ProtocolId, msgTypeData.MessageType, std::move(msgBuf), sendFlags); +} + +CHIP_ERROR AsyncTransferFacilitator::OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader, + System::PacketBufferHandle && payload) +{ + VerifyOrReturnError(mExchange, CHIP_ERROR_INCORRECT_STATE); + + VerifyOrReturnError(ec == mExchange.Get(), CHIP_ERROR_INCORRECT_STATE); + + CHIP_ERROR err = + mTransfer.HandleMessageReceived(payloadHeader, std::move(payload), System::SystemClock().GetMonotonicTimestamp()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(BDX, "OnMessageReceived: Failed to handle message: %" CHIP_ERROR_FORMAT, err.Format()); + + // This should notify the transfer object to abort transfer so it can send a status report across the exchange + // when we call ProcessOutputEvents below. + mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(err)); + } + else if (!payloadHeader.HasMessageType(MessageType::BlockAckEOF)) + { + // Almost every BDX message expect BlockAckEOF will follow up with a response on the exchange. + ec->WillSendMessage(); + } + + ProcessOutputEvents(); + return err; +} + +void AsyncTransferFacilitator::OnResponseTimeout(Messaging::ExchangeContext * ec) +{ + ChipLogDetail(BDX, "OnResponseTimeout, ec: " ChipLogFormatExchange, ChipLogValueExchange(ec)); + DestroySelf(); +} + +CHIP_ERROR AsyncResponder::Init(System::Layer * layer, Messaging::ExchangeContext * exchangeCtx, TransferRole role, + BitFlags xferControlOpts, uint16_t maxBlockSize, + System::Clock::Timeout timeout) +{ + ReturnErrorOnFailure(AsyncTransferFacilitator::Init(layer, exchangeCtx, timeout)); + ReturnErrorOnFailure(mTransfer.WaitForTransfer(role, xferControlOpts, maxBlockSize, timeout)); + return CHIP_NO_ERROR; +} + +void AsyncResponder::NotifyEventHandled(const TransferSession::OutputEventType eventType, CHIP_ERROR status) +{ + ChipLogDetail(BDX, "NotifyEventHandled : Event %s Error %" CHIP_ERROR_FORMAT, + TransferSession::OutputEvent::TypeToString(eventType), status.Format()); + + // If this is the end of the transfer (whether a clean end, or some sort of error condition), ensure that + // we destroy ourselves after processing any output events that might have been generated by + // the transfer session to handle end-of-transfer (e.g. in some error conditions it might want to send + // out a status report). + if (eventType == TransferSession::OutputEventType::kAckEOFReceived || + eventType == TransferSession::OutputEventType::kInternalError || + eventType == TransferSession::OutputEventType::kTransferTimeout || + eventType == TransferSession::OutputEventType::kStatusReceived) + { + mDestroySelfAfterProcessingEvents = true; + } + + // If there was an error handling the output event, this should notify the transfer object to abort transfer so it can send a + // status report across the exchange when we call ProcessOutputEvents below. + if (status != CHIP_NO_ERROR) + { + mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(status)); + } + + ProcessOutputEvents(); +} + +} // namespace bdx +} // namespace chip diff --git a/src/protocols/bdx/AsyncTransferFacilitator.h b/src/protocols/bdx/AsyncTransferFacilitator.h new file mode 100644 index 00000000000000..1ad95d39e98d2d --- /dev/null +++ b/src/protocols/bdx/AsyncTransferFacilitator.h @@ -0,0 +1,139 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include + +#pragma once + +namespace chip { +namespace bdx { + +/** + * An abstract class with methods for receiving and sending BDX messages on an ExchangeContext. It interacts with the Transfer + * Session state machine to process the received messages and send any outgoing messages. + * Note: If the relevant fabric shuts down, it is the responsibility of the subclass that implements HandleTransferSessionOutput + * to destroy itself (and hence this object). + * + * This class does not define any methods for beginning a transfer or initializing the underlying TransferSession object. + * See AsyncResponder for a class that does. + * TODO: # 29334 - Add AsyncInitiator to handle the initiating side of a transfer. + * + * An AsyncTransferFacilitator is associated with a specific BDX transfer. + */ +class AsyncTransferFacilitator : public Messaging::ExchangeDelegate +{ +public: + AsyncTransferFacilitator() : mExchange(*this) {} + ~AsyncTransferFacilitator() override; + +protected: + CHIP_ERROR Init(System::Layer * layer, Messaging::ExchangeContext * exchangeCtx, System::Clock::Timeout timeout); + + // If subclasses override this method and they call the superclass's OnMessageReceived, the superclass + // may destroy the subclass's object before OnMessageReceived returns. + CHIP_ERROR OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader, + System::PacketBufferHandle && payload) override; + + // If subclasses override this method and they call the superclass's OnResponseTimeout, the superclass + // may destroy the subclass's object before OnResponseTimeout returns. + void OnResponseTimeout(Messaging::ExchangeContext * ec) override; + + /** + * This method should be implemented to contain business-logic handling of BDX messages + * and other TransferSession events. + * + * @param[in] event An OutputEvent that contains the output from the TransferSession object. + */ + virtual void HandleTransferSessionOutput(TransferSession::OutputEvent & event) = 0; + + /** + * This method should be implemented to destroy the object subclassing AsyncTransferFacilitator. + * + * This is a hook that is expected to be called by AsyncTransferFacilitator and allows subclasses + * to select an allocation strategy of their choice. + */ + virtual void DestroySelf() = 0; + + // Calling ProcessOutputEvents can destroy this object before the call returns. + void ProcessOutputEvents(); + + // The transfer session corresponding to this AsyncTransferFacilitator object. + TransferSession mTransfer; + + bool mDestroySelfAfterProcessingEvents = false; + +private: + bool mProcessingOutputEvents = false; + + // The Exchange holder that holds the exchange context used for sending and receiving BDX messages. + Messaging::ExchangeHolder mExchange; + + // The timeout for the BDX transfer session. + System::Clock::Timeout mTimeout; + + System::Layer * mSystemLayer; + + CHIP_ERROR SendMessage(const TransferSession::MessageTypeData msgTypeData, System::PacketBufferHandle & msgBuf); +}; + +/** + * An AsyncTransferFacilitator that is initialized to respond to an incoming BDX transfer request. + * An AsyncResponder object is associated with an exchange and handles all BDX messages sent over that exchange. + * + * Provides a method for initializing the TransferSession members but still needs to be extended to implement + * HandleTransferSessionOutput. + * + * An instance of some subclass of this class should be used as the exchange delegate for a BDX transfer. + */ +class AsyncResponder : public AsyncTransferFacilitator +{ +public: + /** + * Initialize the TransferSession state machine to be ready for an incoming transfer request. + * + * @param[in] exchangeCtx The exchange to use for the transfer. + * @param[in] role The role of the Responder: Sender or Receiver of BDX data + * @param[in] xferControlOpts Supported transfer modes (see TransferControlFlags) + * @param[in] maxBlockSize The maximum supported size of BDX Block data + * @param[in] timeout The chosen timeout delay for the BDX transfer + */ + CHIP_ERROR Init(System::Layer * layer, Messaging::ExchangeContext * exchangeCtx, TransferRole role, + BitFlags xferControlOpts, uint16_t maxBlockSize, System::Clock::Timeout timeout); + + /** + * Method that must be called by the subclass implementing HandleTransferSessionOutput to notify the AsyncResponder + * that it has handled the OutputEvent specified in "event" and "status" is the result of handling the event. + * + * Every call to HandleTransferSessionOutput must result in a call to NotifyEventHandled. The call + * to NotifyEventHandled may happen before HandleTransferSessionOutput returns, or may happen + * later, asynchronously. + + * Note: NotifyEventHandled is allowed to destroy the AsyncResponder before the call returns. + * Callers must be careful about this. + * + * @param[in] eventType The OutputEventType that was handled by the subclass. + * @param[in] status The error code that occured when handling the event if an error occurs. Otherwise CHIP_NO_ERROR. + */ + void NotifyEventHandled(const TransferSession::OutputEventType eventType, CHIP_ERROR status); +}; + +} // namespace bdx +} // namespace chip diff --git a/src/protocols/bdx/BUILD.gn b/src/protocols/bdx/BUILD.gn index a95fd02202f626..118410183f9508 100644 --- a/src/protocols/bdx/BUILD.gn +++ b/src/protocols/bdx/BUILD.gn @@ -18,6 +18,8 @@ static_library("bdx") { output_name = "libBdx" sources = [ + "AsyncTransferFacilitator.cpp", + "AsyncTransferFacilitator.h", "BdxMessages.cpp", "BdxMessages.h", "BdxTransferDiagnosticLog.cpp", diff --git a/src/protocols/bdx/BdxTransferSession.cpp b/src/protocols/bdx/BdxTransferSession.cpp index 89851493bad46c..fdf9bb2c848e54 100644 --- a/src/protocols/bdx/BdxTransferSession.cpp +++ b/src/protocols/bdx/BdxTransferSession.cpp @@ -916,6 +916,11 @@ bool TransferSession::IsTransferLengthDefinite() const } const char * TransferSession::OutputEvent::ToString(OutputEventType outputEventType) +{ + return TypeToString(outputEventType); +} + +const char * TransferSession::OutputEvent::TypeToString(OutputEventType outputEventType) { switch (outputEventType) { diff --git a/src/protocols/bdx/BdxTransferSession.h b/src/protocols/bdx/BdxTransferSession.h index 4a50e70fbb6c84..ecfcac66806a08 100644 --- a/src/protocols/bdx/BdxTransferSession.h +++ b/src/protocols/bdx/BdxTransferSession.h @@ -136,6 +136,8 @@ class DLL_EXPORT TransferSession const char * ToString(OutputEventType outputEventType); + static const char * TypeToString(OutputEventType outputEventType); + static OutputEvent TransferInitEvent(TransferInitData data, System::PacketBufferHandle msg); static OutputEvent TransferAcceptEvent(TransferAcceptData data); static OutputEvent TransferAcceptEvent(TransferAcceptData data, System::PacketBufferHandle msg); diff --git a/src/python_testing/TC_WHM_2_1.py b/src/python_testing/TC_WHM_2_1.py index b9dcb0257d1b1a..538450e5986c1c 100644 --- a/src/python_testing/TC_WHM_2_1.py +++ b/src/python_testing/TC_WHM_2_1.py @@ -26,7 +26,7 @@ # --discriminator 1234 # --KVS kvs1 # --trace-to json:${TRACE_APP}.json -# --application evse +# --application water-heater # script-args: > # --storage-path admin_storage.json # --commissioning-method on-network